browser->curr_hot = rb_last(&browser->entries);
}
+static struct annotation_line *annotate_browser__find_new_asm_line(
+ struct annotate_browser *browser,
+ int idx_asm)
+{
+ struct annotation_line *al;
+ struct list_head *head = browser->b.entries;
+
+ /* find an annotation line in the new list with the same idx_asm */
+ list_for_each_entry(al, head, node) {
+ if (al->idx_asm == idx_asm)
+ return al;
+ }
+
+ /* There are no asm lines */
+ return NULL;
+}
+
static struct annotation_line *annotate_browser__find_next_asm_line(
struct annotate_browser *browser,
struct annotation_line *al)
return NULL;
}
-static bool annotate_browser__toggle_source(struct annotate_browser *browser)
+static bool annotation__has_source(struct annotation *notes)
+{
+ struct annotation_line *al;
+ bool found_asm = false;
+
+ /* 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)
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool annotate_browser__toggle_source(struct annotate_browser *browser,
+ struct evsel *evsel)
{
struct annotation *notes = browser__annotation(&browser->b);
struct annotation_line *al;
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;
nd = browser->curr_hot;
break;
case 's':
- if (annotate_browser__toggle_source(browser))
+ 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);
ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
return -1;
}
+
+ if (!annotate_opts.hide_src_code) {
+ notes->src->tried_source = true;
+ if (!annotation__has_source(notes))
+ ui__warning("Annotation has no source code.");
+ }
}
ui_helpline__push("Press ESC to exit");
ret = annotate_browser__run(&browser, evsel, hbt);
- if(not_annotated)
+ if (not_annotated && !notes->src->tried_source)
annotated_source__purge(notes->src);
return ret;