aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorZhang, Yanmin <yanmin_zhang@linux.intel.com>2010-04-19 01:32:50 -0400
committerAvi Kivity <avi@redhat.com>2010-04-19 05:37:24 -0400
commita1645ce12adb6c9cc9e19d7695466204e3f017fe (patch)
tree5d31aaaf534997e6e9cebc07f38eca35f76986cf /tools/perf/util
parentff9d07a0e7ce756a183e7c2e483aec452ee6b574 (diff)
perf: 'perf kvm' tool for monitoring guest performance from host
Here is the patch of userspace perf tool. Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/event.c280
-rw-r--r--tools/perf/util/event.h10
-rw-r--r--tools/perf/util/header.c213
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/hist.c72
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/map.c139
-rw-r--r--tools/perf/util/map.h75
-rw-r--r--tools/perf/util/probe-event.c7
-rw-r--r--tools/perf/util/session.c77
-rw-r--r--tools/perf/util/session.h28
-rw-r--r--tools/perf/util/sort.h5
-rw-r--r--tools/perf/util/symbol.c382
-rw-r--r--tools/perf/util/symbol.h43
-rw-r--r--tools/perf/util/thread.h4
16 files changed, 1049 insertions, 292 deletions
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 04904b35ba81..0f60a3906808 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -24,7 +24,7 @@ static int build_id__mark_dso_hit(event_t *event, struct perf_session *session)
24 } 24 }
25 25
26 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 26 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
27 event->ip.ip, &al); 27 event->ip.pid, event->ip.ip, &al);
28 28
29 if (al.map != NULL) 29 if (al.map != NULL)
30 al.map->dso->hit = 1; 30 al.map->dso->hit = 1;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 571fb25f7eb9..e3fa8d3d11b4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -112,7 +112,11 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
112 event_t ev = { 112 event_t ev = {
113 .header = { 113 .header = {
114 .type = PERF_RECORD_MMAP, 114 .type = PERF_RECORD_MMAP,
115 .misc = 0, /* Just like the kernel, see kernel/perf_event.c __perf_event_mmap */ 115 /*
116 * Just like the kernel, see __perf_event_mmap
117 * in kernel/perf_event.c
118 */
119 .misc = PERF_RECORD_MISC_USER,
116 }, 120 },
117 }; 121 };
118 int n; 122 int n;
@@ -167,11 +171,23 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
167} 171}
168 172
169int event__synthesize_modules(event__handler_t process, 173int event__synthesize_modules(event__handler_t process,
170 struct perf_session *session) 174 struct perf_session *session,
175 struct kernel_info *kerninfo)
171{ 176{
172 struct rb_node *nd; 177 struct rb_node *nd;
178 struct map_groups *kmaps = &kerninfo->kmaps;
179 u16 misc;
173 180
174 for (nd = rb_first(&session->kmaps.maps[MAP__FUNCTION]); 181 /*
182 * kernel uses 0 for user space maps, see kernel/perf_event.c
183 * __perf_event_mmap
184 */
185 if (is_host_kernel(kerninfo))
186 misc = PERF_RECORD_MISC_KERNEL;
187 else
188 misc = PERF_RECORD_MISC_GUEST_KERNEL;
189
190 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
175 nd; nd = rb_next(nd)) { 191 nd; nd = rb_next(nd)) {
176 event_t ev; 192 event_t ev;
177 size_t size; 193 size_t size;
@@ -182,12 +198,13 @@ int event__synthesize_modules(event__handler_t process,
182 198
183 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 199 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
184 memset(&ev, 0, sizeof(ev)); 200 memset(&ev, 0, sizeof(ev));
185 ev.mmap.header.misc = 1; /* kernel uses 0 for user space maps, see kernel/perf_event.c __perf_event_mmap */ 201 ev.mmap.header.misc = misc;
186 ev.mmap.header.type = PERF_RECORD_MMAP; 202 ev.mmap.header.type = PERF_RECORD_MMAP;
187 ev.mmap.header.size = (sizeof(ev.mmap) - 203 ev.mmap.header.size = (sizeof(ev.mmap) -
188 (sizeof(ev.mmap.filename) - size)); 204 (sizeof(ev.mmap.filename) - size));
189 ev.mmap.start = pos->start; 205 ev.mmap.start = pos->start;
190 ev.mmap.len = pos->end - pos->start; 206 ev.mmap.len = pos->end - pos->start;
207 ev.mmap.pid = kerninfo->pid;
191 208
192 memcpy(ev.mmap.filename, pos->dso->long_name, 209 memcpy(ev.mmap.filename, pos->dso->long_name,
193 pos->dso->long_name_len + 1); 210 pos->dso->long_name_len + 1);
@@ -250,13 +267,18 @@ static int find_symbol_cb(void *arg, const char *name, char type, u64 start)
250 267
251int event__synthesize_kernel_mmap(event__handler_t process, 268int event__synthesize_kernel_mmap(event__handler_t process,
252 struct perf_session *session, 269 struct perf_session *session,
270 struct kernel_info *kerninfo,
253 const char *symbol_name) 271 const char *symbol_name)
254{ 272{
255 size_t size; 273 size_t size;
274 const char *filename, *mmap_name;
275 char path[PATH_MAX];
276 char name_buff[PATH_MAX];
277 struct map *map;
278
256 event_t ev = { 279 event_t ev = {
257 .header = { 280 .header = {
258 .type = PERF_RECORD_MMAP, 281 .type = PERF_RECORD_MMAP,
259 .misc = 1, /* kernel uses 0 for user space maps, see kernel/perf_event.c __perf_event_mmap */
260 }, 282 },
261 }; 283 };
262 /* 284 /*
@@ -266,16 +288,37 @@ int event__synthesize_kernel_mmap(event__handler_t process,
266 */ 288 */
267 struct process_symbol_args args = { .name = symbol_name, }; 289 struct process_symbol_args args = { .name = symbol_name, };
268 290
269 if (kallsyms__parse("/proc/kallsyms", &args, find_symbol_cb) <= 0) 291 mmap_name = kern_mmap_name(kerninfo, name_buff);
292 if (is_host_kernel(kerninfo)) {
293 /*
294 * kernel uses PERF_RECORD_MISC_USER for user space maps,
295 * see kernel/perf_event.c __perf_event_mmap
296 */
297 ev.header.misc = PERF_RECORD_MISC_KERNEL;
298 filename = "/proc/kallsyms";
299 } else {
300 ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
301 if (is_default_guest(kerninfo))
302 filename = (char *) symbol_conf.default_guest_kallsyms;
303 else {
304 sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir);
305 filename = path;
306 }
307 }
308
309 if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0)
270 return -ENOENT; 310 return -ENOENT;
271 311
312 map = kerninfo->vmlinux_maps[MAP__FUNCTION];
272 size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), 313 size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename),
273 "[kernel.kallsyms.%s]", symbol_name) + 1; 314 "%s%s", mmap_name, symbol_name) + 1;
274 size = ALIGN(size, sizeof(u64)); 315 size = ALIGN(size, sizeof(u64));
275 ev.mmap.header.size = (sizeof(ev.mmap) - (sizeof(ev.mmap.filename) - size)); 316 ev.mmap.header.size = (sizeof(ev.mmap) -
317 (sizeof(ev.mmap.filename) - size));
276 ev.mmap.pgoff = args.start; 318 ev.mmap.pgoff = args.start;
277 ev.mmap.start = session->vmlinux_maps[MAP__FUNCTION]->start; 319 ev.mmap.start = map->start;
278 ev.mmap.len = session->vmlinux_maps[MAP__FUNCTION]->end - ev.mmap.start ; 320 ev.mmap.len = map->end - ev.mmap.start;
321 ev.mmap.pid = kerninfo->pid;
279 322
280 return process(&ev, session); 323 return process(&ev, session);
281} 324}
@@ -329,22 +372,50 @@ int event__process_lost(event_t *self, struct perf_session *session)
329 return 0; 372 return 0;
330} 373}
331 374
332int event__process_mmap(event_t *self, struct perf_session *session) 375static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
376{
377 maps[MAP__FUNCTION]->start = self->mmap.start;
378 maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len;
379 /*
380 * Be a bit paranoid here, some perf.data file came with
381 * a zero sized synthesized MMAP event for the kernel.
382 */
383 if (maps[MAP__FUNCTION]->end == 0)
384 maps[MAP__FUNCTION]->end = ~0UL;
385}
386
387static int event__process_kernel_mmap(event_t *self,
388 struct perf_session *session)
333{ 389{
334 struct thread *thread;
335 struct map *map; 390 struct map *map;
391 char kmmap_prefix[PATH_MAX];
392 struct kernel_info *kerninfo;
393 enum dso_kernel_type kernel_type;
394 bool is_kernel_mmap;
395
396 kerninfo = kerninfo__findnew(&session->kerninfo_root, self->mmap.pid);
397 if (!kerninfo) {
398 pr_err("Can't find id %d's kerninfo\n", self->mmap.pid);
399 goto out_problem;
400 }
336 401
337 dump_printf(" %d/%d: [%#Lx(%#Lx) @ %#Lx]: %s\n", 402 kern_mmap_name(kerninfo, kmmap_prefix);
338 self->mmap.pid, self->mmap.tid, self->mmap.start, 403 if (is_host_kernel(kerninfo))
339 self->mmap.len, self->mmap.pgoff, self->mmap.filename); 404 kernel_type = DSO_TYPE_KERNEL;
405 else
406 kernel_type = DSO_TYPE_GUEST_KERNEL;
340 407
341 if (self->mmap.pid == 0) { 408 is_kernel_mmap = memcmp(self->mmap.filename,
342 static const char kmmap_prefix[] = "[kernel.kallsyms."; 409 kmmap_prefix,
410 strlen(kmmap_prefix)) == 0;
411 if (self->mmap.filename[0] == '/' ||
412 (!is_kernel_mmap && self->mmap.filename[0] == '[')) {
343 413
344 if (self->mmap.filename[0] == '/') { 414 char short_module_name[1024];
345 char short_module_name[1024]; 415 char *name, *dot;
346 char *name = strrchr(self->mmap.filename, '/'), *dot;
347 416
417 if (self->mmap.filename[0] == '/') {
418 name = strrchr(self->mmap.filename, '/');
348 if (name == NULL) 419 if (name == NULL)
349 goto out_problem; 420 goto out_problem;
350 421
@@ -352,59 +423,86 @@ int event__process_mmap(event_t *self, struct perf_session *session)
352 dot = strrchr(name, '.'); 423 dot = strrchr(name, '.');
353 if (dot == NULL) 424 if (dot == NULL)
354 goto out_problem; 425 goto out_problem;
355
356 snprintf(short_module_name, sizeof(short_module_name), 426 snprintf(short_module_name, sizeof(short_module_name),
357 "[%.*s]", (int)(dot - name), name); 427 "[%.*s]", (int)(dot - name), name);
358 strxfrchar(short_module_name, '-', '_'); 428 strxfrchar(short_module_name, '-', '_');
359 429 } else
360 map = perf_session__new_module_map(session, 430 strcpy(short_module_name, self->mmap.filename);
361 self->mmap.start, 431
362 self->mmap.filename); 432 map = map_groups__new_module(&kerninfo->kmaps,
363 if (map == NULL) 433 self->mmap.start,
364 goto out_problem; 434 self->mmap.filename,
365 435 kerninfo);
366 name = strdup(short_module_name); 436 if (map == NULL)
367 if (name == NULL) 437 goto out_problem;
368 goto out_problem; 438
369 439 name = strdup(short_module_name);
370 map->dso->short_name = name; 440 if (name == NULL)
371 map->end = map->start + self->mmap.len; 441 goto out_problem;
372 } else if (memcmp(self->mmap.filename, kmmap_prefix, 442
373 sizeof(kmmap_prefix) - 1) == 0) { 443 map->dso->short_name = name;
374 const char *symbol_name = (self->mmap.filename + 444 map->end = map->start + self->mmap.len;
375 sizeof(kmmap_prefix) - 1); 445 } else if (is_kernel_mmap) {
446 const char *symbol_name = (self->mmap.filename +
447 strlen(kmmap_prefix));
448 /*
449 * Should be there already, from the build-id table in
450 * the header.
451 */
452 struct dso *kernel = __dsos__findnew(&kerninfo->dsos__kernel,
453 kmmap_prefix);
454 if (kernel == NULL)
455 goto out_problem;
456
457 kernel->kernel = kernel_type;
458 if (__map_groups__create_kernel_maps(&kerninfo->kmaps,
459 kerninfo->vmlinux_maps, kernel) < 0)
460 goto out_problem;
461
462 event_set_kernel_mmap_len(kerninfo->vmlinux_maps, self);
463 perf_session__set_kallsyms_ref_reloc_sym(kerninfo->vmlinux_maps,
464 symbol_name,
465 self->mmap.pgoff);
466 if (is_default_guest(kerninfo)) {
376 /* 467 /*
377 * Should be there already, from the build-id table in 468 * preload dso of guest kernel and modules
378 * the header.
379 */ 469 */
380 struct dso *kernel = __dsos__findnew(&dsos__kernel, 470 dso__load(kernel,
381 "[kernel.kallsyms]"); 471 kerninfo->vmlinux_maps[MAP__FUNCTION],
382 if (kernel == NULL) 472 NULL);
383 goto out_problem; 473 }
384 474 }
385 kernel->kernel = 1; 475 return 0;
386 if (__perf_session__create_kernel_maps(session, kernel) < 0) 476out_problem:
387 goto out_problem; 477 return -1;
478}
388 479
389 session->vmlinux_maps[MAP__FUNCTION]->start = self->mmap.start; 480int event__process_mmap(event_t *self, struct perf_session *session)
390 session->vmlinux_maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len; 481{
391 /* 482 struct kernel_info *kerninfo;
392 * Be a bit paranoid here, some perf.data file came with 483 struct thread *thread;
393 * a zero sized synthesized MMAP event for the kernel. 484 struct map *map;
394 */ 485 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
395 if (session->vmlinux_maps[MAP__FUNCTION]->end == 0) 486 int ret = 0;
396 session->vmlinux_maps[MAP__FUNCTION]->end = ~0UL;
397 487
398 perf_session__set_kallsyms_ref_reloc_sym(session, symbol_name, 488 dump_printf(" %d/%d: [%#Lx(%#Lx) @ %#Lx]: %s\n",
399 self->mmap.pgoff); 489 self->mmap.pid, self->mmap.tid, self->mmap.start,
400 } 490 self->mmap.len, self->mmap.pgoff, self->mmap.filename);
491
492 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
493 cpumode == PERF_RECORD_MISC_KERNEL) {
494 ret = event__process_kernel_mmap(self, session);
495 if (ret < 0)
496 goto out_problem;
401 return 0; 497 return 0;
402 } 498 }
403 499
404 thread = perf_session__findnew(session, self->mmap.pid); 500 thread = perf_session__findnew(session, self->mmap.pid);
405 map = map__new(self->mmap.start, self->mmap.len, self->mmap.pgoff, 501 kerninfo = kerninfo__findhost(&session->kerninfo_root);
406 self->mmap.pid, self->mmap.filename, MAP__FUNCTION, 502 map = map__new(&kerninfo->dsos__user, self->mmap.start,
407 session->cwd, session->cwdlen); 503 self->mmap.len, self->mmap.pgoff,
504 self->mmap.pid, self->mmap.filename,
505 MAP__FUNCTION, session->cwd, session->cwdlen);
408 506
409 if (thread == NULL || map == NULL) 507 if (thread == NULL || map == NULL)
410 goto out_problem; 508 goto out_problem;
@@ -444,22 +542,52 @@ int event__process_task(event_t *self, struct perf_session *session)
444 542
445void thread__find_addr_map(struct thread *self, 543void thread__find_addr_map(struct thread *self,
446 struct perf_session *session, u8 cpumode, 544 struct perf_session *session, u8 cpumode,
447 enum map_type type, u64 addr, 545 enum map_type type, pid_t pid, u64 addr,
448 struct addr_location *al) 546 struct addr_location *al)
449{ 547{
450 struct map_groups *mg = &self->mg; 548 struct map_groups *mg = &self->mg;
549 struct kernel_info *kerninfo = NULL;
451 550
452 al->thread = self; 551 al->thread = self;
453 al->addr = addr; 552 al->addr = addr;
553 al->cpumode = cpumode;
554 al->filtered = false;
454 555
455 if (cpumode == PERF_RECORD_MISC_KERNEL) { 556 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
456 al->level = 'k'; 557 al->level = 'k';
457 mg = &session->kmaps; 558 kerninfo = kerninfo__findhost(&session->kerninfo_root);
458 } else if (cpumode == PERF_RECORD_MISC_USER) 559 mg = &kerninfo->kmaps;
560 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
459 al->level = '.'; 561 al->level = '.';
460 else { 562 kerninfo = kerninfo__findhost(&session->kerninfo_root);
461 al->level = 'H'; 563 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
564 al->level = 'g';
565 kerninfo = kerninfo__find(&session->kerninfo_root, pid);
566 if (!kerninfo) {
567 al->map = NULL;
568 return;
569 }
570 mg = &kerninfo->kmaps;
571 } else {
572 /*
573 * 'u' means guest os user space.
574 * TODO: We don't support guest user space. Might support late.
575 */
576 if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest)
577 al->level = 'u';
578 else
579 al->level = 'H';
462 al->map = NULL; 580 al->map = NULL;
581
582 if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
583 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
584 !perf_guest)
585 al->filtered = true;
586 if ((cpumode == PERF_RECORD_MISC_USER ||
587 cpumode == PERF_RECORD_MISC_KERNEL) &&
588 !perf_host)
589 al->filtered = true;
590
463 return; 591 return;
464 } 592 }
465try_again: 593try_again:
@@ -474,8 +602,11 @@ try_again:
474 * "[vdso]" dso, but for now lets use the old trick of looking 602 * "[vdso]" dso, but for now lets use the old trick of looking
475 * in the whole kernel symbol list. 603 * in the whole kernel symbol list.
476 */ 604 */
477 if ((long long)al->addr < 0 && mg != &session->kmaps) { 605 if ((long long)al->addr < 0 &&
478 mg = &session->kmaps; 606 cpumode == PERF_RECORD_MISC_KERNEL &&
607 kerninfo &&
608 mg != &kerninfo->kmaps) {
609 mg = &kerninfo->kmaps;
479 goto try_again; 610 goto try_again;
480 } 611 }
481 } else 612 } else
@@ -484,11 +615,11 @@ try_again:
484 615
485void thread__find_addr_location(struct thread *self, 616void thread__find_addr_location(struct thread *self,
486 struct perf_session *session, u8 cpumode, 617 struct perf_session *session, u8 cpumode,
487 enum map_type type, u64 addr, 618 enum map_type type, pid_t pid, u64 addr,
488 struct addr_location *al, 619 struct addr_location *al,
489 symbol_filter_t filter) 620 symbol_filter_t filter)
490{ 621{
491 thread__find_addr_map(self, session, cpumode, type, addr, al); 622 thread__find_addr_map(self, session, cpumode, type, pid, addr, al);
492 if (al->map != NULL) 623 if (al->map != NULL)
493 al->sym = map__find_symbol(al->map, al->addr, filter); 624 al->sym = map__find_symbol(al->map, al->addr, filter);
494 else 625 else
@@ -524,7 +655,7 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
524 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 655 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
525 656
526 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 657 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
527 self->ip.ip, al); 658 self->ip.pid, self->ip.ip, al);
528 dump_printf(" ...... dso: %s\n", 659 dump_printf(" ...... dso: %s\n",
529 al->map ? al->map->dso->long_name : 660 al->map ? al->map->dso->long_name :
530 al->level == 'H' ? "[hypervisor]" : "<not found>"); 661 al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -554,7 +685,6 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
554 !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) 685 !strlist__has_entry(symbol_conf.sym_list, al->sym->name))
555 goto out_filtered; 686 goto out_filtered;
556 687
557 al->filtered = false;
558 return 0; 688 return 0;
559 689
560out_filtered: 690out_filtered:
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index e5740ea140ab..4af2ed5d48ad 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -79,6 +79,7 @@ struct sample_data {
79 79
80struct build_id_event { 80struct build_id_event {
81 struct perf_event_header header; 81 struct perf_event_header header;
82 pid_t pid;
82 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; 83 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
83 char filename[]; 84 char filename[];
84}; 85};
@@ -154,10 +155,13 @@ int event__synthesize_thread(pid_t pid, event__handler_t process,
154void event__synthesize_threads(event__handler_t process, 155void event__synthesize_threads(event__handler_t process,
155 struct perf_session *session); 156 struct perf_session *session);
156int event__synthesize_kernel_mmap(event__handler_t process, 157int event__synthesize_kernel_mmap(event__handler_t process,
157 struct perf_session *session, 158 struct perf_session *session,
158 const char *symbol_name); 159 struct kernel_info *kerninfo,
160 const char *symbol_name);
161
159int event__synthesize_modules(event__handler_t process, 162int event__synthesize_modules(event__handler_t process,
160 struct perf_session *session); 163 struct perf_session *session,
164 struct kernel_info *kerninfo);
161 165
162int event__process_comm(event_t *self, struct perf_session *session); 166int event__process_comm(event_t *self, struct perf_session *session);
163int event__process_lost(event_t *self, struct perf_session *session); 167int event__process_lost(event_t *self, struct perf_session *session);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 628173ba689e..75d016768021 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -190,7 +190,8 @@ static int write_padded(int fd, const void *bf, size_t count,
190 continue; \ 190 continue; \
191 else 191 else
192 192
193static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) 193static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
194 u16 misc, int fd)
194{ 195{
195 struct dso *pos; 196 struct dso *pos;
196 197
@@ -205,6 +206,7 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd)
205 len = ALIGN(len, NAME_ALIGN); 206 len = ALIGN(len, NAME_ALIGN);
206 memset(&b, 0, sizeof(b)); 207 memset(&b, 0, sizeof(b));
207 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); 208 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
209 b.pid = pid;
208 b.header.misc = misc; 210 b.header.misc = misc;
209 b.header.size = sizeof(b) + len; 211 b.header.size = sizeof(b) + len;
210 err = do_write(fd, &b, sizeof(b)); 212 err = do_write(fd, &b, sizeof(b));
@@ -219,13 +221,33 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd)
219 return 0; 221 return 0;
220} 222}
221 223
222static int dsos__write_buildid_table(int fd) 224static int dsos__write_buildid_table(struct perf_header *header, int fd)
223{ 225{
224 int err = __dsos__write_buildid_table(&dsos__kernel, 226 struct perf_session *session = container_of(header,
225 PERF_RECORD_MISC_KERNEL, fd); 227 struct perf_session, header);
226 if (err == 0) 228 struct rb_node *nd;
227 err = __dsos__write_buildid_table(&dsos__user, 229 int err = 0;
228 PERF_RECORD_MISC_USER, fd); 230 u16 kmisc, umisc;
231
232 for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) {
233 struct kernel_info *pos = rb_entry(nd, struct kernel_info,
234 rb_node);
235 if (is_host_kernel(pos)) {
236 kmisc = PERF_RECORD_MISC_KERNEL;
237 umisc = PERF_RECORD_MISC_USER;
238 } else {
239 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
240 umisc = PERF_RECORD_MISC_GUEST_USER;
241 }
242
243 err = __dsos__write_buildid_table(&pos->dsos__kernel, pos->pid,
244 kmisc, fd);
245 if (err == 0)
246 err = __dsos__write_buildid_table(&pos->dsos__user,
247 pos->pid, umisc, fd);
248 if (err)
249 break;
250 }
229 return err; 251 return err;
230} 252}
231 253
@@ -342,9 +364,12 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
342 return err; 364 return err;
343} 365}
344 366
345static int dsos__cache_build_ids(void) 367static int dsos__cache_build_ids(struct perf_header *self)
346{ 368{
347 int err_kernel, err_user; 369 struct perf_session *session = container_of(self,
370 struct perf_session, header);
371 struct rb_node *nd;
372 int ret = 0;
348 char debugdir[PATH_MAX]; 373 char debugdir[PATH_MAX];
349 374
350 snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), 375 snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"),
@@ -353,9 +378,30 @@ static int dsos__cache_build_ids(void)
353 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) 378 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
354 return -1; 379 return -1;
355 380
356 err_kernel = __dsos__cache_build_ids(&dsos__kernel, debugdir); 381 for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) {
357 err_user = __dsos__cache_build_ids(&dsos__user, debugdir); 382 struct kernel_info *pos = rb_entry(nd, struct kernel_info,
358 return err_kernel || err_user ? -1 : 0; 383 rb_node);
384 ret |= __dsos__cache_build_ids(&pos->dsos__kernel, debugdir);
385 ret |= __dsos__cache_build_ids(&pos->dsos__user, debugdir);
386 }
387 return ret ? -1 : 0;
388}
389
390static bool dsos__read_build_ids(struct perf_header *self, bool with_hits)
391{
392 bool ret = false;
393 struct perf_session *session = container_of(self,
394 struct perf_session, header);
395 struct rb_node *nd;
396
397 for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) {
398 struct kernel_info *pos = rb_entry(nd, struct kernel_info,
399 rb_node);
400 ret |= __dsos__read_build_ids(&pos->dsos__kernel, with_hits);
401 ret |= __dsos__read_build_ids(&pos->dsos__user, with_hits);
402 }
403
404 return ret;
359} 405}
360 406
361static int perf_header__adds_write(struct perf_header *self, int fd) 407static int perf_header__adds_write(struct perf_header *self, int fd)
@@ -366,7 +412,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
366 u64 sec_start; 412 u64 sec_start;
367 int idx = 0, err; 413 int idx = 0, err;
368 414
369 if (dsos__read_build_ids(true)) 415 if (dsos__read_build_ids(self, true))
370 perf_header__set_feat(self, HEADER_BUILD_ID); 416 perf_header__set_feat(self, HEADER_BUILD_ID);
371 417
372 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 418 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
@@ -401,14 +447,14 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
401 447
402 /* Write build-ids */ 448 /* Write build-ids */
403 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 449 buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
404 err = dsos__write_buildid_table(fd); 450 err = dsos__write_buildid_table(self, fd);
405 if (err < 0) { 451 if (err < 0) {
406 pr_debug("failed to write buildid table\n"); 452 pr_debug("failed to write buildid table\n");
407 goto out_free; 453 goto out_free;
408 } 454 }
409 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - 455 buildid_sec->size = lseek(fd, 0, SEEK_CUR) -
410 buildid_sec->offset; 456 buildid_sec->offset;
411 dsos__cache_build_ids(); 457 dsos__cache_build_ids(self);
412 } 458 }
413 459
414 lseek(fd, sec_start, SEEK_SET); 460 lseek(fd, sec_start, SEEK_SET);
@@ -633,6 +679,85 @@ int perf_file_header__read(struct perf_file_header *self,
633 return 0; 679 return 0;
634} 680}
635 681
682static int __event_process_build_id(struct build_id_event *bev,
683 char *filename,
684 struct perf_session *session)
685{
686 int err = -1;
687 struct list_head *head;
688 struct kernel_info *kerninfo;
689 u16 misc;
690 struct dso *dso;
691 enum dso_kernel_type dso_type;
692
693 kerninfo = kerninfo__findnew(&session->kerninfo_root, bev->pid);
694 if (!kerninfo)
695 goto out;
696
697 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
698
699 switch (misc) {
700 case PERF_RECORD_MISC_KERNEL:
701 dso_type = DSO_TYPE_KERNEL;
702 head = &kerninfo->dsos__kernel;
703 break;
704 case PERF_RECORD_MISC_GUEST_KERNEL:
705 dso_type = DSO_TYPE_GUEST_KERNEL;
706 head = &kerninfo->dsos__kernel;
707 break;
708 case PERF_RECORD_MISC_USER:
709 case PERF_RECORD_MISC_GUEST_USER:
710 dso_type = DSO_TYPE_USER;
711 head = &kerninfo->dsos__user;
712 break;
713 default:
714 goto out;
715 }
716
717 dso = __dsos__findnew(head, filename);
718 if (dso != NULL) {
719 dso__set_build_id(dso, &bev->build_id);
720 if (filename[0] == '[')
721 dso->kernel = dso_type;
722 }
723
724 err = 0;
725out:
726 return err;
727}
728
729static int perf_header__read_build_ids(struct perf_header *self,
730 int input, u64 offset, u64 size)
731{
732 struct perf_session *session = container_of(self,
733 struct perf_session, header);
734 struct build_id_event bev;
735 char filename[PATH_MAX];
736 u64 limit = offset + size;
737 int err = -1;
738
739 while (offset < limit) {
740 ssize_t len;
741
742 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
743 goto out;
744
745 if (self->needs_swap)
746 perf_event_header__bswap(&bev.header);
747
748 len = bev.header.size - sizeof(bev);
749 if (read(input, filename, len) != len)
750 goto out;
751
752 __event_process_build_id(&bev, filename, session);
753
754 offset += bev.header.size;
755 }
756 err = 0;
757out:
758 return err;
759}
760
636static int perf_file_section__process(struct perf_file_section *self, 761static int perf_file_section__process(struct perf_file_section *self,
637 struct perf_header *ph, 762 struct perf_header *ph,
638 int feat, int fd) 763 int feat, int fd)
@@ -989,6 +1114,7 @@ int event__process_tracing_data(event_t *self,
989 1114
990int event__synthesize_build_id(struct dso *pos, u16 misc, 1115int event__synthesize_build_id(struct dso *pos, u16 misc,
991 event__handler_t process, 1116 event__handler_t process,
1117 struct kernel_info *kerninfo,
992 struct perf_session *session) 1118 struct perf_session *session)
993{ 1119{
994 event_t ev; 1120 event_t ev;
@@ -1005,6 +1131,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
1005 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); 1131 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
1006 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; 1132 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
1007 ev.build_id.header.misc = misc; 1133 ev.build_id.header.misc = misc;
1134 ev.build_id.pid = kerninfo->pid;
1008 ev.build_id.header.size = sizeof(ev.build_id) + len; 1135 ev.build_id.header.size = sizeof(ev.build_id) + len;
1009 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 1136 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
1010 1137
@@ -1015,6 +1142,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
1015 1142
1016static int __event_synthesize_build_ids(struct list_head *head, u16 misc, 1143static int __event_synthesize_build_ids(struct list_head *head, u16 misc,
1017 event__handler_t process, 1144 event__handler_t process,
1145 struct kernel_info *kerninfo,
1018 struct perf_session *session) 1146 struct perf_session *session)
1019{ 1147{
1020 struct dso *pos; 1148 struct dso *pos;
@@ -1024,7 +1152,8 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc,
1024 if (!pos->hit) 1152 if (!pos->hit)
1025 continue; 1153 continue;
1026 1154
1027 err = event__synthesize_build_id(pos, misc, process, session); 1155 err = event__synthesize_build_id(pos, misc, process,
1156 kerninfo, session);
1028 if (err < 0) 1157 if (err < 0)
1029 return err; 1158 return err;
1030 } 1159 }
@@ -1035,44 +1164,48 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc,
1035int event__synthesize_build_ids(event__handler_t process, 1164int event__synthesize_build_ids(event__handler_t process,
1036 struct perf_session *session) 1165 struct perf_session *session)
1037{ 1166{
1038 int err; 1167 int err = 0;
1168 u16 kmisc, umisc;
1169 struct kernel_info *pos;
1170 struct rb_node *nd;
1039 1171
1040 if (!dsos__read_build_ids(true)) 1172 if (!dsos__read_build_ids(&session->header, true))
1041 return 0; 1173 return 0;
1042 1174
1043 err = __event_synthesize_build_ids(&dsos__kernel, 1175 for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) {
1044 PERF_RECORD_MISC_KERNEL, 1176 pos = rb_entry(nd, struct kernel_info, rb_node);
1045 process, session); 1177 if (is_host_kernel(pos)) {
1046 if (err == 0) 1178 kmisc = PERF_RECORD_MISC_KERNEL;
1047 err = __event_synthesize_build_ids(&dsos__user, 1179 umisc = PERF_RECORD_MISC_USER;
1048 PERF_RECORD_MISC_USER, 1180 } else {
1049 process, session); 1181 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
1182 umisc = PERF_RECORD_MISC_GUEST_USER;
1183 }
1184
1185 err = __event_synthesize_build_ids(&pos->dsos__kernel,
1186 kmisc, process, pos, session);
1187 if (err == 0)
1188 err = __event_synthesize_build_ids(&pos->dsos__user,
1189 umisc, process, pos, session);
1190 if (err)
1191 break;
1192 }
1050 1193
1051 if (err < 0) { 1194 if (err < 0) {
1052 pr_debug("failed to synthesize build ids\n"); 1195 pr_debug("failed to synthesize build ids\n");
1053 return err; 1196 return err;
1054 } 1197 }
1055 1198
1056 dsos__cache_build_ids(); 1199 dsos__cache_build_ids(&session->header);
1057 1200
1058 return 0; 1201 return 0;
1059} 1202}
1060 1203
1061int event__process_build_id(event_t *self, 1204int event__process_build_id(event_t *self,
1062 struct perf_session *session __unused) 1205 struct perf_session *session)
1063{ 1206{
1064 struct list_head *head = &dsos__user; 1207 __event_process_build_id(&self->build_id,
1065 struct dso *dso; 1208 self->build_id.filename,
1066 1209 session);
1067 if (self->build_id.header.misc & PERF_RECORD_MISC_KERNEL)
1068 head = &dsos__kernel;
1069
1070 dso = __dsos__findnew(head, self->build_id.filename);
1071 if (dso != NULL) {
1072 dso__set_build_id(dso, &self->build_id.build_id);
1073 if (head == &dsos__kernel && self->build_id.filename[0] == '[')
1074 dso->kernel = 1;
1075 }
1076
1077 return 0; 1210 return 0;
1078} 1211}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 4214e2375650..275915458148 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -120,6 +120,7 @@ int event__process_tracing_data(event_t *self,
120 120
121int event__synthesize_build_id(struct dso *pos, u16 misc, 121int event__synthesize_build_id(struct dso *pos, u16 misc,
122 event__handler_t process, 122 event__handler_t process,
123 struct kernel_info *kerninfo,
123 struct perf_session *session); 124 struct perf_session *session);
124int event__synthesize_build_ids(event__handler_t process, 125int event__synthesize_build_ids(event__handler_t process,
125 struct perf_session *session); 126 struct perf_session *session);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9c2b8743cef6..ad6b22dde27f 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -8,6 +8,30 @@ struct callchain_param callchain_param = {
8 .min_percent = 0.5 8 .min_percent = 0.5
9}; 9};
10 10
11void __perf_session__add_count(struct hist_entry *he,
12 struct addr_location *al,
13 u64 count)
14{
15 he->count += count;
16
17 switch (al->cpumode) {
18 case PERF_RECORD_MISC_KERNEL:
19 he->count_sys += count;
20 break;
21 case PERF_RECORD_MISC_USER:
22 he->count_us += count;
23 break;
24 case PERF_RECORD_MISC_GUEST_KERNEL:
25 he->count_guest_sys += count;
26 break;
27 case PERF_RECORD_MISC_GUEST_USER:
28 he->count_guest_us += count;
29 break;
30 default:
31 break;
32 }
33}
34
11/* 35/*
12 * histogram, sorted on item, collects counts 36 * histogram, sorted on item, collects counts
13 */ 37 */
@@ -464,7 +488,7 @@ int hist_entry__snprintf(struct hist_entry *self,
464 u64 session_total) 488 u64 session_total)
465{ 489{
466 struct sort_entry *se; 490 struct sort_entry *se;
467 u64 count, total; 491 u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us;
468 const char *sep = symbol_conf.field_sep; 492 const char *sep = symbol_conf.field_sep;
469 int ret; 493 int ret;
470 494
@@ -474,9 +498,17 @@ int hist_entry__snprintf(struct hist_entry *self,
474 if (pair_session) { 498 if (pair_session) {
475 count = self->pair ? self->pair->count : 0; 499 count = self->pair ? self->pair->count : 0;
476 total = pair_session->events_stats.total; 500 total = pair_session->events_stats.total;
501 count_sys = self->pair ? self->pair->count_sys : 0;
502 count_us = self->pair ? self->pair->count_us : 0;
503 count_guest_sys = self->pair ? self->pair->count_guest_sys : 0;
504 count_guest_us = self->pair ? self->pair->count_guest_us : 0;
477 } else { 505 } else {
478 count = self->count; 506 count = self->count;
479 total = session_total; 507 total = session_total;
508 count_sys = self->count_sys;
509 count_us = self->count_us;
510 count_guest_sys = self->count_guest_sys;
511 count_guest_us = self->count_guest_us;
480 } 512 }
481 513
482 if (total) { 514 if (total) {
@@ -487,6 +519,26 @@ int hist_entry__snprintf(struct hist_entry *self,
487 else 519 else
488 ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%", 520 ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%",
489 (count * 100.0) / total); 521 (count * 100.0) / total);
522 if (symbol_conf.show_cpu_utilization) {
523 ret += percent_color_snprintf(s + ret, size - ret,
524 sep ? "%.2f" : " %6.2f%%",
525 (count_sys * 100.0) / total);
526 ret += percent_color_snprintf(s + ret, size - ret,
527 sep ? "%.2f" : " %6.2f%%",
528 (count_us * 100.0) / total);
529 if (perf_guest) {
530 ret += percent_color_snprintf(s + ret,
531 size - ret,
532 sep ? "%.2f" : " %6.2f%%",
533 (count_guest_sys * 100.0) /
534 total);
535 ret += percent_color_snprintf(s + ret,
536 size - ret,
537 sep ? "%.2f" : " %6.2f%%",
538 (count_guest_us * 100.0) /
539 total);
540 }
541 }
490 } else 542 } else
491 ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count); 543 ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count);
492 544
@@ -597,6 +649,24 @@ size_t perf_session__fprintf_hists(struct rb_root *hists,
597 fputs(" Samples ", fp); 649 fputs(" Samples ", fp);
598 } 650 }
599 651
652 if (symbol_conf.show_cpu_utilization) {
653 if (sep) {
654 ret += fprintf(fp, "%csys", *sep);
655 ret += fprintf(fp, "%cus", *sep);
656 if (perf_guest) {
657 ret += fprintf(fp, "%cguest sys", *sep);
658 ret += fprintf(fp, "%cguest us", *sep);
659 }
660 } else {
661 ret += fprintf(fp, " sys ");
662 ret += fprintf(fp, " us ");
663 if (perf_guest) {
664 ret += fprintf(fp, " guest sys ");
665 ret += fprintf(fp, " guest us ");
666 }
667 }
668 }
669
600 if (pair) { 670 if (pair) {
601 if (sep) 671 if (sep)
602 ret += fprintf(fp, "%cDelta", *sep); 672 ret += fprintf(fp, "%cDelta", *sep);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ad17f0ad798b..9df1c340ec92 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -12,6 +12,9 @@ struct addr_location;
12struct symbol; 12struct symbol;
13struct rb_root; 13struct rb_root;
14 14
15void __perf_session__add_count(struct hist_entry *he,
16 struct addr_location *al,
17 u64 count);
15struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, 18struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
16 struct addr_location *al, 19 struct addr_location *al,
17 struct symbol *parent, 20 struct symbol *parent,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 37913b241bdf..7facd016ec97 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -4,6 +4,7 @@
4#include <stdlib.h> 4#include <stdlib.h>
5#include <string.h> 5#include <string.h>
6#include <stdio.h> 6#include <stdio.h>
7#include <unistd.h>
7#include "map.h" 8#include "map.h"
8 9
9const char *map_type__name[MAP__NR_TYPES] = { 10const char *map_type__name[MAP__NR_TYPES] = {
@@ -37,9 +38,11 @@ void map__init(struct map *self, enum map_type type,
37 self->map_ip = map__map_ip; 38 self->map_ip = map__map_ip;
38 self->unmap_ip = map__unmap_ip; 39 self->unmap_ip = map__unmap_ip;
39 RB_CLEAR_NODE(&self->rb_node); 40 RB_CLEAR_NODE(&self->rb_node);
41 self->groups = NULL;
40} 42}
41 43
42struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, 44struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
45 u64 pgoff, u32 pid, char *filename,
43 enum map_type type, char *cwd, int cwdlen) 46 enum map_type type, char *cwd, int cwdlen)
44{ 47{
45 struct map *self = malloc(sizeof(*self)); 48 struct map *self = malloc(sizeof(*self));
@@ -66,7 +69,7 @@ struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename,
66 filename = newfilename; 69 filename = newfilename;
67 } 70 }
68 71
69 dso = dsos__findnew(filename); 72 dso = __dsos__findnew(dsos__list, filename);
70 if (dso == NULL) 73 if (dso == NULL)
71 goto out_delete; 74 goto out_delete;
72 75
@@ -242,6 +245,7 @@ void map_groups__init(struct map_groups *self)
242 self->maps[i] = RB_ROOT; 245 self->maps[i] = RB_ROOT;
243 INIT_LIST_HEAD(&self->removed_maps[i]); 246 INIT_LIST_HEAD(&self->removed_maps[i]);
244 } 247 }
248 self->this_kerninfo = NULL;
245} 249}
246 250
247void map_groups__flush(struct map_groups *self) 251void map_groups__flush(struct map_groups *self)
@@ -508,3 +512,134 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
508 512
509 return NULL; 513 return NULL;
510} 514}
515
516struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root,
517 pid_t pid, const char *root_dir)
518{
519 struct rb_node **p = &kerninfo_root->rb_node;
520 struct rb_node *parent = NULL;
521 struct kernel_info *kerninfo, *pos;
522
523 kerninfo = malloc(sizeof(struct kernel_info));
524 if (!kerninfo)
525 return NULL;
526
527 kerninfo->pid = pid;
528 map_groups__init(&kerninfo->kmaps);
529 kerninfo->root_dir = strdup(root_dir);
530 RB_CLEAR_NODE(&kerninfo->rb_node);
531 INIT_LIST_HEAD(&kerninfo->dsos__user);
532 INIT_LIST_HEAD(&kerninfo->dsos__kernel);
533 kerninfo->kmaps.this_kerninfo = kerninfo;
534
535 while (*p != NULL) {
536 parent = *p;
537 pos = rb_entry(parent, struct kernel_info, rb_node);
538 if (pid < pos->pid)
539 p = &(*p)->rb_left;
540 else
541 p = &(*p)->rb_right;
542 }
543
544 rb_link_node(&kerninfo->rb_node, parent, p);
545 rb_insert_color(&kerninfo->rb_node, kerninfo_root);
546
547 return kerninfo;
548}
549
550struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid)
551{
552 struct rb_node **p = &kerninfo_root->rb_node;
553 struct rb_node *parent = NULL;
554 struct kernel_info *kerninfo;
555 struct kernel_info *default_kerninfo = NULL;
556
557 while (*p != NULL) {
558 parent = *p;
559 kerninfo = rb_entry(parent, struct kernel_info, rb_node);
560 if (pid < kerninfo->pid)
561 p = &(*p)->rb_left;
562 else if (pid > kerninfo->pid)
563 p = &(*p)->rb_right;
564 else
565 return kerninfo;
566 if (!kerninfo->pid)
567 default_kerninfo = kerninfo;
568 }
569
570 return default_kerninfo;
571}
572
573struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root)
574{
575 struct rb_node **p = &kerninfo_root->rb_node;
576 struct rb_node *parent = NULL;
577 struct kernel_info *kerninfo;
578 pid_t pid = HOST_KERNEL_ID;
579
580 while (*p != NULL) {
581 parent = *p;
582 kerninfo = rb_entry(parent, struct kernel_info, rb_node);
583 if (pid < kerninfo->pid)
584 p = &(*p)->rb_left;
585 else if (pid > kerninfo->pid)
586 p = &(*p)->rb_right;
587 else
588 return kerninfo;
589 }
590
591 return NULL;
592}
593
594struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid)
595{
596 char path[PATH_MAX];
597 const char *root_dir;
598 int ret;
599 struct kernel_info *kerninfo = kerninfo__find(kerninfo_root, pid);
600
601 if (!kerninfo || kerninfo->pid != pid) {
602 if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID)
603 root_dir = "";
604 else {
605 if (!symbol_conf.guestmount)
606 goto out;
607 sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
608 ret = access(path, R_OK);
609 if (ret) {
610 pr_err("Can't access file %s\n", path);
611 goto out;
612 }
613 root_dir = path;
614 }
615 kerninfo = add_new_kernel_info(kerninfo_root, pid, root_dir);
616 }
617
618out:
619 return kerninfo;
620}
621
622void kerninfo__process_allkernels(struct rb_root *kerninfo_root,
623 process_kernel_info process,
624 void *data)
625{
626 struct rb_node *nd;
627
628 for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) {
629 struct kernel_info *pos = rb_entry(nd, struct kernel_info,
630 rb_node);
631 process(pos, data);
632 }
633}
634
635char *kern_mmap_name(struct kernel_info *kerninfo, char *buff)
636{
637 if (is_host_kernel(kerninfo))
638 sprintf(buff, "[%s]", "kernel.kallsyms");
639 else if (is_default_guest(kerninfo))
640 sprintf(buff, "[%s]", "guest.kernel.kallsyms");
641 else
642 sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", kerninfo->pid);
643
644 return buff;
645}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2031278cc06a..30d38d634e09 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -19,6 +19,7 @@ extern const char *map_type__name[MAP__NR_TYPES];
19struct dso; 19struct dso;
20struct ref_reloc_sym; 20struct ref_reloc_sym;
21struct map_groups; 21struct map_groups;
22struct kernel_info;
22 23
23struct map { 24struct map {
24 union { 25 union {
@@ -36,6 +37,7 @@ struct map {
36 u64 (*unmap_ip)(struct map *, u64); 37 u64 (*unmap_ip)(struct map *, u64);
37 38
38 struct dso *dso; 39 struct dso *dso;
40 struct map_groups *groups;
39}; 41};
40 42
41struct kmap { 43struct kmap {
@@ -43,6 +45,26 @@ struct kmap {
43 struct map_groups *kmaps; 45 struct map_groups *kmaps;
44}; 46};
45 47
48struct map_groups {
49 struct rb_root maps[MAP__NR_TYPES];
50 struct list_head removed_maps[MAP__NR_TYPES];
51 struct kernel_info *this_kerninfo;
52};
53
54/* Native host kernel uses -1 as pid index in kernel_info */
55#define HOST_KERNEL_ID (-1)
56#define DEFAULT_GUEST_KERNEL_ID (0)
57
58struct kernel_info {
59 struct rb_node rb_node;
60 pid_t pid;
61 char *root_dir;
62 struct list_head dsos__user;
63 struct list_head dsos__kernel;
64 struct map_groups kmaps;
65 struct map *vmlinux_maps[MAP__NR_TYPES];
66};
67
46static inline struct kmap *map__kmap(struct map *self) 68static inline struct kmap *map__kmap(struct map *self)
47{ 69{
48 return (struct kmap *)(self + 1); 70 return (struct kmap *)(self + 1);
@@ -74,7 +96,8 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
74 96
75void map__init(struct map *self, enum map_type type, 97void map__init(struct map *self, enum map_type type,
76 u64 start, u64 end, u64 pgoff, struct dso *dso); 98 u64 start, u64 end, u64 pgoff, struct dso *dso);
77struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, 99struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
100 u64 pgoff, u32 pid, char *filename,
78 enum map_type type, char *cwd, int cwdlen); 101 enum map_type type, char *cwd, int cwdlen);
79void map__delete(struct map *self); 102void map__delete(struct map *self);
80struct map *map__clone(struct map *self); 103struct map *map__clone(struct map *self);
@@ -91,11 +114,6 @@ void map__fixup_end(struct map *self);
91 114
92void map__reloc_vmlinux(struct map *self); 115void map__reloc_vmlinux(struct map *self);
93 116
94struct map_groups {
95 struct rb_root maps[MAP__NR_TYPES];
96 struct list_head removed_maps[MAP__NR_TYPES];
97};
98
99size_t __map_groups__fprintf_maps(struct map_groups *self, 117size_t __map_groups__fprintf_maps(struct map_groups *self,
100 enum map_type type, int verbose, FILE *fp); 118 enum map_type type, int verbose, FILE *fp);
101void maps__insert(struct rb_root *maps, struct map *map); 119void maps__insert(struct rb_root *maps, struct map *map);
@@ -106,9 +124,40 @@ int map_groups__clone(struct map_groups *self,
106size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); 124size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp);
107size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp); 125size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp);
108 126
127struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root,
128 pid_t pid, const char *root_dir);
129struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid);
130struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid);
131struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root);
132char *kern_mmap_name(struct kernel_info *kerninfo, char *buff);
133
134/*
135 * Default guest kernel is defined by parameter --guestkallsyms
136 * and --guestmodules
137 */
138static inline int is_default_guest(struct kernel_info *kerninfo)
139{
140 if (!kerninfo)
141 return 0;
142 return kerninfo->pid == DEFAULT_GUEST_KERNEL_ID;
143}
144
145static inline int is_host_kernel(struct kernel_info *kerninfo)
146{
147 if (!kerninfo)
148 return 0;
149 return kerninfo->pid == HOST_KERNEL_ID;
150}
151
152typedef void (*process_kernel_info)(struct kernel_info *kerninfo, void *data);
153void kerninfo__process_allkernels(struct rb_root *kerninfo_root,
154 process_kernel_info process,
155 void *data);
156
109static inline void map_groups__insert(struct map_groups *self, struct map *map) 157static inline void map_groups__insert(struct map_groups *self, struct map *map)
110{ 158{
111 maps__insert(&self->maps[map->type], map); 159 maps__insert(&self->maps[map->type], map);
160 map->groups = self;
112} 161}
113 162
114static inline struct map *map_groups__find(struct map_groups *self, 163static inline struct map *map_groups__find(struct map_groups *self,
@@ -148,13 +197,11 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
148 197
149struct map *map_groups__find_by_name(struct map_groups *self, 198struct map *map_groups__find_by_name(struct map_groups *self,
150 enum map_type type, const char *name); 199 enum map_type type, const char *name);
151int __map_groups__create_kernel_maps(struct map_groups *self, 200struct map *map_groups__new_module(struct map_groups *self,
152 struct map *vmlinux_maps[MAP__NR_TYPES], 201 u64 start,
153 struct dso *kernel); 202 const char *filename,
154int map_groups__create_kernel_maps(struct map_groups *self, 203 struct kernel_info *kerninfo);
155 struct map *vmlinux_maps[MAP__NR_TYPES]); 204
156struct map *map_groups__new_module(struct map_groups *self, u64 start,
157 const char *filename);
158void map_groups__flush(struct map_groups *self); 205void map_groups__flush(struct map_groups *self);
159 206
160#endif /* __PERF_MAP_H */ 207#endif /* __PERF_MAP_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 5bf8ab034466..3967f8f63d0d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -78,6 +78,7 @@ static struct map *kmaps[MAP__NR_TYPES];
78/* Initialize symbol maps and path of vmlinux */ 78/* Initialize symbol maps and path of vmlinux */
79static int init_vmlinux(void) 79static int init_vmlinux(void)
80{ 80{
81 struct dso *kernel;
81 int ret; 82 int ret;
82 83
83 symbol_conf.sort_by_name = true; 84 symbol_conf.sort_by_name = true;
@@ -91,8 +92,12 @@ static int init_vmlinux(void)
91 goto out; 92 goto out;
92 } 93 }
93 94
95 kernel = dso__new_kernel(symbol_conf.vmlinux_name);
96 if (kernel == NULL)
97 die("Failed to create kernel dso.");
98
94 map_groups__init(&kmap_groups); 99 map_groups__init(&kmap_groups);
95 ret = map_groups__create_kernel_maps(&kmap_groups, kmaps); 100 ret = __map_groups__create_kernel_maps(&kmap_groups, kmaps, kernel);
96 if (ret < 0) 101 if (ret < 0)
97 pr_debug("Failed to create kernel maps.\n"); 102 pr_debug("Failed to create kernel maps.\n");
98 103
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0fdf3ebef1e9..7d88ae5c270f 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -67,6 +67,17 @@ void perf_session__update_sample_type(struct perf_session *self)
67 self->sample_type = perf_header__sample_type(&self->header); 67 self->sample_type = perf_header__sample_type(&self->header);
68} 68}
69 69
70int perf_session__create_kernel_maps(struct perf_session *self)
71{
72 int ret;
73 struct rb_root *root = &self->kerninfo_root;
74
75 ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID);
76 if (ret >= 0)
77 ret = map_groups__create_guest_kernel_maps(root);
78 return ret;
79}
80
70struct perf_session *perf_session__new(const char *filename, int mode, bool force) 81struct perf_session *perf_session__new(const char *filename, int mode, bool force)
71{ 82{
72 size_t len = filename ? strlen(filename) + 1 : 0; 83 size_t len = filename ? strlen(filename) + 1 : 0;
@@ -86,7 +97,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
86 self->cwd = NULL; 97 self->cwd = NULL;
87 self->cwdlen = 0; 98 self->cwdlen = 0;
88 self->unknown_events = 0; 99 self->unknown_events = 0;
89 map_groups__init(&self->kmaps); 100 self->kerninfo_root = RB_ROOT;
90 101
91 if (mode == O_RDONLY) { 102 if (mode == O_RDONLY) {
92 if (perf_session__open(self, force) < 0) 103 if (perf_session__open(self, force) < 0)
@@ -157,8 +168,9 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
157 continue; 168 continue;
158 } 169 }
159 170
171 al.filtered = false;
160 thread__find_addr_location(thread, self, cpumode, 172 thread__find_addr_location(thread, self, cpumode,
161 MAP__FUNCTION, ip, &al, NULL); 173 MAP__FUNCTION, thread->pid, ip, &al, NULL);
162 if (al.sym != NULL) { 174 if (al.sym != NULL) {
163 if (sort__has_parent && !*parent && 175 if (sort__has_parent && !*parent &&
164 symbol__match_parent_regex(al.sym)) 176 symbol__match_parent_regex(al.sym))
@@ -399,46 +411,6 @@ void perf_event_header__bswap(struct perf_event_header *self)
399 self->size = bswap_16(self->size); 411 self->size = bswap_16(self->size);
400} 412}
401 413
402int perf_header__read_build_ids(struct perf_header *self,
403 int input, u64 offset, u64 size)
404{
405 struct build_id_event bev;
406 char filename[PATH_MAX];
407 u64 limit = offset + size;
408 int err = -1;
409
410 while (offset < limit) {
411 struct dso *dso;
412 ssize_t len;
413 struct list_head *head = &dsos__user;
414
415 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
416 goto out;
417
418 if (self->needs_swap)
419 perf_event_header__bswap(&bev.header);
420
421 len = bev.header.size - sizeof(bev);
422 if (read(input, filename, len) != len)
423 goto out;
424
425 if (bev.header.misc & PERF_RECORD_MISC_KERNEL)
426 head = &dsos__kernel;
427
428 dso = __dsos__findnew(head, filename);
429 if (dso != NULL) {
430 dso__set_build_id(dso, &bev.build_id);
431 if (head == &dsos__kernel && filename[0] == '[')
432 dso->kernel = 1;
433 }
434
435 offset += bev.header.size;
436 }
437 err = 0;
438out:
439 return err;
440}
441
442static struct thread *perf_session__register_idle_thread(struct perf_session *self) 414static struct thread *perf_session__register_idle_thread(struct perf_session *self)
443{ 415{
444 struct thread *thread = perf_session__findnew(self, 0); 416 struct thread *thread = perf_session__findnew(self, 0);
@@ -690,26 +662,33 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg)
690 return true; 662 return true;
691} 663}
692 664
693int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self, 665int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
694 const char *symbol_name, 666 const char *symbol_name,
695 u64 addr) 667 u64 addr)
696{ 668{
697 char *bracket; 669 char *bracket;
698 enum map_type i; 670 enum map_type i;
671 struct ref_reloc_sym *ref;
672
673 ref = zalloc(sizeof(struct ref_reloc_sym));
674 if (ref == NULL)
675 return -ENOMEM;
699 676
700 self->ref_reloc_sym.name = strdup(symbol_name); 677 ref->name = strdup(symbol_name);
701 if (self->ref_reloc_sym.name == NULL) 678 if (ref->name == NULL) {
679 free(ref);
702 return -ENOMEM; 680 return -ENOMEM;
681 }
703 682
704 bracket = strchr(self->ref_reloc_sym.name, ']'); 683 bracket = strchr(ref->name, ']');
705 if (bracket) 684 if (bracket)
706 *bracket = '\0'; 685 *bracket = '\0';
707 686
708 self->ref_reloc_sym.addr = addr; 687 ref->addr = addr;
709 688
710 for (i = 0; i < MAP__NR_TYPES; ++i) { 689 for (i = 0; i < MAP__NR_TYPES; ++i) {
711 struct kmap *kmap = map__kmap(self->vmlinux_maps[i]); 690 struct kmap *kmap = map__kmap(maps[i]);
712 kmap->ref_reloc_sym = &self->ref_reloc_sym; 691 kmap->ref_reloc_sym = ref;
713 } 692 }
714 693
715 return 0; 694 return 0;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0ac14d42dc28..5e47c87b9266 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -15,17 +15,15 @@ struct perf_session {
15 struct perf_header header; 15 struct perf_header header;
16 unsigned long size; 16 unsigned long size;
17 unsigned long mmap_window; 17 unsigned long mmap_window;
18 struct map_groups kmaps;
19 struct rb_root threads; 18 struct rb_root threads;
20 struct thread *last_match; 19 struct thread *last_match;
21 struct map *vmlinux_maps[MAP__NR_TYPES]; 20 struct rb_root kerninfo_root;
22 struct events_stats events_stats; 21 struct events_stats events_stats;
23 struct rb_root stats_by_id; 22 struct rb_root stats_by_id;
24 unsigned long event_total[PERF_RECORD_MAX]; 23 unsigned long event_total[PERF_RECORD_MAX];
25 unsigned long unknown_events; 24 unsigned long unknown_events;
26 struct rb_root hists; 25 struct rb_root hists;
27 u64 sample_type; 26 u64 sample_type;
28 struct ref_reloc_sym ref_reloc_sym;
29 int fd; 27 int fd;
30 bool fd_pipe; 28 bool fd_pipe;
31 int cwdlen; 29 int cwdlen;
@@ -69,33 +67,13 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
69 67
70bool perf_session__has_traces(struct perf_session *self, const char *msg); 68bool perf_session__has_traces(struct perf_session *self, const char *msg);
71 69
72int perf_header__read_build_ids(struct perf_header *self, int input, 70int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
73 u64 offset, u64 file_size);
74
75int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
76 const char *symbol_name, 71 const char *symbol_name,
77 u64 addr); 72 u64 addr);
78 73
79void mem_bswap_64(void *src, int byte_size); 74void mem_bswap_64(void *src, int byte_size);
80 75
81static inline int __perf_session__create_kernel_maps(struct perf_session *self, 76int perf_session__create_kernel_maps(struct perf_session *self);
82 struct dso *kernel)
83{
84 return __map_groups__create_kernel_maps(&self->kmaps,
85 self->vmlinux_maps, kernel);
86}
87
88static inline int perf_session__create_kernel_maps(struct perf_session *self)
89{
90 return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps);
91}
92
93static inline struct map *
94 perf_session__new_module_map(struct perf_session *self,
95 u64 start, const char *filename)
96{
97 return map_groups__new_module(&self->kmaps, start, filename);
98}
99 77
100int do_read(int fd, void *buf, size_t size); 78int do_read(int fd, void *buf, size_t size);
101void perf_session__update_sample_type(struct perf_session *self); 79void perf_session__update_sample_type(struct perf_session *self);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 1d857aa2c01f..b7c54eeed9c9 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -44,6 +44,11 @@ extern enum sort_type sort__first_dimension;
44struct hist_entry { 44struct hist_entry {
45 struct rb_node rb_node; 45 struct rb_node rb_node;
46 u64 count; 46 u64 count;
47 u64 count_sys;
48 u64 count_us;
49 u64 count_guest_sys;
50 u64 count_guest_us;
51
47 /* 52 /*
48 * XXX WARNING! 53 * XXX WARNING!
49 * thread _has_ to come after ms, see 54 * thread _has_ to come after ms, see
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index f3d4151e46a1..e782e7db16c5 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -28,6 +28,8 @@ static void dsos__add(struct list_head *head, struct dso *dso);
28static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 28static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
29static int dso__load_kernel_sym(struct dso *self, struct map *map, 29static int dso__load_kernel_sym(struct dso *self, struct map *map,
30 symbol_filter_t filter); 30 symbol_filter_t filter);
31static int dso__load_guest_kernel_sym(struct dso *self, struct map *map,
32 symbol_filter_t filter);
31static int vmlinux_path__nr_entries; 33static int vmlinux_path__nr_entries;
32static char **vmlinux_path; 34static char **vmlinux_path;
33 35
@@ -186,6 +188,7 @@ struct dso *dso__new(const char *name)
186 self->loaded = 0; 188 self->loaded = 0;
187 self->sorted_by_name = 0; 189 self->sorted_by_name = 0;
188 self->has_build_id = 0; 190 self->has_build_id = 0;
191 self->kernel = DSO_TYPE_USER;
189 } 192 }
190 193
191 return self; 194 return self;
@@ -402,12 +405,9 @@ int kallsyms__parse(const char *filename, void *arg,
402 char *symbol_name; 405 char *symbol_name;
403 406
404 line_len = getline(&line, &n, file); 407 line_len = getline(&line, &n, file);
405 if (line_len < 0) 408 if (line_len < 0 || !line)
406 break; 409 break;
407 410
408 if (!line)
409 goto out_failure;
410
411 line[--line_len] = '\0'; /* \n */ 411 line[--line_len] = '\0'; /* \n */
412 412
413 len = hex2u64(line, &start); 413 len = hex2u64(line, &start);
@@ -459,6 +459,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
459 * map__split_kallsyms, when we have split the maps per module 459 * map__split_kallsyms, when we have split the maps per module
460 */ 460 */
461 symbols__insert(root, sym); 461 symbols__insert(root, sym);
462
462 return 0; 463 return 0;
463} 464}
464 465
@@ -483,6 +484,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
483 symbol_filter_t filter) 484 symbol_filter_t filter)
484{ 485{
485 struct map_groups *kmaps = map__kmap(map)->kmaps; 486 struct map_groups *kmaps = map__kmap(map)->kmaps;
487 struct kernel_info *kerninfo = kmaps->this_kerninfo;
486 struct map *curr_map = map; 488 struct map *curr_map = map;
487 struct symbol *pos; 489 struct symbol *pos;
488 int count = 0; 490 int count = 0;
@@ -504,15 +506,33 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
504 *module++ = '\0'; 506 *module++ = '\0';
505 507
506 if (strcmp(curr_map->dso->short_name, module)) { 508 if (strcmp(curr_map->dso->short_name, module)) {
507 curr_map = map_groups__find_by_name(kmaps, map->type, module); 509 if (curr_map != map &&
510 self->kernel == DSO_TYPE_GUEST_KERNEL &&
511 is_default_guest(kerninfo)) {
512 /*
513 * We assume all symbols of a module are
514 * continuous in * kallsyms, so curr_map
515 * points to a module and all its
516 * symbols are in its kmap. Mark it as
517 * loaded.
518 */
519 dso__set_loaded(curr_map->dso,
520 curr_map->type);
521 }
522
523 curr_map = map_groups__find_by_name(kmaps,
524 map->type, module);
508 if (curr_map == NULL) { 525 if (curr_map == NULL) {
509 pr_debug("/proc/{kallsyms,modules} " 526 pr_err("%s/proc/{kallsyms,modules} "
510 "inconsistency while looking " 527 "inconsistency while looking "
511 "for \"%s\" module!\n", module); 528 "for \"%s\" module!\n",
512 return -1; 529 kerninfo->root_dir, module);
530 curr_map = map;
531 goto discard_symbol;
513 } 532 }
514 533
515 if (curr_map->dso->loaded) 534 if (curr_map->dso->loaded &&
535 !is_default_guest(kmaps->this_kerninfo))
516 goto discard_symbol; 536 goto discard_symbol;
517 } 537 }
518 /* 538 /*
@@ -525,13 +545,21 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
525 char dso_name[PATH_MAX]; 545 char dso_name[PATH_MAX];
526 struct dso *dso; 546 struct dso *dso;
527 547
528 snprintf(dso_name, sizeof(dso_name), "[kernel].%d", 548 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
529 kernel_range++); 549 snprintf(dso_name, sizeof(dso_name),
550 "[guest.kernel].%d",
551 kernel_range++);
552 else
553 snprintf(dso_name, sizeof(dso_name),
554 "[kernel].%d",
555 kernel_range++);
530 556
531 dso = dso__new(dso_name); 557 dso = dso__new(dso_name);
532 if (dso == NULL) 558 if (dso == NULL)
533 return -1; 559 return -1;
534 560
561 dso->kernel = self->kernel;
562
535 curr_map = map__new2(pos->start, dso, map->type); 563 curr_map = map__new2(pos->start, dso, map->type);
536 if (curr_map == NULL) { 564 if (curr_map == NULL) {
537 dso__delete(dso); 565 dso__delete(dso);
@@ -555,6 +583,12 @@ discard_symbol: rb_erase(&pos->rb_node, root);
555 } 583 }
556 } 584 }
557 585
586 if (curr_map != map &&
587 self->kernel == DSO_TYPE_GUEST_KERNEL &&
588 is_default_guest(kmaps->this_kerninfo)) {
589 dso__set_loaded(curr_map->dso, curr_map->type);
590 }
591
558 return count; 592 return count;
559} 593}
560 594
@@ -565,7 +599,10 @@ int dso__load_kallsyms(struct dso *self, const char *filename,
565 return -1; 599 return -1;
566 600
567 symbols__fixup_end(&self->symbols[map->type]); 601 symbols__fixup_end(&self->symbols[map->type]);
568 self->origin = DSO__ORIG_KERNEL; 602 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
603 self->origin = DSO__ORIG_GUEST_KERNEL;
604 else
605 self->origin = DSO__ORIG_KERNEL;
569 606
570 return dso__split_kallsyms(self, map, filter); 607 return dso__split_kallsyms(self, map, filter);
571} 608}
@@ -952,7 +989,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
952 nr_syms = shdr.sh_size / shdr.sh_entsize; 989 nr_syms = shdr.sh_size / shdr.sh_entsize;
953 990
954 memset(&sym, 0, sizeof(sym)); 991 memset(&sym, 0, sizeof(sym));
955 if (!self->kernel) { 992 if (self->kernel == DSO_TYPE_USER) {
956 self->adjust_symbols = (ehdr.e_type == ET_EXEC || 993 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
957 elf_section_by_name(elf, &ehdr, &shdr, 994 elf_section_by_name(elf, &ehdr, &shdr,
958 ".gnu.prelink_undo", 995 ".gnu.prelink_undo",
@@ -984,7 +1021,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
984 1021
985 section_name = elf_sec__name(&shdr, secstrs); 1022 section_name = elf_sec__name(&shdr, secstrs);
986 1023
987 if (self->kernel || kmodule) { 1024 if (self->kernel != DSO_TYPE_USER || kmodule) {
988 char dso_name[PATH_MAX]; 1025 char dso_name[PATH_MAX];
989 1026
990 if (strcmp(section_name, 1027 if (strcmp(section_name,
@@ -1011,6 +1048,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
1011 curr_dso = dso__new(dso_name); 1048 curr_dso = dso__new(dso_name);
1012 if (curr_dso == NULL) 1049 if (curr_dso == NULL)
1013 goto out_elf_end; 1050 goto out_elf_end;
1051 curr_dso->kernel = self->kernel;
1014 curr_map = map__new2(start, curr_dso, 1052 curr_map = map__new2(start, curr_dso,
1015 map->type); 1053 map->type);
1016 if (curr_map == NULL) { 1054 if (curr_map == NULL) {
@@ -1021,7 +1059,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
1021 curr_map->unmap_ip = identity__map_ip; 1059 curr_map->unmap_ip = identity__map_ip;
1022 curr_dso->origin = self->origin; 1060 curr_dso->origin = self->origin;
1023 map_groups__insert(kmap->kmaps, curr_map); 1061 map_groups__insert(kmap->kmaps, curr_map);
1024 dsos__add(&dsos__kernel, curr_dso); 1062 dsos__add(&self->node, curr_dso);
1025 dso__set_loaded(curr_dso, map->type); 1063 dso__set_loaded(curr_dso, map->type);
1026 } else 1064 } else
1027 curr_dso = curr_map->dso; 1065 curr_dso = curr_map->dso;
@@ -1083,7 +1121,7 @@ static bool dso__build_id_equal(const struct dso *self, u8 *build_id)
1083 return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; 1121 return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0;
1084} 1122}
1085 1123
1086static bool __dsos__read_build_ids(struct list_head *head, bool with_hits) 1124bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1087{ 1125{
1088 bool have_build_id = false; 1126 bool have_build_id = false;
1089 struct dso *pos; 1127 struct dso *pos;
@@ -1101,13 +1139,6 @@ static bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1101 return have_build_id; 1139 return have_build_id;
1102} 1140}
1103 1141
1104bool dsos__read_build_ids(bool with_hits)
1105{
1106 bool kbuildids = __dsos__read_build_ids(&dsos__kernel, with_hits),
1107 ubuildids = __dsos__read_build_ids(&dsos__user, with_hits);
1108 return kbuildids || ubuildids;
1109}
1110
1111/* 1142/*
1112 * Align offset to 4 bytes as needed for note name and descriptor data. 1143 * Align offset to 4 bytes as needed for note name and descriptor data.
1113 */ 1144 */
@@ -1242,6 +1273,8 @@ char dso__symtab_origin(const struct dso *self)
1242 [DSO__ORIG_BUILDID] = 'b', 1273 [DSO__ORIG_BUILDID] = 'b',
1243 [DSO__ORIG_DSO] = 'd', 1274 [DSO__ORIG_DSO] = 'd',
1244 [DSO__ORIG_KMODULE] = 'K', 1275 [DSO__ORIG_KMODULE] = 'K',
1276 [DSO__ORIG_GUEST_KERNEL] = 'g',
1277 [DSO__ORIG_GUEST_KMODULE] = 'G',
1245 }; 1278 };
1246 1279
1247 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) 1280 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
@@ -1257,11 +1290,20 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1257 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1290 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1258 int ret = -1; 1291 int ret = -1;
1259 int fd; 1292 int fd;
1293 struct kernel_info *kerninfo;
1294 const char *root_dir;
1260 1295
1261 dso__set_loaded(self, map->type); 1296 dso__set_loaded(self, map->type);
1262 1297
1263 if (self->kernel) 1298 if (self->kernel == DSO_TYPE_KERNEL)
1264 return dso__load_kernel_sym(self, map, filter); 1299 return dso__load_kernel_sym(self, map, filter);
1300 else if (self->kernel == DSO_TYPE_GUEST_KERNEL)
1301 return dso__load_guest_kernel_sym(self, map, filter);
1302
1303 if (map->groups && map->groups->this_kerninfo)
1304 kerninfo = map->groups->this_kerninfo;
1305 else
1306 kerninfo = NULL;
1265 1307
1266 name = malloc(size); 1308 name = malloc(size);
1267 if (!name) 1309 if (!name)
@@ -1315,6 +1357,13 @@ more:
1315 case DSO__ORIG_DSO: 1357 case DSO__ORIG_DSO:
1316 snprintf(name, size, "%s", self->long_name); 1358 snprintf(name, size, "%s", self->long_name);
1317 break; 1359 break;
1360 case DSO__ORIG_GUEST_KMODULE:
1361 if (map->groups && map->groups->this_kerninfo)
1362 root_dir = map->groups->this_kerninfo->root_dir;
1363 else
1364 root_dir = "";
1365 snprintf(name, size, "%s%s", root_dir, self->long_name);
1366 break;
1318 1367
1319 default: 1368 default:
1320 goto out; 1369 goto out;
@@ -1368,7 +1417,8 @@ struct map *map_groups__find_by_name(struct map_groups *self,
1368 return NULL; 1417 return NULL;
1369} 1418}
1370 1419
1371static int dso__kernel_module_get_build_id(struct dso *self) 1420static int dso__kernel_module_get_build_id(struct dso *self,
1421 const char *root_dir)
1372{ 1422{
1373 char filename[PATH_MAX]; 1423 char filename[PATH_MAX];
1374 /* 1424 /*
@@ -1378,8 +1428,8 @@ static int dso__kernel_module_get_build_id(struct dso *self)
1378 const char *name = self->short_name + 1; 1428 const char *name = self->short_name + 1;
1379 1429
1380 snprintf(filename, sizeof(filename), 1430 snprintf(filename, sizeof(filename),
1381 "/sys/module/%.*s/notes/.note.gnu.build-id", 1431 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
1382 (int)strlen(name - 1), name); 1432 root_dir, (int)strlen(name) - 1, name);
1383 1433
1384 if (sysfs__read_build_id(filename, self->build_id, 1434 if (sysfs__read_build_id(filename, self->build_id,
1385 sizeof(self->build_id)) == 0) 1435 sizeof(self->build_id)) == 0)
@@ -1388,7 +1438,8 @@ static int dso__kernel_module_get_build_id(struct dso *self)
1388 return 0; 1438 return 0;
1389} 1439}
1390 1440
1391static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_name) 1441static int map_groups__set_modules_path_dir(struct map_groups *self,
1442 const char *dir_name)
1392{ 1443{
1393 struct dirent *dent; 1444 struct dirent *dent;
1394 DIR *dir = opendir(dir_name); 1445 DIR *dir = opendir(dir_name);
@@ -1400,8 +1451,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_n
1400 1451
1401 while ((dent = readdir(dir)) != NULL) { 1452 while ((dent = readdir(dir)) != NULL) {
1402 char path[PATH_MAX]; 1453 char path[PATH_MAX];
1454 struct stat st;
1455
1456 /*sshfs might return bad dent->d_type, so we have to stat*/
1457 sprintf(path, "%s/%s", dir_name, dent->d_name);
1458 if (stat(path, &st))
1459 continue;
1403 1460
1404 if (dent->d_type == DT_DIR) { 1461 if (S_ISDIR(st.st_mode)) {
1405 if (!strcmp(dent->d_name, ".") || 1462 if (!strcmp(dent->d_name, ".") ||
1406 !strcmp(dent->d_name, "..")) 1463 !strcmp(dent->d_name, ".."))
1407 continue; 1464 continue;
@@ -1433,7 +1490,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_n
1433 if (long_name == NULL) 1490 if (long_name == NULL)
1434 goto failure; 1491 goto failure;
1435 dso__set_long_name(map->dso, long_name); 1492 dso__set_long_name(map->dso, long_name);
1436 dso__kernel_module_get_build_id(map->dso); 1493 dso__kernel_module_get_build_id(map->dso, "");
1437 } 1494 }
1438 } 1495 }
1439 1496
@@ -1443,16 +1500,46 @@ failure:
1443 return -1; 1500 return -1;
1444} 1501}
1445 1502
1446static int map_groups__set_modules_path(struct map_groups *self) 1503static char *get_kernel_version(const char *root_dir)
1447{ 1504{
1448 struct utsname uts; 1505 char version[PATH_MAX];
1506 FILE *file;
1507 char *name, *tmp;
1508 const char *prefix = "Linux version ";
1509
1510 sprintf(version, "%s/proc/version", root_dir);
1511 file = fopen(version, "r");
1512 if (!file)
1513 return NULL;
1514
1515 version[0] = '\0';
1516 tmp = fgets(version, sizeof(version), file);
1517 fclose(file);
1518
1519 name = strstr(version, prefix);
1520 if (!name)
1521 return NULL;
1522 name += strlen(prefix);
1523 tmp = strchr(name, ' ');
1524 if (tmp)
1525 *tmp = '\0';
1526
1527 return strdup(name);
1528}
1529
1530static int map_groups__set_modules_path(struct map_groups *self,
1531 const char *root_dir)
1532{
1533 char *version;
1449 char modules_path[PATH_MAX]; 1534 char modules_path[PATH_MAX];
1450 1535
1451 if (uname(&uts) < 0) 1536 version = get_kernel_version(root_dir);
1537 if (!version)
1452 return -1; 1538 return -1;
1453 1539
1454 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", 1540 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
1455 uts.release); 1541 root_dir, version);
1542 free(version);
1456 1543
1457 return map_groups__set_modules_path_dir(self, modules_path); 1544 return map_groups__set_modules_path_dir(self, modules_path);
1458} 1545}
@@ -1477,11 +1564,13 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1477} 1564}
1478 1565
1479struct map *map_groups__new_module(struct map_groups *self, u64 start, 1566struct map *map_groups__new_module(struct map_groups *self, u64 start,
1480 const char *filename) 1567 const char *filename,
1568 struct kernel_info *kerninfo)
1481{ 1569{
1482 struct map *map; 1570 struct map *map;
1483 struct dso *dso = __dsos__findnew(&dsos__kernel, filename); 1571 struct dso *dso;
1484 1572
1573 dso = __dsos__findnew(&kerninfo->dsos__kernel, filename);
1485 if (dso == NULL) 1574 if (dso == NULL)
1486 return NULL; 1575 return NULL;
1487 1576
@@ -1489,21 +1578,37 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start,
1489 if (map == NULL) 1578 if (map == NULL)
1490 return NULL; 1579 return NULL;
1491 1580
1492 dso->origin = DSO__ORIG_KMODULE; 1581 if (is_host_kernel(kerninfo))
1582 dso->origin = DSO__ORIG_KMODULE;
1583 else
1584 dso->origin = DSO__ORIG_GUEST_KMODULE;
1493 map_groups__insert(self, map); 1585 map_groups__insert(self, map);
1494 return map; 1586 return map;
1495} 1587}
1496 1588
1497static int map_groups__create_modules(struct map_groups *self) 1589static int map_groups__create_modules(struct kernel_info *kerninfo)
1498{ 1590{
1499 char *line = NULL; 1591 char *line = NULL;
1500 size_t n; 1592 size_t n;
1501 FILE *file = fopen("/proc/modules", "r"); 1593 FILE *file;
1502 struct map *map; 1594 struct map *map;
1595 const char *root_dir;
1596 const char *modules;
1597 char path[PATH_MAX];
1598
1599 if (is_default_guest(kerninfo))
1600 modules = symbol_conf.default_guest_modules;
1601 else {
1602 sprintf(path, "%s/proc/modules", kerninfo->root_dir);
1603 modules = path;
1604 }
1503 1605
1606 file = fopen(modules, "r");
1504 if (file == NULL) 1607 if (file == NULL)
1505 return -1; 1608 return -1;
1506 1609
1610 root_dir = kerninfo->root_dir;
1611
1507 while (!feof(file)) { 1612 while (!feof(file)) {
1508 char name[PATH_MAX]; 1613 char name[PATH_MAX];
1509 u64 start; 1614 u64 start;
@@ -1532,16 +1637,17 @@ static int map_groups__create_modules(struct map_groups *self)
1532 *sep = '\0'; 1637 *sep = '\0';
1533 1638
1534 snprintf(name, sizeof(name), "[%s]", line); 1639 snprintf(name, sizeof(name), "[%s]", line);
1535 map = map_groups__new_module(self, start, name); 1640 map = map_groups__new_module(&kerninfo->kmaps,
1641 start, name, kerninfo);
1536 if (map == NULL) 1642 if (map == NULL)
1537 goto out_delete_line; 1643 goto out_delete_line;
1538 dso__kernel_module_get_build_id(map->dso); 1644 dso__kernel_module_get_build_id(map->dso, root_dir);
1539 } 1645 }
1540 1646
1541 free(line); 1647 free(line);
1542 fclose(file); 1648 fclose(file);
1543 1649
1544 return map_groups__set_modules_path(self); 1650 return map_groups__set_modules_path(&kerninfo->kmaps, root_dir);
1545 1651
1546out_delete_line: 1652out_delete_line:
1547 free(line); 1653 free(line);
@@ -1708,8 +1814,57 @@ out_fixup:
1708 return err; 1814 return err;
1709} 1815}
1710 1816
1711LIST_HEAD(dsos__user); 1817static int dso__load_guest_kernel_sym(struct dso *self, struct map *map,
1712LIST_HEAD(dsos__kernel); 1818 symbol_filter_t filter)
1819{
1820 int err;
1821 const char *kallsyms_filename = NULL;
1822 struct kernel_info *kerninfo;
1823 char path[PATH_MAX];
1824
1825 if (!map->groups) {
1826 pr_debug("Guest kernel map hasn't the point to groups\n");
1827 return -1;
1828 }
1829 kerninfo = map->groups->this_kerninfo;
1830
1831 if (is_default_guest(kerninfo)) {
1832 /*
1833 * if the user specified a vmlinux filename, use it and only
1834 * it, reporting errors to the user if it cannot be used.
1835 * Or use file guest_kallsyms inputted by user on commandline
1836 */
1837 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1838 err = dso__load_vmlinux(self, map,
1839 symbol_conf.default_guest_vmlinux_name, filter);
1840 goto out_try_fixup;
1841 }
1842
1843 kallsyms_filename = symbol_conf.default_guest_kallsyms;
1844 if (!kallsyms_filename)
1845 return -1;
1846 } else {
1847 sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir);
1848 kallsyms_filename = path;
1849 }
1850
1851 err = dso__load_kallsyms(self, kallsyms_filename, map, filter);
1852 if (err > 0)
1853 pr_debug("Using %s for symbols\n", kallsyms_filename);
1854
1855out_try_fixup:
1856 if (err > 0) {
1857 if (kallsyms_filename != NULL) {
1858 kern_mmap_name(kerninfo, path);
1859 dso__set_long_name(self,
1860 strdup(path));
1861 }
1862 map__fixup_start(map);
1863 map__fixup_end(map);
1864 }
1865
1866 return err;
1867}
1713 1868
1714static void dsos__add(struct list_head *head, struct dso *dso) 1869static void dsos__add(struct list_head *head, struct dso *dso)
1715{ 1870{
@@ -1752,10 +1907,16 @@ static void __dsos__fprintf(struct list_head *head, FILE *fp)
1752 } 1907 }
1753} 1908}
1754 1909
1755void dsos__fprintf(FILE *fp) 1910void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp)
1756{ 1911{
1757 __dsos__fprintf(&dsos__kernel, fp); 1912 struct rb_node *nd;
1758 __dsos__fprintf(&dsos__user, fp); 1913
1914 for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) {
1915 struct kernel_info *pos = rb_entry(nd, struct kernel_info,
1916 rb_node);
1917 __dsos__fprintf(&pos->dsos__kernel, fp);
1918 __dsos__fprintf(&pos->dsos__user, fp);
1919 }
1759} 1920}
1760 1921
1761static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 1922static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
@@ -1773,10 +1934,21 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
1773 return ret; 1934 return ret;
1774} 1935}
1775 1936
1776size_t dsos__fprintf_buildid(FILE *fp, bool with_hits) 1937size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root,
1938 FILE *fp, bool with_hits)
1777{ 1939{
1778 return (__dsos__fprintf_buildid(&dsos__kernel, fp, with_hits) + 1940 struct rb_node *nd;
1779 __dsos__fprintf_buildid(&dsos__user, fp, with_hits)); 1941 size_t ret = 0;
1942
1943 for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) {
1944 struct kernel_info *pos = rb_entry(nd, struct kernel_info,
1945 rb_node);
1946 ret += __dsos__fprintf_buildid(&pos->dsos__kernel,
1947 fp, with_hits);
1948 ret += __dsos__fprintf_buildid(&pos->dsos__user,
1949 fp, with_hits);
1950 }
1951 return ret;
1780} 1952}
1781 1953
1782struct dso *dso__new_kernel(const char *name) 1954struct dso *dso__new_kernel(const char *name)
@@ -1785,28 +1957,59 @@ struct dso *dso__new_kernel(const char *name)
1785 1957
1786 if (self != NULL) { 1958 if (self != NULL) {
1787 dso__set_short_name(self, "[kernel]"); 1959 dso__set_short_name(self, "[kernel]");
1788 self->kernel = 1; 1960 self->kernel = DSO_TYPE_KERNEL;
1961 }
1962
1963 return self;
1964}
1965
1966static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo,
1967 const char *name)
1968{
1969 char buff[PATH_MAX];
1970 struct dso *self;
1971
1972 kern_mmap_name(kerninfo, buff);
1973 self = dso__new(name ?: buff);
1974 if (self != NULL) {
1975 dso__set_short_name(self, "[guest.kernel]");
1976 self->kernel = DSO_TYPE_GUEST_KERNEL;
1789 } 1977 }
1790 1978
1791 return self; 1979 return self;
1792} 1980}
1793 1981
1794void dso__read_running_kernel_build_id(struct dso *self) 1982void dso__read_running_kernel_build_id(struct dso *self,
1983 struct kernel_info *kerninfo)
1795{ 1984{
1796 if (sysfs__read_build_id("/sys/kernel/notes", self->build_id, 1985 char path[PATH_MAX];
1986
1987 if (is_default_guest(kerninfo))
1988 return;
1989 sprintf(path, "%s/sys/kernel/notes", kerninfo->root_dir);
1990 if (sysfs__read_build_id(path, self->build_id,
1797 sizeof(self->build_id)) == 0) 1991 sizeof(self->build_id)) == 0)
1798 self->has_build_id = true; 1992 self->has_build_id = true;
1799} 1993}
1800 1994
1801static struct dso *dsos__create_kernel(const char *vmlinux) 1995static struct dso *dsos__create_kernel(struct kernel_info *kerninfo)
1802{ 1996{
1803 struct dso *kernel = dso__new_kernel(vmlinux); 1997 const char *vmlinux_name = NULL;
1998 struct dso *kernel;
1804 1999
1805 if (kernel != NULL) { 2000 if (is_host_kernel(kerninfo)) {
1806 dso__read_running_kernel_build_id(kernel); 2001 vmlinux_name = symbol_conf.vmlinux_name;
1807 dsos__add(&dsos__kernel, kernel); 2002 kernel = dso__new_kernel(vmlinux_name);
2003 } else {
2004 if (is_default_guest(kerninfo))
2005 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
2006 kernel = dso__new_guest_kernel(kerninfo, vmlinux_name);
1808 } 2007 }
1809 2008
2009 if (kernel != NULL) {
2010 dso__read_running_kernel_build_id(kernel, kerninfo);
2011 dsos__add(&kerninfo->dsos__kernel, kernel);
2012 }
1810 return kernel; 2013 return kernel;
1811} 2014}
1812 2015
@@ -1950,23 +2153,29 @@ out_free_comm_list:
1950 return -1; 2153 return -1;
1951} 2154}
1952 2155
1953int map_groups__create_kernel_maps(struct map_groups *self, 2156int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid)
1954 struct map *vmlinux_maps[MAP__NR_TYPES])
1955{ 2157{
1956 struct dso *kernel = dsos__create_kernel(symbol_conf.vmlinux_name); 2158 struct kernel_info *kerninfo;
2159 struct dso *kernel;
1957 2160
2161 kerninfo = kerninfo__findnew(kerninfo_root, pid);
2162 if (kerninfo == NULL)
2163 return -1;
2164 kernel = dsos__create_kernel(kerninfo);
1958 if (kernel == NULL) 2165 if (kernel == NULL)
1959 return -1; 2166 return -1;
1960 2167
1961 if (__map_groups__create_kernel_maps(self, vmlinux_maps, kernel) < 0) 2168 if (__map_groups__create_kernel_maps(&kerninfo->kmaps,
2169 kerninfo->vmlinux_maps, kernel) < 0)
1962 return -1; 2170 return -1;
1963 2171
1964 if (symbol_conf.use_modules && map_groups__create_modules(self) < 0) 2172 if (symbol_conf.use_modules &&
2173 map_groups__create_modules(kerninfo) < 0)
1965 pr_debug("Problems creating module maps, continuing anyway...\n"); 2174 pr_debug("Problems creating module maps, continuing anyway...\n");
1966 /* 2175 /*
1967 * Now that we have all the maps created, just set the ->end of them: 2176 * Now that we have all the maps created, just set the ->end of them:
1968 */ 2177 */
1969 map_groups__fixup_end(self); 2178 map_groups__fixup_end(&kerninfo->kmaps);
1970 return 0; 2179 return 0;
1971} 2180}
1972 2181
@@ -2012,3 +2221,46 @@ char *strxfrchar(char *s, char from, char to)
2012 2221
2013 return s; 2222 return s;
2014} 2223}
2224
2225int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root)
2226{
2227 int ret = 0;
2228 struct dirent **namelist = NULL;
2229 int i, items = 0;
2230 char path[PATH_MAX];
2231 pid_t pid;
2232
2233 if (symbol_conf.default_guest_vmlinux_name ||
2234 symbol_conf.default_guest_modules ||
2235 symbol_conf.default_guest_kallsyms) {
2236 map_groups__create_kernel_maps(kerninfo_root,
2237 DEFAULT_GUEST_KERNEL_ID);
2238 }
2239
2240 if (symbol_conf.guestmount) {
2241 items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
2242 if (items <= 0)
2243 return -ENOENT;
2244 for (i = 0; i < items; i++) {
2245 if (!isdigit(namelist[i]->d_name[0])) {
2246 /* Filter out . and .. */
2247 continue;
2248 }
2249 pid = atoi(namelist[i]->d_name);
2250 sprintf(path, "%s/%s/proc/kallsyms",
2251 symbol_conf.guestmount,
2252 namelist[i]->d_name);
2253 ret = access(path, R_OK);
2254 if (ret) {
2255 pr_debug("Can't access file %s\n", path);
2256 goto failure;
2257 }
2258 map_groups__create_kernel_maps(kerninfo_root,
2259 pid);
2260 }
2261failure:
2262 free(namelist);
2263 }
2264
2265 return ret;
2266}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 757fae3f5ee0..478f5ab37787 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -69,10 +69,15 @@ struct symbol_conf {
69 show_nr_samples, 69 show_nr_samples,
70 use_callchain, 70 use_callchain,
71 exclude_other, 71 exclude_other,
72 full_paths; 72 full_paths,
73 show_cpu_utilization;
73 const char *vmlinux_name, 74 const char *vmlinux_name,
74 *field_sep; 75 *field_sep;
75 char *dso_list_str, 76 const char *default_guest_vmlinux_name,
77 *default_guest_kallsyms,
78 *default_guest_modules;
79 const char *guestmount;
80 char *dso_list_str,
76 *comm_list_str, 81 *comm_list_str,
77 *sym_list_str, 82 *sym_list_str,
78 *col_width_list_str; 83 *col_width_list_str;
@@ -106,6 +111,13 @@ struct addr_location {
106 u64 addr; 111 u64 addr;
107 char level; 112 char level;
108 bool filtered; 113 bool filtered;
114 unsigned int cpumode;
115};
116
117enum dso_kernel_type {
118 DSO_TYPE_USER = 0,
119 DSO_TYPE_KERNEL,
120 DSO_TYPE_GUEST_KERNEL
109}; 121};
110 122
111struct dso { 123struct dso {
@@ -115,7 +127,7 @@ struct dso {
115 u8 adjust_symbols:1; 127 u8 adjust_symbols:1;
116 u8 slen_calculated:1; 128 u8 slen_calculated:1;
117 u8 has_build_id:1; 129 u8 has_build_id:1;
118 u8 kernel:1; 130 enum dso_kernel_type kernel;
119 u8 hit:1; 131 u8 hit:1;
120 u8 annotate_warned:1; 132 u8 annotate_warned:1;
121 unsigned char origin; 133 unsigned char origin;
@@ -143,34 +155,30 @@ static inline void dso__set_loaded(struct dso *self, enum map_type type)
143 155
144void dso__sort_by_name(struct dso *self, enum map_type type); 156void dso__sort_by_name(struct dso *self, enum map_type type);
145 157
146extern struct list_head dsos__user, dsos__kernel;
147
148struct dso *__dsos__findnew(struct list_head *head, const char *name); 158struct dso *__dsos__findnew(struct list_head *head, const char *name);
149 159
150static inline struct dso *dsos__findnew(const char *name)
151{
152 return __dsos__findnew(&dsos__user, name);
153}
154
155int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); 160int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
156int dso__load_vmlinux_path(struct dso *self, struct map *map, 161int dso__load_vmlinux_path(struct dso *self, struct map *map,
157 symbol_filter_t filter); 162 symbol_filter_t filter);
158int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, 163int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,
159 symbol_filter_t filter); 164 symbol_filter_t filter);
160void dsos__fprintf(FILE *fp); 165void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp);
161size_t dsos__fprintf_buildid(FILE *fp, bool with_hits); 166size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root,
167 FILE *fp, bool with_hits);
162 168
163size_t dso__fprintf_buildid(struct dso *self, FILE *fp); 169size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
164size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); 170size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
165 171
166enum dso_origin { 172enum dso_origin {
167 DSO__ORIG_KERNEL = 0, 173 DSO__ORIG_KERNEL = 0,
174 DSO__ORIG_GUEST_KERNEL,
168 DSO__ORIG_JAVA_JIT, 175 DSO__ORIG_JAVA_JIT,
169 DSO__ORIG_BUILD_ID_CACHE, 176 DSO__ORIG_BUILD_ID_CACHE,
170 DSO__ORIG_FEDORA, 177 DSO__ORIG_FEDORA,
171 DSO__ORIG_UBUNTU, 178 DSO__ORIG_UBUNTU,
172 DSO__ORIG_BUILDID, 179 DSO__ORIG_BUILDID,
173 DSO__ORIG_DSO, 180 DSO__ORIG_DSO,
181 DSO__ORIG_GUEST_KMODULE,
174 DSO__ORIG_KMODULE, 182 DSO__ORIG_KMODULE,
175 DSO__ORIG_NOT_FOUND, 183 DSO__ORIG_NOT_FOUND,
176}; 184};
@@ -178,19 +186,26 @@ enum dso_origin {
178char dso__symtab_origin(const struct dso *self); 186char dso__symtab_origin(const struct dso *self);
179void dso__set_long_name(struct dso *self, char *name); 187void dso__set_long_name(struct dso *self, char *name);
180void dso__set_build_id(struct dso *self, void *build_id); 188void dso__set_build_id(struct dso *self, void *build_id);
181void dso__read_running_kernel_build_id(struct dso *self); 189void dso__read_running_kernel_build_id(struct dso *self,
190 struct kernel_info *kerninfo);
182struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); 191struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr);
183struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, 192struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type,
184 const char *name); 193 const char *name);
185 194
186int filename__read_build_id(const char *filename, void *bf, size_t size); 195int filename__read_build_id(const char *filename, void *bf, size_t size);
187int sysfs__read_build_id(const char *filename, void *bf, size_t size); 196int sysfs__read_build_id(const char *filename, void *bf, size_t size);
188bool dsos__read_build_ids(bool with_hits); 197bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
189int build_id__sprintf(const u8 *self, int len, char *bf); 198int build_id__sprintf(const u8 *self, int len, char *bf);
190int kallsyms__parse(const char *filename, void *arg, 199int kallsyms__parse(const char *filename, void *arg,
191 int (*process_symbol)(void *arg, const char *name, 200 int (*process_symbol)(void *arg, const char *name,
192 char type, u64 start)); 201 char type, u64 start));
193 202
203int __map_groups__create_kernel_maps(struct map_groups *self,
204 struct map *vmlinux_maps[MAP__NR_TYPES],
205 struct dso *kernel);
206int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid);
207int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root);
208
194int symbol__init(void); 209int symbol__init(void);
195bool symbol_type__is_a(char symbol_type, enum map_type map_type); 210bool symbol_type__is_a(char symbol_type, enum map_type map_type);
196 211
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 9c488fcadec9..1dfd9ff8bdcd 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -33,12 +33,12 @@ static inline struct map *thread__find_map(struct thread *self,
33 33
34void thread__find_addr_map(struct thread *self, 34void thread__find_addr_map(struct thread *self,
35 struct perf_session *session, u8 cpumode, 35 struct perf_session *session, u8 cpumode,
36 enum map_type type, u64 addr, 36 enum map_type type, pid_t pid, u64 addr,
37 struct addr_location *al); 37 struct addr_location *al);
38 38
39void thread__find_addr_location(struct thread *self, 39void thread__find_addr_location(struct thread *self,
40 struct perf_session *session, u8 cpumode, 40 struct perf_session *session, u8 cpumode,
41 enum map_type type, u64 addr, 41 enum map_type type, pid_t pid, u64 addr,
42 struct addr_location *al, 42 struct addr_location *al,
43 symbol_filter_t filter); 43 symbol_filter_t filter);
44#endif /* __PERF_THREAD_H */ 44#endif /* __PERF_THREAD_H */