if (!disasm_line__is_valid_local_jump(cursor, sym)) return;
/* * This first was seen with a gcc function, _cpp_lex_token, that * has the usual jumps: * * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92> * * I.e. jumps to a label inside that function (_cpp_lex_token), and * those works, but also this kind: * * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72> * * I.e. jumps to another function, outside _cpp_lex_token, which * are not being correctly handled generating as a side effect references * to ab->offset[] entries that are set to NULL, so to make this code * more robust, check that here. * * A proper fix for will be put in place, looking at the function * name right after the '<' token and probably treating this like a * 'call' instruction.
*/
target = annotated_source__get_line(notes->src, cursor->ops.target.offset); if (target == NULL) {
ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
cursor->ops.target.offset); return;
}
if (annotate_opts.hide_src_code) {
from = cursor->al.idx_asm;
to = target->idx_asm;
} else {
from = (u64)cursor->al.idx;
to = (u64)target->idx;
}
/* find next asm line */
list_for_each_entry_continue(it, browser->b.entries, node) { if (it->idx_asm >= 0) return it;
}
/* no asm line found forwards, try backwards */
it = al;
list_for_each_entry_continue_reverse(it, browser->b.entries, node) { if (it->idx_asm >= 0) return it;
}
/* Let's skip the first non-asm lines which present regardless of source. */
list_for_each_entry(al, ¬es->src->source, node) { if (al->offset >= 0) {
found_asm = true; break;
}
}
if (found_asm) { /* After assembly lines, any line without offset means source. */
list_for_each_entry_continue(al, ¬es->src->source, node) { if (al->offset == -1) returntrue;
}
} returnfalse;
}
browser->b.seek(&browser->b, offset, SEEK_CUR);
al = list_entry(browser->b.top, struct annotation_line, node);
if (!annotate_opts.annotate_src)
annotate_opts.annotate_src = true;
/* * It's about to get source code annotation for the first time. * Drop the existing annotation_lines and get the new one with source. * And then move to the original line at the same asm index.
*/ if (annotate_opts.hide_src_code && !notes->src->tried_source) { struct map_symbol *ms = browser->b.priv; int orig_idx_asm = al->idx_asm;
/* annotate again with source code info */
annotate_opts.hide_src_code = false;
annotated_source__purge(notes->src);
symbol__annotate2(ms, evsel, &browser->arch);
annotate_opts.hide_src_code = true;
/* should be after annotated_source__purge() */
notes->src->tried_source = true;
if (!annotation__has_source(notes))
ui__warning("Annotation has no source code.");
browser->b.entries = ¬es->src->source;
al = annotate_browser__find_new_asm_line(browser, orig_idx_asm); if (unlikely(al == NULL)) {
al = list_first_entry(¬es->src->source, struct annotation_line, node);
}
browser->b.seek(&browser->b, al->idx_asm, SEEK_SET);
}
if (annotate_opts.hide_src_code) { if (al->idx_asm < offset)
offset = al->idx;
browser->b.nr_entries = notes->src->nr_entries;
annotate_opts.hide_src_code = false;
browser->b.seek(&browser->b, -offset, SEEK_CUR);
browser->b.top_idx = al->idx - offset;
browser->b.index = al->idx;
} else { if (al->idx_asm < 0) { /* move cursor to next asm line */
al = annotate_browser__find_next_asm_line(browser, al); if (!al) {
browser->b.seek(&browser->b, -offset, SEEK_CUR); returnfalse;
}
}
/* * This can be called from external jumps, i.e. jumps from one function * to another, like from the kernel's entry_SYSCALL_64 function to the * swapgs_restore_regs_and_return_to_usermode() function. * * So all we check here is that dl->ops.target.sym is set, if it is, just * go to that function and when exiting from its disassembly, come back * to the calling function.
*/ staticbool annotate_browser__callq(struct annotate_browser *browser, struct evsel *evsel, struct hist_browser_timer *hbt)
{ struct map_symbol *ms = browser->b.priv, target_ms; struct disasm_line *dl = disasm_line(browser->selection); struct annotation *notes; char title[SYM_TITLE_MAX_SIZE];
if (!dl->ops.target.sym) {
ui_helpline__puts("The called function was not found."); returntrue;
}
al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); if (al == NULL) {
ui_helpline__puts("String not found!"); returnfalse;
}
while (1) {
key = ui_browser__run(&browser->b, delay_secs);
if (delay_secs != 0) {
annotate_browser__calc_percent(browser, evsel); /* * Current line focus got out of the list of most active * lines, NULL it so that if TAB|UNTAB is pressed, we * move to curr_hot (current hottest line).
*/ if (nd != NULL && RB_EMPTY_NODE(nd))
nd = NULL;
}
switch (key) { case K_TIMER: if (hbt)
hbt->timer(hbt->arg);
if (delay_secs != 0) {
symbol__annotate_decay_histogram(sym, evsel);
annotate__scnprintf_title(hists, title, sizeof(title));
annotate_browser__show(&browser->b, title, help);
} continue; case K_TAB: if (nd != NULL) {
nd = rb_prev(nd); if (nd == NULL)
nd = rb_last(&browser->entries);
} else
nd = browser->curr_hot; break; case K_UNTAB: if (nd != NULL) {
nd = rb_next(nd); if (nd == NULL)
nd = rb_first(&browser->entries);
} else
nd = browser->curr_hot; break; case K_F1: case'h':
ui_browser__help_window(&browser->b, "UP/DOWN/PGUP\n" "PGDN/SPACE Navigate\n" "> Move to prev/next symbol\n" "q/ESC/CTRL+C Exit\n\n" "ENTER Go to target\n" "H Go to hottest instruction\n" "TAB/shift+TAB Cycle thru hottest instructions\n" "j Toggle showing jump to target arrows\n" "J Toggle showing number of jump sources on targets\n" "n Search next string\n" "o Toggle disassembler output/simplified view\n" "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n" "s Toggle source code view\n" "t Circulate percent, total period, samples view\n" "c Show min/max cycle\n" "/ Search string\n" "k Toggle line numbers\n" "l Show full source file location\n" "P Print to [symbol_name].annotation file.\n" "r Run available scripts\n" "p Toggle percent type [local/global]\n" "b Toggle percent base [period/hits]\n" "B Branch counter abbr list (Optional)\n" "? Search string backwards\n" "f Toggle showing offsets to full address\n"); continue; case'r':
script_browse(NULL, NULL);
annotate_browser__show(&browser->b, title, help); continue; case'k':
annotate_opts.show_linenr = !annotate_opts.show_linenr; continue; case'l':
annotate_browser__show_full_location (&browser->b); continue; case'H':
nd = browser->curr_hot; break; case's': if (annotate_browser__toggle_source(browser, evsel))
ui_helpline__puts(help);
annotate__scnprintf_title(hists, title, sizeof(title));
annotate_browser__show(&browser->b, title, help); continue; case'o':
annotate_opts.use_offset = !annotate_opts.use_offset;
annotation__update_column_widths(notes); continue; case'O': if (++annotate_opts.offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
annotate_opts.offset_level = ANNOTATION__MIN_OFFSET_LEVEL; continue; case'j':
annotate_opts.jump_arrows = !annotate_opts.jump_arrows; continue; case'J':
annotate_opts.show_nr_jumps = !annotate_opts.show_nr_jumps;
annotation__update_column_widths(notes); continue; case'/': if (annotate_browser__search(browser, delay_secs)) {
show_help:
ui_helpline__puts(help);
} continue; case'n': if (browser->searching_backwards ?
annotate_browser__continue_search_reverse(browser, delay_secs) :
annotate_browser__continue_search(browser, delay_secs)) goto show_help; continue; case'?': if (annotate_browser__search_reverse(browser, delay_secs)) goto show_help; continue; case'D': { staticint seq;
ui_helpline__pop();
ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d",
seq++, browser->b.nr_entries,
browser->b.height,
browser->b.index,
browser->b.top_idx,
notes->src->nr_asm_entries);
} continue; case K_ENTER: case K_RIGHT:
{ struct disasm_line *dl = disasm_line(browser->selection);
if (browser->selection == NULL)
ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); elseif (browser->selection->offset == -1)
ui_helpline__puts("Actions are only available for assembly lines."); elseif (!dl->ins.ops) goto show_sup_ins; elseif (ins__is_ret(&dl->ins)) goto out; elseif (!(annotate_browser__jump(browser, evsel, hbt) ||
annotate_browser__callq(browser, evsel, hbt))) {
show_sup_ins:
ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
} continue;
} case'P':
map_symbol__annotation_dump(ms, evsel); continue; case't': if (symbol_conf.show_total_period) {
symbol_conf.show_total_period = false;
symbol_conf.show_nr_samples = true;
} elseif (symbol_conf.show_nr_samples)
symbol_conf.show_nr_samples = false; else
symbol_conf.show_total_period = true;
annotation__update_column_widths(notes); continue; case'c': if (annotate_opts.show_minmax_cycle)
annotate_opts.show_minmax_cycle = false; else
annotate_opts.show_minmax_cycle = true;
annotation__update_column_widths(notes); continue; case'p': case'b':
switch_percent_type(&annotate_opts, key == 'b');
annotate__scnprintf_title(hists, title, sizeof(title));
annotate_browser__show(&browser->b, title, help); continue; case'B': if (br_cntr_text)
ui_browser__help_window(&browser->b, br_cntr_text); else {
ui_browser__help_window(&browser->b, "\n The branch counter is not available.\n");
} continue; case'f':
annotation__toggle_full_addr(notes, ms); continue; case K_LEFT: case'<': case'>': case K_ESC: case'q': case CTRL('c'): goto out; default:
ui_browser__warn_unhandled_hotkey(&browser->b, key, delay_secs, ", use 'h'/F1 to see actions"); continue;
}
int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel, struct hist_browser_timer *hbt)
{ /* reset abort key so that it can get Ctrl-C as a key */
SLang_reset_tty();
SLang_init_tty(0, 0, 0);
SLtty_set_suspend_state(true);
if (!annotate_opts.hide_src_code) {
notes->src->tried_source = true; if (!annotation__has_source(notes))
ui__warning("Annotation has no source code.");
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.