aboutsummaryrefslogtreecommitdiff
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-probe.txt19
-rw-r--r--tools/perf/Documentation/perfconfig.example8
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-probe.c86
-rw-r--r--tools/perf/builtin-record.c14
-rw-r--r--tools/perf/builtin-report.c14
-rw-r--r--tools/perf/builtin-top.c24
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/perf/ui/browser.c182
-rw-r--r--tools/perf/ui/browser.h1
-rw-r--r--tools/perf/ui/browsers/annotate.c262
-rw-r--r--tools/perf/ui/browsers/hists.c338
-rw-r--r--tools/perf/ui/setup.c1
-rw-r--r--tools/perf/util/config.c2
-rw-r--r--tools/perf/util/evsel.c90
-rw-r--r--tools/perf/util/evsel.h3
-rw-r--r--tools/perf/util/parse-events.c27
-rw-r--r--tools/perf/util/probe-event.c422
-rw-r--r--tools/perf/util/probe-event.h12
-rw-r--r--tools/perf/util/symbol.c8
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/thread_map.c21
23 files changed, 1035 insertions, 508 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 2780d9ce48b..b715cb71592 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -77,7 +77,8 @@ OPTIONS
-F::
--funcs::
- Show available functions in given module or kernel.
+ Show available functions in given module or kernel. With -x/--exec,
+ can also list functions in a user space executable / shared library.
--filter=FILTER::
(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
@@ -98,6 +99,15 @@ OPTIONS
--max-probes::
Set the maximum number of probe points for an event. Default is 128.
+-x::
+--exec=PATH::
+ Specify path to the executable or shared library file for user
+ space tracing. Can also be used with --funcs option.
+
+In absence of -m/-x options, perf probe checks if the first argument after
+the options is an absolute path name. If its an absolute path, perf probe
+uses it as a target module/target user space binary to probe.
+
PROBE SYNTAX
------------
Probe points are defined by following syntax.
@@ -182,6 +192,13 @@ Delete all probes on schedule().
./perf probe --del='schedule*'
+Add probes at zfree() function on /bin/zsh
+
+ ./perf probe -x /bin/zsh zfree or ./perf probe /bin/zsh zfree
+
+Add probes at malloc() function on libc
+
+ ./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc
SEE ALSO
--------
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index 42c6fd2ae85..767ea2436e1 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -19,3 +19,11 @@
# Default, disable using /dev/null
dir = /root/.debug
+
+[annotate]
+
+ # Defaults
+ hide_src_code = false
+ use_offset = true
+ jump_arrows = true
+ show_nr_jumps = false
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 1d3d513beb9..0eee64cfe9a 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -80,7 +80,7 @@ ifeq ("$(origin DEBUG)", "command line")
PERF_DEBUG = $(DEBUG)
endif
ifndef PERF_DEBUG
- CFLAGS_OPTIMIZE = -O6
+ CFLAGS_OPTIMIZE = -O6 -D_FORTIFY_SOURCE=2
endif
ifdef PARSER_DEBUG
@@ -89,7 +89,7 @@ ifdef PARSER_DEBUG
PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG
endif
-CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS)
+CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS)
EXTLIBS = -lpthread -lrt -lelf -lm
ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
ALL_LDFLAGS = $(LDFLAGS)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 806e0a28663..67522cf8740 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -215,7 +215,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
}
if (total_nr_samples == 0) {
- ui__warning("The %s file has no samples!\n", session->filename);
+ ui__error("The %s file has no samples!\n", session->filename);
goto out_delete;
}
out_delete:
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 4935c09dd5b..e215ae61b2a 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -54,6 +54,7 @@ static struct {
bool show_ext_vars;
bool show_funcs;
bool mod_events;
+ bool uprobes;
int nevents;
struct perf_probe_event events[MAX_PROBES];
struct strlist *dellist;
@@ -75,6 +76,8 @@ static int parse_probe_event(const char *str)
return -1;
}
+ pev->uprobes = params.uprobes;
+
/* Parse a perf-probe command into event */
ret = parse_perf_probe_command(str, pev);
pr_debug("%d arguments\n", pev->nargs);
@@ -82,21 +85,58 @@ static int parse_probe_event(const char *str)
return ret;
}
+static int set_target(const char *ptr)
+{
+ int found = 0;
+ const char *buf;
+
+ /*
+ * The first argument after options can be an absolute path
+ * to an executable / library or kernel module.
+ *
+ * TODO: Support relative path, and $PATH, $LD_LIBRARY_PATH,
+ * short module name.
+ */
+ if (!params.target && ptr && *ptr == '/') {
+ params.target = ptr;
+ found = 1;
+ buf = ptr + (strlen(ptr) - 3);
+
+ if (strcmp(buf, ".ko"))
+ params.uprobes = true;
+
+ }
+
+ return found;
+}
+
static int parse_probe_event_argv(int argc, const char **argv)
{
- int i, len, ret;
+ int i, len, ret, found_target;
char *buf;
+ found_target = set_target(argv[0]);
+ if (found_target && argc == 1)
+ return 0;
+
/* Bind up rest arguments */
len = 0;
- for (i = 0; i < argc; i++)
+ for (i = 0; i < argc; i++) {
+ if (i == 0 && found_target)
+ continue;
+
len += strlen(argv[i]) + 1;
+ }
buf = zalloc(len + 1);
if (buf == NULL)
return -ENOMEM;
len = 0;
- for (i = 0; i < argc; i++)
+ for (i = 0; i < argc; i++) {
+ if (i == 0 && found_target)
+ continue;
+
len += sprintf(&buf[len], "%s ", argv[i]);
+ }
params.mod_events = true;
ret = parse_probe_event(buf);
free(buf);
@@ -125,6 +165,28 @@ static int opt_del_probe_event(const struct option *opt __used,
return 0;
}
+static int opt_set_target(const struct option *opt, const char *str,
+ int unset __used)
+{
+ int ret = -ENOENT;
+
+ if (str && !params.target) {
+ if (!strcmp(opt->long_name, "exec"))
+ params.uprobes = true;
+#ifdef DWARF_SUPPORT
+ else if (!strcmp(opt->long_name, "module"))
+ params.uprobes = false;
+#endif
+ else
+ return ret;
+
+ params.target = str;
+ ret = 0;
+ }
+
+ return ret;
+}
+
#ifdef DWARF_SUPPORT
static int opt_show_lines(const struct option *opt __used,
const char *str, int unset __used)
@@ -246,9 +308,9 @@ static const struct option options[] = {
"file", "vmlinux pathname"),
OPT_STRING('s', "source", &symbol_conf.source_prefix,
"directory", "path to kernel source"),
- OPT_STRING('m', "module", &params.target,
- "modname|path",
- "target module name (for online) or path (for offline)"),
+ OPT_CALLBACK('m', "module", NULL, "modname|path",
+ "target module name (for online) or path (for offline)",
+ opt_set_target),
#endif
OPT__DRY_RUN(&probe_event_dry_run),
OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
@@ -260,6 +322,8 @@ static const struct option options[] = {
"\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
"\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
opt_set_filter),
+ OPT_CALLBACK('x', "exec", NULL, "executable|path",
+ "target executable name or path", opt_set_target),
OPT_END()
};
@@ -310,6 +374,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
pr_err(" Error: Don't use --list with --funcs.\n");
usage_with_options(probe_usage, options);
}
+ if (params.uprobes) {
+ pr_warning(" Error: Don't use --list with --exec.\n");
+ usage_with_options(probe_usage, options);
+ }
ret = show_perf_probe_events();
if (ret < 0)
pr_err(" Error: Failed to show event list. (%d)\n",
@@ -333,8 +401,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
if (!params.filter)
params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
NULL);
- ret = show_available_funcs(params.target,
- params.filter);
+ ret = show_available_funcs(params.target, params.filter,
+ params.uprobes);
strfilter__delete(params.filter);
if (ret < 0)
pr_err(" Error: Failed to show functions."
@@ -343,7 +411,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
}
#ifdef DWARF_SUPPORT
- if (params.show_lines) {
+ if (params.show_lines && !params.uprobes) {
if (params.mod_events) {
pr_err(" Error: Don't use --line with"
" --add/--del.\n");
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e5cb08427e1..f95840d04e4 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -264,7 +264,7 @@ try_again:
}
if (err == ENOENT) {
- ui__warning("The %s event is not supported.\n",
+ ui__error("The %s event is not supported.\n",
event_name(pos));
exit(EXIT_FAILURE);
}
@@ -858,8 +858,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
usage_with_options(record_usage, record_options);
if (rec->force && rec->append_file) {
- fprintf(stderr, "Can't overwrite and append at the same time."
- " You need to choose between -f and -A");
+ ui__error("Can't overwrite and append at the same time."
+ " You need to choose between -f and -A");
usage_with_options(record_usage, record_options);
} else if (rec->append_file) {
rec->write_mode = WRITE_APPEND;
@@ -868,8 +868,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
}
if (nr_cgroups && !rec->opts.target.system_wide) {
- fprintf(stderr, "cgroup monitoring only available in"
- " system-wide mode\n");
+ ui__error("cgroup monitoring only available in"
+ " system-wide mode\n");
usage_with_options(record_usage, record_options);
}
@@ -905,7 +905,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
int saved_errno = errno;
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
- ui__warning("%s", errbuf);
+ ui__error("%s", errbuf);
err = -saved_errno;
goto out_free_fd;
@@ -933,7 +933,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
else if (rec->opts.freq) {
rec->opts.default_interval = rec->opts.freq;
} else {
- fprintf(stderr, "frequency and count are zero, aborting\n");
+ ui__error("frequency and count are zero, aborting\n");
err = -EINVAL;
goto out_free_fd;
}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index d58e41445d0..8c767c6bca9 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -251,13 +251,13 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
- ui__warning("Selected --sort parent, but no "
+ ui__error("Selected --sort parent, but no "
"callchain data. Did you call "
"'perf record' without -g?\n");
return -EINVAL;
}
if (symbol_conf.use_callchain) {
- ui__warning("Selected -g but no callchain data. Did "
+ ui__error("Selected -g but no callchain data. Did "
"you call 'perf record' without -g?\n");
return -1;
}
@@ -266,17 +266,15 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
!symbol_conf.use_callchain) {
symbol_conf.use_callchain = true;
if (callchain_register_param(&callchain_param) < 0) {
- ui__warning("Can't register callchain "
- "params.\n");
+ ui__error("Can't register callchain params.\n");
return -EINVAL;
}
}
if (sort__branch_mode == 1) {
if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
- fprintf(stderr, "selected -b but no branch data."
- " Did you call perf record without"
- " -b?\n");
+ ui__error("Selected -b but no branch data. "
+ "Did you call perf record without -b?\n");
return -1;
}
}
@@ -420,7 +418,7 @@ static int __cmd_report(struct perf_report *rep)
}
if (nr_samples == 0) {
- ui__warning("The %s file has no samples!\n", session->filename);
+ ui__error("The %s file has no samples!\n", session->filename);
goto out_delete;
}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6031dce0429..871b540293e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -953,22 +953,22 @@ try_again:
attr->config = PERF_COUNT_SW_CPU_CLOCK;
if (counter->name) {
free(counter->name);
- counter->name = strdup(event_name(counter));
+ counter->name = NULL;
}
goto try_again;
}
if (err == ENOENT) {
- ui__warning("The %s event is not supported.\n",
+ ui__error("The %s event is not supported.\n",
event_name(counter));
goto out_err;
} else if (err == EMFILE) {
- ui__warning("Too many events are opened.\n"
+ ui__error("Too many events are opened.\n"
"Try again after reducing the number of events\n");
goto out_err;
}
- ui__warning("The sys_perf_event_open() syscall "
+ ui__error("The sys_perf_event_open() syscall "
"returned with %d (%s). /bin/dmesg "
"may provide additional information.\n"
"No CONFIG_PERF_EVENTS=y kernel support "
@@ -978,7 +978,7 @@ try_again:
}
if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) {
- ui__warning("Failed to mmap with %d (%s)\n",
+ ui__error("Failed to mmap with %d (%s)\n",
errno, strerror(errno));
goto out_err;
}
@@ -994,12 +994,12 @@ static int perf_top__setup_sample_type(struct perf_top *top)
{
if (!top->sort_has_symbols) {
if (symbol_conf.use_callchain) {
- ui__warning("Selected -g but \"sym\" not present in --sort/-s.");
+ ui__error("Selected -g but \"sym\" not present in --sort/-s.");
return -EINVAL;
}
} else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
if (callchain_register_param(&callchain_param) < 0) {
- ui__warning("Can't register callchain params.\n");
+ ui__error("Can't register callchain params.\n");
return -EINVAL;
}
}
@@ -1041,7 +1041,7 @@ static int __cmd_top(struct perf_top *top)
if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
display_thread), top)) {
- printf("Could not create display thread.\n");
+ ui__error("Could not create display thread.\n");
exit(-1);
}
@@ -1050,7 +1050,7 @@ static int __cmd_top(struct perf_top *top)
param.sched_priority = top->realtime_prio;
if (sched_setscheduler(0, SCHED_FIFO, &param)) {
- printf("Could not set realtime priority.\n");
+ ui__error("Could not set realtime priority.\n");
exit(-1);
}
}
@@ -1274,7 +1274,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
int saved_errno = errno;
perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
- ui__warning("%s", errbuf);
+ ui__error("%s", errbuf);
status = -saved_errno;
goto out_delete_evlist;
@@ -1288,7 +1288,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
if (!top.evlist->nr_entries &&
perf_evlist__add_default(top.evlist) < 0) {
- pr_err("Not enough memory for event selector list\n");
+ ui__error("Not enough memory for event selector list\n");
return -ENOMEM;
}
@@ -1305,7 +1305,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
else if (top.freq) {
top.default_interval = top.freq;
} else {
- fprintf(stderr, "frequency and count are zero, aborting\n");
+ ui__error("frequency and count are zero, aborting\n");
exit(EXIT_FAILURE);
}
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 14f1034f14f..f960ccb2edc 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -227,7 +227,7 @@ struct perf_record_opts {
unsigned int freq;
unsigned int mmap_pages;
unsigned int user_freq;
- int branch_stack;
+ u64 branch_stack;
u64 default_interval;
u64 user_interval;
};
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index cde4d0f0ddb..1818a531f1d 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -35,16 +35,16 @@ int ui_browser__set_color(struct ui_browser *browser, int color)
return ret;
}
-void ui_browser__set_percent_color(struct ui_browser *self,
+void ui_browser__set_percent_color(struct ui_browser *browser,
double percent, bool current)
{
- int color = ui_browser__percent_color(self, percent, current);
- ui_browser__set_color(self, color);
+ int color = ui_browser__percent_color(browser, percent, current);
+ ui_browser__set_color(browser, color);
}
-void ui_browser__gotorc(struct ui_browser *self, int y, int x)
+void ui_browser__gotorc(struct ui_browser *browser, int y, int x)
{
- SLsmg_gotorc(self->y + y, self->x + x);
+ SLsmg_gotorc(browser->y + y, browser->x + x);
}
static struct list_head *
@@ -73,23 +73,23 @@ ui_browser__list_head_filter_prev_entries(struct ui_browser *browser,
return NULL;
}
-void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
+void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whence)
{
- struct list_head *head = self->entries;
+ struct list_head *head = browser->entries;
struct list_head *pos;
- if (self->nr_entries == 0)
+ if (browser->nr_entries == 0)
return;
switch (whence) {
case SEEK_SET:
- pos = ui_browser__list_head_filter_entries(self, head->next);
+ pos = ui_browser__list_head_filter_entries(browser, head->next);
break;
case SEEK_CUR:
- pos = self->top;
+ pos = browser->top;
break;
case SEEK_END:
- pos = ui_browser__list_head_filter_prev_entries(self, head->prev);
+ pos = ui_browser__list_head_filter_prev_entries(browser, head->prev);
break;
default:
return;
@@ -99,18 +99,18 @@ void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whenc
if (offset > 0) {
while (offset-- != 0)
- pos = ui_browser__list_head_filter_entries(self, pos->next);
+ pos = ui_browser__list_head_filter_entries(browser, pos->next);
} else {
while (offset++ != 0)
- pos = ui_browser__list_head_filter_prev_entries(self, pos->prev);
+ pos = ui_browser__list_head_filter_prev_entries(browser, pos->prev);
}
- self->top = pos;
+ browser->top = pos;
}
-void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence)
+void ui_browser__rb_tree_seek(struct ui_browser *browser, off_t offset, int whence)
{
- struct rb_root *root = self->entries;
+ struct rb_root *root = browser->entries;
struct rb_node *nd;
switch (whence) {
@@ -118,7 +118,7 @@ void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence)
nd = rb_first(root);
break;
case SEEK_CUR:
- nd = self->top;
+ nd = browser->top;
break;
case SEEK_END:
nd = rb_last(root);
@@ -135,23 +135,23 @@ void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence)
nd = rb_prev(nd);
}
- self->top = nd;
+ browser->top = nd;
}
-unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
+unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser)
{
struct rb_node *nd;
int row = 0;
- if (self->top == NULL)
- self->top = rb_first(self->entries);
+ if (browser->top == NULL)
+ browser->top = rb_first(browser->entries);
- nd = self->top;
+ nd = browser->top;
while (nd != NULL) {
- ui_browser__gotorc(self, row, 0);
- self->write(self, nd, row);
- if (++row == self->height)
+ ui_browser__gotorc(browser, row, 0);
+ browser->write(browser, nd, row);
+ if (++row == browser->height)
break;
nd = rb_next(nd);
}
@@ -159,17 +159,17 @@ unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
return row;
}
-bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
+bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row)
{
- return self->top_idx + row == self->index;
+ return browser->top_idx + row == browser->index;
}
-void ui_browser__refresh_dimensions(struct ui_browser *self)
+void ui_browser__refresh_dimensions(struct ui_browser *browser)
{
- self->width = SLtt_Screen_Cols - 1;
- self->height = SLtt_Screen_Rows - 2;
- self->y = 1;
- self->x = 0;
+ browser->width = SLtt_Screen_Cols - 1;
+ browser->height = SLtt_Screen_Rows - 2;
+ browser->y = 1;
+ browser->x = 0;
}
void ui_browser__handle_resize(struct ui_browser *browser)
@@ -225,10 +225,10 @@ bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text)
return key == K_ENTER || toupper(key) == 'Y';
}
-void ui_browser__reset_index(struct ui_browser *self)
+void ui_browser__reset_index(struct ui_browser *browser)
{
- self->index = self->top_idx = 0;
- self->seek(self, 0, SEEK_SET);
+ browser->index = browser->top_idx = 0;
+ browser->seek(browser, 0, SEEK_SET);
}
void __ui_browser__show_title(struct ui_browser *browser, const char *title)
@@ -245,26 +245,26 @@ void ui_browser__show_title(struct ui_browser *browser, const char *title)
pthread_mutex_unlock(&ui__lock);
}
-int ui_browser__show(struct ui_browser *self, const char *title,
+int ui_browser__show(struct ui_browser *browser, const char *title,
const char *helpline, ...)
{
int err;
va_list ap;
- ui_browser__refresh_dimensions(self);
+ ui_browser__refresh_dimensions(browser);
pthread_mutex_lock(&ui__lock);
- __ui_browser__show_title(self, title);
+ __ui_browser__show_title(browser, title);
- self->title = title;
- free(self->helpline);
- self->helpline = NULL;
+ browser->title = title;
+ free(browser->helpline);
+ browser->helpline = NULL;
va_start(ap, helpline);
- err = vasprintf(&self->helpline, helpline, ap);
+ err = vasprintf(&browser->helpline, helpline, ap);
va_end(ap);
if (err > 0)
- ui_helpline__push(self->helpline);
+ ui_helpline__push(browser->helpline);
pthread_mutex_unlock(&ui__lock);
return err ? 0 : -1;
}
@@ -350,7 +350,7 @@ void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
browser->seek(browser, browser->top_idx, SEEK_SET);
}
-int ui_browser__run(struct ui_browser *self, int delay_secs)
+int ui_browser__run(struct ui_browser *browser, int delay_secs)
{
int err, key;
@@ -358,7 +358,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
off_t offset;
pthread_mutex_lock(&ui__lock);
- err = __ui_browser__refresh(self);
+ err = __ui_browser__refresh(browser);
SLsmg_refresh();
pthread_mutex_unlock(&ui__lock);
if (err < 0)
@@ -368,18 +368,18 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
if (key == K_RESIZE) {
ui__refresh_dimensions(false);
- ui_browser__refresh_dimensions(self);
- __ui_browser__show_title(self, self->title);
- ui_helpline__puts(self->helpline);
+ ui_browser__refresh_dimensions(browser);
+ __ui_browser__show_title(browser, browser->title);
+ ui_helpline__puts(browser->helpline);
continue;
}
- if (self->use_navkeypressed && !self->navkeypressed) {
+ if (browser->use_navkeypressed && !browser->navkeypressed) {
if (key == K_DOWN || key == K_UP ||
key == K_PGDN || key == K_PGUP ||
key == K_HOME || key == K_END ||
key == ' ') {
- self->navkeypressed = true;
+ browser->navkeypressed = true;
continue;
} else
return key;
@@ -387,59 +387,59 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
switch (key) {
case K_DOWN:
- if (self->index == self->nr_entries - 1)
+ if (browser->index == browser->nr_entries - 1)
break;
- ++self->index;
- if (self->index == self->top_idx + self->height) {
- ++self->top_idx;
- self->seek(self, +1, SEEK_CUR);
+ ++browser->index;
+ if (browser->index == browser->top_idx + browser->height) {
+ ++browser->top_idx;
+ browser->seek(browser, +1, SEEK_CUR);
}
break;
case K_UP:
- if (self->index == 0)
+ if (browser->index == 0)
break;
- --self->index;
- if (self->index < self->top_idx) {
- --self->top_idx;
- self->seek(self, -1, SEEK_CUR);
+ --browser->index;
+ if (browser->index < browser->top_idx) {
+ --browser->top_idx;
+ browser->seek(browser, -1, SEEK_CUR);
}
break;
case K_PGDN:
case ' ':
- if (self->top_idx + self->height > self->nr_entries - 1)
+ if (browser->top_idx + browser->height > browser->nr_entries - 1)
break;
- offset = self->height;
- if (self->index + offset > self->nr_entries - 1)
- offset = self->nr_entries - 1 - self->index;
- self->index += offset;
- self->top_idx += offset;
- self->seek(self, +offset, SEEK_CUR);
+ offset = browser->height;
+ if (browser->index + offset > browser->nr_entries - 1)
+ offset = browser->nr_entries - 1 - browser->index;
+ browser->index += offset;
+ browser->top_idx += offset;
+ browser->seek(browser, +offset, SEEK_CUR);
break;
case K_PGUP:
- if (self->top_idx == 0)
+ if (browser->top_idx == 0)
break;
- if (self->top_idx < self->height)
- offset = self->top_idx;
+ if (browser->top_idx < browser->height)
+ offset = browser->top_idx;
else
- offset = self->height;
+ offset = browser->height;
- self->index -= offset;
- self->top_idx -= offset;
- self->seek(self, -offset, SEEK_CUR);
+ browser->index -= offset;
+ browser->top_idx -= offset;
+ browser->seek(browser, -offset, SEEK_CUR);
break;
case K_HOME:
- ui_browser__reset_index(self);
+ ui_browser__reset_index(browser);
break;
case K_END:
- offset = self->height - 1;
- if (offset >= self->nr_entries)
- offset = self->nr_entries - 1;
+ offset = browser->height - 1;
+ if (offset >= browser->nr_entries)
+ offset = browser->nr_entries - 1;
- self->index = self->nr_entries - 1;
- self->top_idx = self->index - offset;
- self->seek(self, -offset, SEEK_END);
+ browser->index = browser->nr_entries - 1;
+ browser->top_idx = browser->index - offset;
+ browser->seek(browser, -offset, SEEK_END);
break;
default:
return key;
@@ -448,22 +448,22 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
return -1;
}
-unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
+unsigned int ui_browser__list_head_refresh(struct ui_browser *browser)
{
struct list_head *pos;
- struct list_head *head = self->entries;
+ struct list_head *head = browser->entries;
int row = 0;
- if (self->top == NULL || self->top == self->entries)
- self->top = ui_browser__list_head_filter_entries(self, head->next);
+ if (browser->top == NULL || browser->top == browser->entries)
+ browser->top = ui_browser__list_head_filter_entries(browser, head->next);
- pos = self->top;
+ pos = browser->top;
list_for_each_from(pos, head) {
- if (!self->filter || !self->filter(self, pos)) {
- ui_browser__gotorc(self, row, 0);
- self->write(self, pos, row);
- if (++row == self->height)
+ if (!browser->filter || !browser->filter(browser, pos)) {
+ ui_browser__gotorc(browser, row, 0);
+ browser->write(browser, pos, row);
+ if (++row == browser->height)
break;
}
}
@@ -708,4 +708,6 @@ void ui_browser__init(void)
struct ui_browser__colorset *c = &ui_browser__colorsets[i++];
sltt_set_color(c->colorset, c->name, c->fg, c->bg);
}
+
+ annotate_browser__init();
}
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index dd96d822990..af70314605e 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -69,4 +69,5 @@ void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whenc
unsigned int ui_browser__list_head_refresh(struct ui_browser *self);
void ui_browser__init(void);
+void annotate_browser__init(void);
#endif /* _PERF_UI_BROWSER_H_ */
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 6e0ef79be16..4deea6aaf92 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -19,6 +19,16 @@ struct browser_disasm_line {
int jump_sources;
};
+sta