// SPDX-License-Identifier: GPL-2.0
#include "../browser.h"
#include "../helpline.h"
#include "../ui.h"
#include "../../util/annotate.h"
#include "../../util/debug.h"
#include "../../util/dso.h"
#include "../../util/hist.h"
#include "../../util/sort.h"
#include "../../util/map.h"
#include "../../util/mutex.h"
#include "../../util/symbol.h"
#include "../../util/evsel.h"
#include "../../util/evlist.h"
#include <inttypes.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/zalloc.h>
#include <sys/ttydefaults.h>
#include <asm/bug.h>
struct arch;
struct annotate_browser {
struct ui_browser b;
struct rb_root entries;
struct rb_node *curr_hot;
struct annotation_line *selection;
struct arch *arch;
bool searching_backwards;
char search_bf[128];
};
static inline struct annotation *browser__annotation(struct ui_browser *browser)
{
struct map_symbol *ms = browser->priv;
return symbol__annotation(ms->sym);
}
static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, void *entry)
{
struct annotation_line *al = list_entry(entry, struct annotation_line, node);
return annotation_line__filter(al);
}
static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
{
struct annotation *notes = browser__annotation(browser);
if (current && (!browser->use_navkeypressed || browser->navkeypressed))
return HE_COLORSET_SELECTED;
if (nr == notes->src->max_jump_sources)
return HE_COLORSET_TOP;
if (nr > 1)
return HE_COLORSET_MEDIUM;
return HE_COLORSET_NORMAL;
}
static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current)
{
int color = ui_browser__jumps_percent_color(browser, nr, current);
return ui_browser__set_color(browser, color);
}
static int annotate_browser__set_color(void *browser, int color)
{
return ui_browser__set_color(browser, color);
}
static void annotate_browser__write_graph(void *browser, int graph)
{
ui_browser__write_graph(browser, graph);
}
static void annotate_browser__set_percent_color(void *browser, double percent, bool current)
{
ui_browser__set_percent_color(browser, percent, current);
}
static void annotate_browser__printf(void *browser, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
ui_browser__vprintf(browser, fmt, args);
va_end(args);
}
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 annotation *notes = browser__annotation(browser);
struct annotation_line *al = list_entry(entry, struct annotation_line, node);
const bool is_current_entry = ui_browser__is_current_entry(browser, row);
struct annotation_write_ops ops = {
.first_line = row == 0,
.current_entry = is_current_entry,
.change_color = (!annotate_opts.hide_src_code &&
(!is_current_entry ||
(browser->use_navkeypressed &&
!browser->navkeypressed))),
.width = browser->width,
.obj = browser,
.set_color = annotate_browser__set_color,
.set_percent_color = annotate_browser__set_percent_color,
.set_jumps_percent_color = ui_browser__set_jumps_percent_color,
.printf = annotate_browser__printf,
.write_graph = annotate_browser__write_graph,
};
/* The scroll bar isn't being used */
if (!browser->navkeypressed)
ops.width += 1;
annotation_line__write(al, notes, &ops);
if (ops.current_entry)
ab->selection = al;
}
static int is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
{
struct disasm_line *pos = list_prev_entry(cursor, al.node);
const char *name;
int diff = 1;
while (pos && pos->al.offset == -1) {
pos = list_prev_entry(pos, al.node);
if (!annotate_opts.hide_src_code)
diff++;
}
if (!pos)
return 0;
if (ins__is_lock(&pos->ins))
name = pos->ops.locked.ins.name;
else
name = pos->ins.name;
if (!name || !cursor->ins.name)
return 0;
if (ins__is_fused(ab->arch, name, cursor->ins.name))
return diff;
return 0;
}
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 = disasm_line(ab->selection);
struct annotation_line *target;
unsigned int from, to;
struct map_symbol *ms = ab->b.priv;
struct symbol *sym = ms->sym;
struct annotation *notes = symbol__annotation(sym);
u8 pcnt_width = annotation__pcnt_width(notes);
u8 cntr