Commit 1b36c03e authored by Adrian Hunter's avatar Adrian Hunter Committed by Arnaldo Carvalho de Melo

perf record: Add support for using symbols in address filters

Symbols come from either the DSO or /proc/kallsyms for the kernel.
Details of the functionality can be found in Documentation/perf-record.txt.
Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-8-git-send-email-adrian.hunter@intel.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent cd67f99f
...@@ -89,9 +89,62 @@ OPTIONS ...@@ -89,9 +89,62 @@ OPTIONS
--filter=<filter>:: --filter=<filter>::
Event filter. This option should follow a event selector (-e) which Event filter. This option should follow a event selector (-e) which
selects tracepoint event(s). Multiple '--filter' options are combined selects either tracepoint event(s) or a hardware trace PMU
(e.g. Intel PT or CoreSight).
- tracepoint filters
In the case of tracepoints, multiple '--filter' options are combined
using '&&'. using '&&'.
- address filters
A hardware trace PMU advertises its ability to accept a number of
address filters by specifying a non-zero value in
/sys/bus/event_source/devices/<pmu>/nr_addr_filters.
Address filters have the format:
filter|start|stop|tracestop <start> [/ <size>] [@<file name>]
Where:
- 'filter': defines a region that will be traced.
- 'start': defines an address at which tracing will begin.
- 'stop': defines an address at which tracing will stop.
- 'tracestop': defines a region in which tracing will stop.
<file name> is the name of the object file, <start> is the offset to the
code to trace in that file, and <size> is the size of the region to
trace. 'start' and 'stop' filters need not specify a <size>.
If no object file is specified then the kernel is assumed, in which case
the start address must be a current kernel memory address.
<start> can also be specified by providing the name of a symbol. If the
symbol name is not unique, it can be disambiguated by inserting #n where
'n' selects the n'th symbol in address order. Alternately #0, #g or #G
select only a global symbol. <size> can also be specified by providing
the name of a symbol, in which case the size is calculated to the end
of that symbol. For 'filter' and 'tracestop' filters, if <size> is
omitted and <start> is a symbol, then the size is calculated to the end
of that symbol.
If <size> is omitted and <start> is '*', then the start and size will
be calculated from the first and last symbols, i.e. to trace the whole
file.
If symbol names (or '*') are provided, they must be surrounded by white
space.
The filter passed to the kernel is not necessarily the same as entered.
To see the filter that is passed, use the -v option.
The kernel may not be able to configure a trace region if it is not
within a single mapping. MMAP events (or /proc/<pid>/maps) can be
examined to determine if that is a possibility.
Multiple filters can be separated with space or comma.
--exclude-perf:: --exclude-perf::
Don't record events issued by perf itself. This option should follow Don't record events issued by perf itself. This option should follow
a event selector (-e) which selects tracepoint event(s). It adds a a event selector (-e) which selects tracepoint event(s). It adds a
......
...@@ -1581,6 +1581,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -1581,6 +1581,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
if (err) if (err)
goto out; goto out;
/*
* Allow aliases to facilitate the lookup of symbols for address
* filters. Refer to auxtrace_parse_filters().
*/
symbol_conf.allow_aliases = true;
symbol__init(NULL);
err = auxtrace_parse_filters(rec->evlist);
if (err)
goto out;
if (dry_run) if (dry_run)
goto out; goto out;
...@@ -1594,8 +1606,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -1594,8 +1606,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
err = -ENOMEM; err = -ENOMEM;
symbol__init(NULL);
if (symbol_conf.kptr_restrict) if (symbol_conf.kptr_restrict)
pr_warning( pr_warning(
"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
......
This diff is collapsed.
...@@ -318,6 +318,48 @@ struct auxtrace_record { ...@@ -318,6 +318,48 @@ struct auxtrace_record {
unsigned int alignment; unsigned int alignment;
}; };
/**
* struct addr_filter - address filter.
* @list: list node
* @range: true if it is a range filter
* @start: true if action is 'filter' or 'start'
* @action: 'filter', 'start' or 'stop' ('tracestop' is accepted but converted
* to 'stop')
* @sym_from: symbol name for the filter address
* @sym_to: symbol name that determines the filter size
* @sym_from_idx: selects n'th from symbols with the same name (0 means global
* and less than 0 means symbol must be unique)
* @sym_to_idx: same as @sym_from_idx but for @sym_to
* @addr: filter address
* @size: filter region size (for range filters)
* @filename: DSO file name or NULL for the kernel
* @str: allocated string that contains the other string members
*/
struct addr_filter {
struct list_head list;
bool range;
bool start;
const char *action;
const char *sym_from;
const char *sym_to;
int sym_from_idx;
int sym_to_idx;
u64 addr;
u64 size;
const char *filename;
char *str;
};
/**
* struct addr_filters - list of address filters.
* @head: list of address filters
* @cnt: number of address filters
*/
struct addr_filters {
struct list_head head;
int cnt;
};
#ifdef HAVE_AUXTRACE_SUPPORT #ifdef HAVE_AUXTRACE_SUPPORT
/* /*
...@@ -482,6 +524,12 @@ void perf_session__auxtrace_error_inc(struct perf_session *session, ...@@ -482,6 +524,12 @@ void perf_session__auxtrace_error_inc(struct perf_session *session,
union perf_event *event); union perf_event *event);
void events_stats__auxtrace_error_warn(const struct events_stats *stats); void events_stats__auxtrace_error_warn(const struct events_stats *stats);
void addr_filters__init(struct addr_filters *filts);
void addr_filters__exit(struct addr_filters *filts);
int addr_filters__parse_bare_filter(struct addr_filters *filts,
const char *filter);
int auxtrace_parse_filters(struct perf_evlist *evlist);
static inline int auxtrace__process_event(struct perf_session *session, static inline int auxtrace__process_event(struct perf_session *session,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
...@@ -640,6 +688,12 @@ void auxtrace_index__free(struct list_head *head __maybe_unused) ...@@ -640,6 +688,12 @@ void auxtrace_index__free(struct list_head *head __maybe_unused)
{ {
} }
static inline
int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused)
{
return 0;
}
int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
struct auxtrace_mmap_params *mp, struct auxtrace_mmap_params *mp,
void *userpg, int fd); void *userpg, int fd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment