diff options
-rw-r--r-- | tools/perf/Makefile | 2 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 9 | ||||
-rw-r--r-- | tools/perf/util/newt.c | 185 |
3 files changed, 109 insertions, 87 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 6aa2fe323db1..17a3692397c5 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -577,7 +577,7 @@ ifdef NO_LIBPERL | |||
577 | else | 577 | else |
578 | PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null` | 578 | PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null` |
579 | PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` | 579 | PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` |
580 | PERL_EMBED_FLAGS=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) | 580 | FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) |
581 | 581 | ||
582 | ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED)),y) | 582 | ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED)),y) |
583 | BASIC_CFLAGS += -DNO_LIBPERL | 583 | BASIC_CFLAGS += -DNO_LIBPERL |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 86b1c3b6264e..0df64088135f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -445,8 +445,6 @@ static void atexit_header(void) | |||
445 | static void event__synthesize_guest_os(struct machine *machine, void *data) | 445 | static void event__synthesize_guest_os(struct machine *machine, void *data) |
446 | { | 446 | { |
447 | int err; | 447 | int err; |
448 | char *guest_kallsyms; | ||
449 | char path[PATH_MAX]; | ||
450 | struct perf_session *psession = data; | 448 | struct perf_session *psession = data; |
451 | 449 | ||
452 | if (machine__is_host(machine)) | 450 | if (machine__is_host(machine)) |
@@ -466,13 +464,6 @@ static void event__synthesize_guest_os(struct machine *machine, void *data) | |||
466 | pr_err("Couldn't record guest kernel [%d]'s reference" | 464 | pr_err("Couldn't record guest kernel [%d]'s reference" |
467 | " relocation symbol.\n", machine->pid); | 465 | " relocation symbol.\n", machine->pid); |
468 | 466 | ||
469 | if (machine__is_default_guest(machine)) | ||
470 | guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms; | ||
471 | else { | ||
472 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); | ||
473 | guest_kallsyms = path; | ||
474 | } | ||
475 | |||
476 | /* | 467 | /* |
477 | * We use _stext for guest kernel because guest kernel's /proc/kallsyms | 468 | * We use _stext for guest kernel because guest kernel's /proc/kallsyms |
478 | * have no _text sometimes. | 469 | * have no _text sometimes. |
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index cf182ca132fe..7bdbfd3e24d2 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c | |||
@@ -267,9 +267,48 @@ struct ui_browser { | |||
267 | void *first_visible_entry, *entries; | 267 | void *first_visible_entry, *entries; |
268 | u16 top, left, width, height; | 268 | u16 top, left, width, height; |
269 | void *priv; | 269 | void *priv; |
270 | unsigned int (*refresh_entries)(struct ui_browser *self); | ||
271 | void (*seek)(struct ui_browser *self, | ||
272 | off_t offset, int whence); | ||
270 | u32 nr_entries; | 273 | u32 nr_entries; |
271 | }; | 274 | }; |
272 | 275 | ||
276 | static void ui_browser__list_head_seek(struct ui_browser *self, | ||
277 | off_t offset, int whence) | ||
278 | { | ||
279 | struct list_head *head = self->entries; | ||
280 | struct list_head *pos; | ||
281 | |||
282 | switch (whence) { | ||
283 | case SEEK_SET: | ||
284 | pos = head->next; | ||
285 | break; | ||
286 | case SEEK_CUR: | ||
287 | pos = self->first_visible_entry; | ||
288 | break; | ||
289 | case SEEK_END: | ||
290 | pos = head->prev; | ||
291 | break; | ||
292 | default: | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | if (offset > 0) { | ||
297 | while (offset-- != 0) | ||
298 | pos = pos->next; | ||
299 | } else { | ||
300 | while (offset++ != 0) | ||
301 | pos = pos->prev; | ||
302 | } | ||
303 | |||
304 | self->first_visible_entry = pos; | ||
305 | } | ||
306 | |||
307 | static bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row) | ||
308 | { | ||
309 | return (self->first_visible_entry_idx + row) == self->index; | ||
310 | } | ||
311 | |||
273 | static void ui_browser__refresh_dimensions(struct ui_browser *self) | 312 | static void ui_browser__refresh_dimensions(struct ui_browser *self) |
274 | { | 313 | { |
275 | int cols, rows; | 314 | int cols, rows; |
@@ -286,8 +325,34 @@ static void ui_browser__refresh_dimensions(struct ui_browser *self) | |||
286 | 325 | ||
287 | static void ui_browser__reset_index(struct ui_browser *self) | 326 | static void ui_browser__reset_index(struct ui_browser *self) |
288 | { | 327 | { |
289 | self->index = self->first_visible_entry_idx = 0; | 328 | self->index = self->first_visible_entry_idx = 0; |
290 | self->first_visible_entry = NULL; | 329 | self->seek(self, 0, SEEK_SET); |
330 | } | ||
331 | |||
332 | static int ui_browser__show(struct ui_browser *self, const char *title) | ||
333 | { | ||
334 | if (self->form != NULL) | ||
335 | return 0; | ||
336 | ui_browser__refresh_dimensions(self); | ||
337 | newtCenteredWindow(self->width + 2, self->height, title); | ||
338 | self->form = newt_form__new(); | ||
339 | if (self->form == NULL) | ||
340 | return -1; | ||
341 | |||
342 | self->sb = newtVerticalScrollbar(self->width + 1, 0, self->height, | ||
343 | HE_COLORSET_NORMAL, | ||
344 | HE_COLORSET_SELECTED); | ||
345 | if (self->sb == NULL) | ||
346 | return -1; | ||
347 | |||
348 | newtFormAddHotKey(self->form, NEWT_KEY_UP); | ||
349 | newtFormAddHotKey(self->form, NEWT_KEY_DOWN); | ||
350 | newtFormAddHotKey(self->form, NEWT_KEY_PGUP); | ||
351 | newtFormAddHotKey(self->form, NEWT_KEY_PGDN); | ||
352 | newtFormAddHotKey(self->form, NEWT_KEY_HOME); | ||
353 | newtFormAddHotKey(self->form, NEWT_KEY_END); | ||
354 | newtFormAddComponent(self->form, self->sb); | ||
355 | return 0; | ||
291 | } | 356 | } |
292 | 357 | ||
293 | static int objdump_line__show(struct objdump_line *self, struct list_head *head, | 358 | static int objdump_line__show(struct objdump_line *self, struct list_head *head, |
@@ -341,26 +406,10 @@ static int objdump_line__show(struct objdump_line *self, struct list_head *head, | |||
341 | 406 | ||
342 | static int ui_browser__refresh_entries(struct ui_browser *self) | 407 | static int ui_browser__refresh_entries(struct ui_browser *self) |
343 | { | 408 | { |
344 | struct objdump_line *pos; | 409 | int row; |
345 | struct list_head *head = self->entries; | ||
346 | struct hist_entry *he = self->priv; | ||
347 | int row = 0; | ||
348 | int len = he->ms.sym->end - he->ms.sym->start; | ||
349 | |||
350 | if (self->first_visible_entry == NULL || self->first_visible_entry == self->entries) | ||
351 | self->first_visible_entry = head->next; | ||
352 | |||
353 | pos = list_entry(self->first_visible_entry, struct objdump_line, node); | ||
354 | |||
355 | list_for_each_entry_from(pos, head, node) { | ||
356 | bool current_entry = (self->first_visible_entry_idx + row) == self->index; | ||
357 | SLsmg_gotorc(self->top + row, self->left); | ||
358 | objdump_line__show(pos, head, self->width, | ||
359 | he, len, current_entry); | ||
360 | if (++row == self->height) | ||
361 | break; | ||
362 | } | ||
363 | 410 | ||
411 | newtScrollbarSet(self->sb, self->index, self->nr_entries - 1); | ||
412 | row = self->refresh_entries(self); | ||
364 | SLsmg_set_color(HE_COLORSET_NORMAL); | 413 | SLsmg_set_color(HE_COLORSET_NORMAL); |
365 | SLsmg_fill_region(self->top + row, self->left, | 414 | SLsmg_fill_region(self->top + row, self->left, |
366 | self->height - row, self->width, ' '); | 415 | self->height - row, self->width, ' '); |
@@ -368,42 +417,13 @@ static int ui_browser__refresh_entries(struct ui_browser *self) | |||
368 | return 0; | 417 | return 0; |
369 | } | 418 | } |
370 | 419 | ||
371 | static int ui_browser__run(struct ui_browser *self, const char *title, | 420 | static int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es) |
372 | struct newtExitStruct *es) | ||
373 | { | 421 | { |
374 | if (self->form) { | ||
375 | newtFormDestroy(self->form); | ||
376 | newtPopWindow(); | ||
377 | } | ||
378 | |||
379 | ui_browser__refresh_dimensions(self); | ||
380 | newtCenteredWindow(self->width + 2, self->height, title); | ||
381 | self->form = newt_form__new(); | ||
382 | if (self->form == NULL) | ||
383 | return -1; | ||
384 | |||
385 | self->sb = newtVerticalScrollbar(self->width + 1, 0, self->height, | ||
386 | HE_COLORSET_NORMAL, | ||
387 | HE_COLORSET_SELECTED); | ||
388 | if (self->sb == NULL) | ||
389 | return -1; | ||
390 | |||
391 | newtFormAddHotKey(self->form, NEWT_KEY_UP); | ||
392 | newtFormAddHotKey(self->form, NEWT_KEY_DOWN); | ||
393 | newtFormAddHotKey(self->form, NEWT_KEY_PGUP); | ||
394 | newtFormAddHotKey(self->form, NEWT_KEY_PGDN); | ||
395 | newtFormAddHotKey(self->form, ' '); | ||
396 | newtFormAddHotKey(self->form, NEWT_KEY_HOME); | ||
397 | newtFormAddHotKey(self->form, NEWT_KEY_END); | ||
398 | newtFormAddHotKey(self->form, NEWT_KEY_TAB); | ||
399 | newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); | ||
400 | |||
401 | if (ui_browser__refresh_entries(self) < 0) | 422 | if (ui_browser__refresh_entries(self) < 0) |
402 | return -1; | 423 | return -1; |
403 | newtFormAddComponent(self->form, self->sb); | ||
404 | 424 | ||
405 | while (1) { | 425 | while (1) { |
406 | unsigned int offset; | 426 | off_t offset; |
407 | 427 | ||
408 | newtFormRun(self->form, es); | 428 | newtFormRun(self->form, es); |
409 | 429 | ||
@@ -417,9 +437,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title, | |||
417 | break; | 437 | break; |
418 | ++self->index; | 438 | ++self->index; |
419 | if (self->index == self->first_visible_entry_idx + self->height) { | 439 | if (self->index == self->first_visible_entry_idx + self->height) { |
420 | struct list_head *pos = self->first_visible_entry; | ||
421 | ++self->first_visible_entry_idx; | 440 | ++self->first_visible_entry_idx; |
422 | self->first_visible_entry = pos->next; | 441 | self->seek(self, +1, SEEK_CUR); |
423 | } | 442 | } |
424 | break; | 443 | break; |
425 | case NEWT_KEY_UP: | 444 | case NEWT_KEY_UP: |
@@ -427,9 +446,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title, | |||
427 | break; | 446 | break; |
428 | --self->index; | 447 | --self->index; |
429 | if (self->index < self->first_visible_entry_idx) { | 448 | if (self->index < self->first_visible_entry_idx) { |
430 | struct list_head *pos = self->first_visible_entry; | ||
431 | --self->first_visible_entry_idx; | 449 | --self->first_visible_entry_idx; |
432 | self->first_visible_entry = pos->prev; | 450 | self->seek(self, -1, SEEK_CUR); |
433 | } | 451 | } |
434 | break; | 452 | break; |
435 | case NEWT_KEY_PGDN: | 453 | case NEWT_KEY_PGDN: |
@@ -442,12 +460,7 @@ static int ui_browser__run(struct ui_browser *self, const char *title, | |||
442 | offset = self->nr_entries - 1 - self->index; | 460 | offset = self->nr_entries - 1 - self->index; |
443 | self->index += offset; | 461 | self->index += offset; |
444 | self->first_visible_entry_idx += offset; | 462 | self->first_visible_entry_idx += offset; |
445 | 463 | self->seek(self, +offset, SEEK_CUR); | |
446 | while (offset--) { | ||
447 | struct list_head *pos = self->first_visible_entry; | ||
448 | self->first_visible_entry = pos->next; | ||
449 | } | ||
450 | |||
451 | break; | 464 | break; |
452 | case NEWT_KEY_PGUP: | 465 | case NEWT_KEY_PGUP: |
453 | if (self->first_visible_entry_idx == 0) | 466 | if (self->first_visible_entry_idx == 0) |
@@ -460,29 +473,19 @@ static int ui_browser__run(struct ui_browser *self, const char *title, | |||
460 | 473 | ||
461 | self->index -= offset; | 474 | self->index -= offset; |
462 | self->first_visible_entry_idx -= offset; | 475 | self->first_visible_entry_idx -= offset; |
463 | 476 | self->seek(self, -offset, SEEK_CUR); | |
464 | while (offset--) { | ||
465 | struct list_head *pos = self->first_visible_entry; | ||
466 | self->first_visible_entry = pos->prev; | ||
467 | } | ||
468 | break; | 477 | break; |
469 | case NEWT_KEY_HOME: | 478 | case NEWT_KEY_HOME: |
470 | ui_browser__reset_index(self); | 479 | ui_browser__reset_index(self); |
471 | break; | 480 | break; |
472 | case NEWT_KEY_END: { | 481 | case NEWT_KEY_END: |
473 | struct list_head *head = self->entries; | ||
474 | offset = self->height - 1; | 482 | offset = self->height - 1; |
475 | 483 | ||
476 | if (offset > self->nr_entries) | 484 | if (offset > self->nr_entries) |
477 | offset = self->nr_entries; | 485 | offset = self->nr_entries; |
478 | 486 | ||
479 | self->index = self->first_visible_entry_idx = self->nr_entries - 1 - offset; | 487 | self->index = self->first_visible_entry_idx = self->nr_entries - 1 - offset; |
480 | self->first_visible_entry = head->prev; | 488 | self->seek(self, -offset, SEEK_END); |
481 | while (offset-- != 0) { | ||
482 | struct list_head *pos = self->first_visible_entry; | ||
483 | self->first_visible_entry = pos->prev; | ||
484 | } | ||
485 | } | ||
486 | break; | 489 | break; |
487 | case NEWT_KEY_RIGHT: | 490 | case NEWT_KEY_RIGHT: |
488 | case NEWT_KEY_LEFT: | 491 | case NEWT_KEY_LEFT: |
@@ -539,6 +542,31 @@ static char *callchain_list__sym_name(struct callchain_list *self, | |||
539 | return bf; | 542 | return bf; |
540 | } | 543 | } |
541 | 544 | ||
545 | static unsigned int hist_entry__annotate_browser_refresh(struct ui_browser *self) | ||
546 | { | ||
547 | struct objdump_line *pos; | ||
548 | struct list_head *head = self->entries; | ||
549 | struct hist_entry *he = self->priv; | ||
550 | int row = 0; | ||
551 | int len = he->ms.sym->end - he->ms.sym->start; | ||
552 | |||
553 | if (self->first_visible_entry == NULL || self->first_visible_entry == self->entries) | ||
554 | self->first_visible_entry = head->next; | ||
555 | |||
556 | pos = list_entry(self->first_visible_entry, struct objdump_line, node); | ||
557 | |||
558 | list_for_each_entry_from(pos, head, node) { | ||
559 | bool current_entry = ui_browser__is_current_entry(self, row); | ||
560 | SLsmg_gotorc(self->top + row, self->left); | ||
561 | objdump_line__show(pos, head, self->width, | ||
562 | he, len, current_entry); | ||
563 | if (++row == self->height) | ||
564 | break; | ||
565 | } | ||
566 | |||
567 | return row; | ||
568 | } | ||
569 | |||
542 | static void __callchain__append_graph_browser(struct callchain_node *self, | 570 | static void __callchain__append_graph_browser(struct callchain_node *self, |
543 | newtComponent tree, u64 total, | 571 | newtComponent tree, u64 total, |
544 | int *indexes, int depth) | 572 | int *indexes, int depth) |
@@ -701,7 +729,9 @@ int hist_entry__tui_annotate(struct hist_entry *self) | |||
701 | ui_helpline__push("Press <- or ESC to exit"); | 729 | ui_helpline__push("Press <- or ESC to exit"); |
702 | 730 | ||
703 | memset(&browser, 0, sizeof(browser)); | 731 | memset(&browser, 0, sizeof(browser)); |
704 | browser.entries = &head; | 732 | browser.entries = &head; |
733 | browser.refresh_entries = hist_entry__annotate_browser_refresh; | ||
734 | browser.seek = ui_browser__list_head_seek; | ||
705 | browser.priv = self; | 735 | browser.priv = self; |
706 | list_for_each_entry(pos, &head, node) { | 736 | list_for_each_entry(pos, &head, node) { |
707 | size_t line_len = strlen(pos->line); | 737 | size_t line_len = strlen(pos->line); |
@@ -711,7 +741,8 @@ int hist_entry__tui_annotate(struct hist_entry *self) | |||
711 | } | 741 | } |
712 | 742 | ||
713 | browser.width += 18; /* Percentage */ | 743 | browser.width += 18; /* Percentage */ |
714 | ret = ui_browser__run(&browser, self->ms.sym->name, &es); | 744 | ui_browser__show(&browser, self->ms.sym->name); |
745 | ui_browser__run(&browser, &es); | ||
715 | newtFormDestroy(browser.form); | 746 | newtFormDestroy(browser.form); |
716 | newtPopWindow(); | 747 | newtPopWindow(); |
717 | list_for_each_entry_safe(pos, n, &head, node) { | 748 | list_for_each_entry_safe(pos, n, &head, node) { |