cregit-Linux how code gets into the kernel

Release 4.10 tools/perf/ui/browsers/annotate.c

#include "../../util/util.h"
#include "../browser.h"
#include "../helpline.h"
#include "../ui.h"
#include "../util.h"
#include "../../util/annotate.h"
#include "../../util/hist.h"
#include "../../util/sort.h"
#include "../../util/symbol.h"
#include "../../util/evsel.h"
#include "../../util/config.h"
#include <pthread.h>


struct disasm_line_samples {
	
double		percent;
	
u64		nr;
};


#define IPC_WIDTH 6

#define CYCLES_WIDTH 6


struct browser_disasm_line {
	
struct rb_node			rb_node;
	
u32				idx;
	
int				idx_asm;
	
int				jump_sources;
	/*
         * actual length of this array is saved on the nr_events field
         * of the struct annotate_browser
         */
	
struct disasm_line_samples	samples[1];
};


static struct annotate_browser_opt {
	
bool hide_src_code,
	     
use_offset,
	     
jump_arrows,
	     
show_linenr,
	     
show_nr_jumps,
	     
show_total_period;
} 
annotate_browser__opts = {
	.use_offset	= true,
	.jump_arrows	= true,
};


struct annotate_browser {
	
struct ui_browser b;
	
struct rb_root	  entries;
	
struct rb_node	  *curr_hot;
	
struct disasm_line  *selection;
	
struct disasm_line  **offsets;
	
int		    nr_events;
	
u64		    start;
	
int		    nr_asm_entries;
	
int		    nr_entries;
	
int		    max_jump_sources;
	
int		    nr_jumps;
	
bool		    searching_backwards;
	
bool		    have_cycles;
	
u8		    addr_width;
	
u8		    jumps_width;
	
u8		    target_width;
	
u8		    min_addr_width;
	
u8		    max_addr_width;
	
char		    search_bf[128];
};


static inline struct browser_disasm_line *disasm_line__browser(struct disasm_line *dl) { return (struct browser_disasm_line *)(dl + 1); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo26100.00%3100.00%
Total26100.00%3100.00%


static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, void *entry) { if (annotate_browser__opts.hide_src_code) { struct disasm_line *dl = list_entry(entry, struct disasm_line, node); return dl->offset == -1; } return false; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo4998.00%375.00%
irina tirdeairina tirdea12.00%125.00%
Total50100.00%4100.00%


static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, int nr, bool current) { if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) return HE_COLORSET_SELECTED; if (nr == browser->max_jump_sources) return HE_COLORSET_TOP; if (nr > 1) return HE_COLORSET_MEDIUM; return HE_COLORSET_NORMAL; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo62100.00%1100.00%
Total62100.00%1100.00%


static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, int nr, bool current) { int color = annotate_browser__jumps_percent_color(browser, nr, current); return ui_browser__set_color(&browser->b, color); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo40100.00%1100.00%
Total40100.00%1100.00%


static int annotate_browser__pcnt_width(struct annotate_browser *ab) { int w = 7 * ab->nr_events; if (ab->have_cycles) w += IPC_WIDTH + CYCLES_WIDTH; return w; }

Contributors

PersonTokensPropCommitsCommitProp
andi kleenandi kleen35100.00%1100.00%
Total35100.00%1100.00%


static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); struct disasm_line *dl = list_entry(entry, struct disasm_line, node); struct browser_disasm_line *bdl = disasm_line__browser(dl); bool current_entry = ui_browser__is_current_entry(browser, row); bool change_color = (!annotate_browser__opts.hide_src_code && (!current_entry || (browser->use_navkeypressed && !browser->navkeypressed))); int width = browser->width, printed; int i, pcnt_width = annotate_browser__pcnt_width(ab); double percent_max = 0.0; char bf[256]; for (i = 0; i < ab->nr_events; i++) { if (bdl->samples[i].percent > percent_max) percent_max = bdl->samples[i].percent; } if (dl->offset != -1 && percent_max != 0.0) { if (percent_max != 0.0) { for (i = 0; i < ab->nr_events; i++) { ui_browser__set_percent_color(browser, bdl->samples[i].percent, current_entry); if (annotate_browser__opts.show_total_period) { ui_browser__printf(browser, "%6" PRIu64 " ", bdl->samples[i].nr); } else { ui_browser__printf(browser, "%6.2f ", bdl->samples[i].percent); } } } else { ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); } } else { ui_browser__set_percent_color(browser, 0, current_entry); ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); } if (ab->have_cycles) { if (dl->ipc) ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc); else ui_browser__write_nstring(browser, " ", IPC_WIDTH); if (dl->cycles) ui_browser__printf(browser, "%*" PRIu64 " ", CYCLES_WIDTH - 1, dl->cycles); else ui_browser__write_nstring(browser, " ", CYCLES_WIDTH); } SLsmg_write_char(' '); /* The scroll bar isn't being used */ if (!browser->navkeypressed) width += 1; if (!*dl->line) ui_browser__write_nstring(browser, " ", width - pcnt_width); else if (dl->offset == -1) { if (dl->line_nr && annotate_browser__opts.show_linenr) printed = scnprintf(bf, sizeof(bf), "%-*d ", ab->addr_width + 1, dl->line_nr); else printed = scnprintf(bf, sizeof(bf), "%*s ", ab->addr_width, " "); ui_browser__write_nstring(browser, bf, printed); ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1); } else { u64 addr = dl->offset; int color = -1; if (!annotate_browser__opts.use_offset) addr += ab->start; if (!annotate_browser__opts.use_offset) { printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); } else { if (bdl->jump_sources) { if (annotate_browser__opts.show_nr_jumps) { int prev; printed = scnprintf(bf, sizeof(bf), "%*d ", ab->jumps_width, bdl->jump_sources); prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, current_entry); ui_browser__write_nstring(browser, bf, printed); ui_browser__set_color(browser, prev); } printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", ab->target_width, addr); } else { printed = scnprintf(bf, sizeof(bf), "%*s ", ab->addr_width, " "); } } if (change_color) color = ui_browser__set_color(browser, HE_COLORSET_ADDR); ui_browser__write_nstring(browser, bf, printed); if (change_color) ui_browser__set_color(browser, color); if (dl->ins.ops && dl->ins.ops->scnprintf) { if (ins__is_jump(&dl->ins)) { bool fwd = dl->ops.target.offset > dl->offset; ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : SLSMG_UARROW_CHAR); SLsmg_write_char(' '); } else if (ins__is_call(&dl->ins)) { ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); SLsmg_write_char(' '); } else if (ins__is_ret(&dl->ins)) { ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); SLsmg_write_char(' '); } else { ui_browser__write_nstring(browser, " ", 2); } } else { ui_browser__write_nstring(browser, " ", 2); } disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed); } if (current_entry) ab->selection = dl; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo63370.96%3181.58%
andi kleenandi kleen12413.90%25.26%
namhyung kimnamhyung kim798.86%37.89%
martin liskamartin liska343.81%12.63%
naveen n. raonaveen n. rao222.47%12.63%
Total892100.00%38100.00%


static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) { if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) || !disasm_line__has_offset(dl) || dl->ops.target.offset < 0 || dl->ops.target.offset >= (s64)symbol__size(sym)) return false; return true; }

Contributors

PersonTokensPropCommitsCommitProp
frederik deweerdtfrederik deweerdt5978.67%133.33%
ravi bangoriaravi bangoria1317.33%133.33%
arnaldo carvalho de meloarnaldo carvalho de melo34.00%133.33%
Total75100.00%3100.00%


static void annotate_browser__draw_current_jump(struct ui_browser *browser) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); struct disasm_line *cursor = ab->selection, *target; struct browser_disasm_line *btarget, *bcursor; unsigned int from, to; struct map_symbol *ms = ab->b.priv; struct symbol *sym = ms->sym; u8 pcnt_width = annotate_browser__pcnt_width(ab); /* PLT symbols contain external offsets */ if (strstr(sym->name, "@plt")) return; if (!disasm_line__is_valid_jump(cursor, sym)) return; target = ab->offsets[cursor->ops.target.offset]; if (!target) return; bcursor = disasm_line__browser(cursor); btarget = disasm_line__browser(target); if (annotate_browser__opts.hide_src_code) { from = bcursor->idx_asm; to = btarget->idx_asm; } else { from = (u64)bcursor->idx; to = (u64)btarget->idx; } ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, from, to); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo15676.47%654.55%
namhyung kimnamhyung kim4019.61%218.18%
andi kleenandi kleen41.96%19.09%
frederik deweerdtfrederik deweerdt31.47%19.09%
taeung songtaeung song10.49%19.09%
Total204100.00%11100.00%


static unsigned int annotate_browser__refresh(struct ui_browser *browser) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); int ret = ui_browser__list_head_refresh(browser); int pcnt_width = annotate_browser__pcnt_width(ab); if (annotate_browser__opts.jump_arrows) annotate_browser__draw_current_jump(browser); ui_browser__set_color(browser, HE_COLORSET_NORMAL); __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo5569.62%466.67%
namhyung kimnamhyung kim1924.05%116.67%
andi kleenandi kleen56.33%116.67%
Total79100.00%6100.00%


static int disasm__cmp(struct browser_disasm_line *a, struct browser_disasm_line *b, int nr_pcnt) { int i; for (i = 0; i < nr_pcnt; i++) { if (a->samples[i].percent == b->samples[i].percent) continue; return a->samples[i].percent < b->samples[i].percent; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
namhyung kimnamhyung kim6885.00%150.00%
martin liskamartin liska1215.00%150.00%
Total80100.00%2100.00%


static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl, int nr_events) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct browser_disasm_line *l; while (*p != NULL) { parent = *p; l = rb_entry(parent, struct browser_disasm_line, rb_node); if (disasm__cmp(bdl, l, nr_events)) p = &(*p)->rb_left; else p = &(*p)->rb_right; } rb_link_node(&bdl->rb_node, parent, p); rb_insert_color(&bdl->rb_node, root); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo11392.62%480.00%
namhyung kimnamhyung kim97.38%120.00%
Total122100.00%5100.00%


static void annotate_browser__set_top(struct annotate_browser *browser, struct disasm_line *pos, u32 idx) { unsigned back; ui_browser__refresh_dimensions(&browser->b); back = browser->b.height / 2; browser->b.top_idx = browser->b.index = idx; while (browser->b.top_idx != 0 && back != 0) { pos = list_entry(pos->node.prev, struct disasm_line, node); if (disasm_line__filter(&browser->b, &pos->node)) continue; --browser->b.top_idx; --back; } browser->b.top = pos; browser->b.navkeypressed = true; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo128100.00%6100.00%
Total128100.00%6100.00%


static void annotate_browser__set_rb_top(struct annotate_browser *browser, struct rb_node *nd) { struct browser_disasm_line *bpos; struct disasm_line *pos; u32 idx; bpos = rb_entry(nd, struct browser_disasm_line, rb_node); pos = ((struct disasm_line *)bpos) - 1; idx = bpos->idx; if (annotate_browser__opts.hide_src_code) idx = bpos->idx_asm; annotate_browser__set_top(browser, pos, idx); browser->curr_hot = nd; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo87100.00%6100.00%
Total87100.00%6100.00%


static void annotate_browser__calc_percent(struct annotate_browser *browser, struct perf_evsel *evsel) { struct map_symbol *ms = browser->b.priv; struct symbol *sym = ms->sym; struct annotation *notes = symbol__annotation(sym); struct disasm_line *pos, *next; s64 len = symbol__size(sym); browser->entries = RB_ROOT; pthread_mutex_lock(&notes->lock); list_for_each_entry(pos, &notes->src->source, node) { struct browser_disasm_line *bpos = disasm_line__browser(pos); const char *path = NULL; double max_percent = 0.0; int i; if (pos->offset == -1) { RB_CLEAR_NODE(&bpos->rb_node); continue; } next = disasm__get_next_ip_line(&notes->src->source, pos); for (i = 0; i < browser->nr_events; i++) { u64 nr_samples; bpos->samples[i].percent = disasm__calc_percent(notes, evsel->idx + i, pos->offset, next ? next->offset : len, &path, &nr_samples); bpos->samples[i].nr = nr_samples; if (max_percent < bpos->samples[i].percent) max_percent = bpos->samples[i].percent; } if (max_percent < 0.01 && pos->ipc == 0) { RB_CLEAR_NODE(&bpos->rb_node); continue; } disasm_rb_tree__insert(&browser->entries, bpos, browser->nr_events); } pthread_mutex_unlock(&notes->lock); browser->curr_hot = rb_last(&browser->entries); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo13646.10%440.00%
namhyung kimnamhyung kim12743.05%440.00%
martin liskamartin liska268.81%110.00%
andi kleenandi kleen62.03%110.00%
Total295100.00%10100.00%


static bool annotate_browser__toggle_source(struct annotate_browser *browser) { struct disasm_line *dl; struct browser_disasm_line *bdl; off_t offset = browser->b.index - browser->b.top_idx; browser->b.seek(&browser->b, offset, SEEK_CUR); dl = list_entry(browser->b.top, struct disasm_line, node); bdl = disasm_line__browser(dl); if (annotate_browser__opts.hide_src_code) { if (bdl->idx_asm < offset) offset = bdl->idx; browser->b.nr_entries = browser->nr_entries; annotate_browser__opts.hide_src_code = false; browser->b.seek(&browser->b, -offset, SEEK_CUR); browser->b.top_idx = bdl->idx - offset; browser->b.index = bdl->idx; } else { if (bdl->idx_asm < 0) { ui_helpline__puts("Only available for assembly lines."); browser->b.seek(&browser->b, -offset, SEEK_CUR); return false; } if (bdl->idx_asm < offset) offset = bdl->idx_asm; browser->b.nr_entries = browser->nr_asm_entries; annotate_browser__opts.hide_src_code = true; browser->b.seek(&browser->b, -offset, SEEK_CUR); browser->b.top_idx = bdl->idx_asm - offset; browser->b.index = bdl->idx_asm; } return true; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo262100.00%4100.00%
Total262100.00%4100.00%


static void annotate_browser__init_asm_mode(struct annotate_browser *browser) { ui_browser__reset_index(&browser->b); browser->b.nr_entries = browser->nr_asm_entries; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo29100.00%1100.00%
Total29100.00%1100.00%

#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
static int sym_title(struct symbol *sym, struct map *map, char *title, size_t sz) { return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter43100.00%1100.00%
Total43100.00%1100.00%


static bool annotate_browser__callq(struct annotate_browser *browser, struct perf_evsel *evsel, struct hist_browser_timer *hbt) { struct map_symbol *ms = browser->b.priv; struct disasm_line *dl = browser->selection; struct annotation *notes; struct addr_map_symbol target = { .map = ms->map, .addr = map__objdump_2mem(ms->map, dl->ops.target.addr), }; char title[SYM_TITLE_MAX_SIZE]