aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/builtin-record.c9
-rw-r--r--tools/perf/util/newt.c185
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
577else 577else
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)
445static void event__synthesize_guest_os(struct machine *machine, void *data) 445static 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
276static 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
307static 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
273static void ui_browser__refresh_dimensions(struct ui_browser *self) 312static 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
287static void ui_browser__reset_index(struct ui_browser *self) 326static 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
332static 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
293static int objdump_line__show(struct objdump_line *self, struct list_head *head, 358static 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
342static int ui_browser__refresh_entries(struct ui_browser *self) 407static 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
371static int ui_browser__run(struct ui_browser *self, const char *title, 420static 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
545static 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
542static void __callchain__append_graph_browser(struct callchain_node *self, 570static 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) {