summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Documentation/perf-script.txt20
-rw-r--r--tools/perf/builtin-script.c2
-rw-r--r--tools/perf/util/event.c24
-rw-r--r--tools/perf/util/symbol.c49
-rw-r--r--tools/perf/util/symbol_conf.h4
5 files changed, 98 insertions, 1 deletions
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 6347cfb97ed3..5b8b61075039 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -422,9 +422,29 @@ include::itrace.txt[]
Only consider the listed symbols. Symbols are typically a name
but they may also be hexadecimal address.
+ The hexadecimal address may be the start address of a symbol or
+ any other address to filter the trace records
+
For example, to select the symbol noploop or the address 0x4007a0:
perf script --symbols=noploop,0x4007a0
+ Support filtering trace records by symbol name, start address of
+ symbol, any hexadecimal address and address range.
+
+ The comparison order is:
+
+ 1. symbol name comparison
+ 2. symbol start address comparison.
+ 3. any hexadecimal address comparison.
+ 4. address range comparison (see --addr-range).
+
+--addr-range::
+ Use with -S or --symbols to list traced records within address range.
+
+ For example, to list the traced records within the address range
+ [0x4007a0, 0x0x4007a9]:
+ perf script -S 0x4007a0 --addr-range 10
+
--dsos=::
Only consider symbols in these DSOs.
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 62bb0f1c35c3..1ff72647b416 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -3552,6 +3552,8 @@ int cmd_script(int argc, const char **argv)
"only consider symbols in these DSOs"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
"only consider these symbols"),
+ OPT_INTEGER(0, "addr-range", &symbol_conf.addr_range,
+ "Use with -S to list traced records within address range"),
OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL,
"Decode instructions from itrace", parse_insn_trace),
OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 208b6c141d98..ac706304afe9 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -645,6 +645,19 @@ struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode,
return al->sym;
}
+static bool check_address_range(struct intlist *addr_list, int addr_range,
+ unsigned long addr)
+{
+ struct int_node *pos;
+
+ intlist__for_each_entry(pos, addr_list) {
+ if (addr >= pos->i && addr < pos->i + addr_range)
+ return true;
+ }
+
+ return false;
+}
+
/*
* Callers need to drop the reference to al->thread, obtained in
* machine__findnew_thread()
@@ -711,6 +724,17 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
ret = strlist__has_entry(symbol_conf.sym_list,
al_addr_str);
}
+ if (!ret && symbol_conf.addr_list && al->map) {
+ unsigned long addr = al->map->unmap_ip(al->map, al->addr);
+
+ ret = intlist__has_entry(symbol_conf.addr_list, addr);
+ if (!ret && symbol_conf.addr_range) {
+ ret = check_address_range(symbol_conf.addr_list,
+ symbol_conf.addr_range,
+ addr);
+ }
+ }
+
if (!ret)
al->filtered |= (1 << HIST_FILTER__SYMBOL);
}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 64a039cbba1b..40844d0ef6cc 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2406,6 +2406,49 @@ int setup_intlist(struct intlist **list, const char *list_str,
return 0;
}
+static int setup_addrlist(struct intlist **addr_list, struct strlist *sym_list)
+{
+ struct str_node *pos, *tmp;
+ unsigned long val;
+ char *sep;
+ const char *end;
+ int i = 0, err;
+
+ *addr_list = intlist__new(NULL);
+ if (!*addr_list)
+ return -1;
+
+ strlist__for_each_entry_safe(pos, tmp, sym_list) {
+ errno = 0;
+ val = strtoul(pos->s, &sep, 16);
+ if (errno || (sep == pos->s))
+ continue;
+
+ if (*sep != '\0') {
+ end = pos->s + strlen(pos->s) - 1;
+ while (end >= sep && isspace(*end))
+ end--;
+
+ if (end >= sep)
+ continue;
+ }
+
+ err = intlist__add(*addr_list, val);
+ if (err)
+ break;
+
+ strlist__remove(sym_list, pos);
+ i++;
+ }
+
+ if (i == 0) {
+ intlist__delete(*addr_list);
+ *addr_list = NULL;
+ }
+
+ return 0;
+}
+
static bool symbol__read_kptr_restrict(void)
{
bool value = false;
@@ -2489,6 +2532,10 @@ int symbol__init(struct perf_env *env)
symbol_conf.sym_list_str, "symbol") < 0)
goto out_free_tid_list;
+ if (symbol_conf.sym_list &&
+ setup_addrlist(&symbol_conf.addr_list, symbol_conf.sym_list) < 0)
+ goto out_free_sym_list;
+
if (setup_list(&symbol_conf.bt_stop_list,
symbol_conf.bt_stop_list_str, "symbol") < 0)
goto out_free_sym_list;
@@ -2512,6 +2559,7 @@ int symbol__init(struct perf_env *env)
out_free_sym_list:
strlist__delete(symbol_conf.sym_list);
+ intlist__delete(symbol_conf.addr_list);
out_free_tid_list:
intlist__delete(symbol_conf.tid_list);
out_free_pid_list:
@@ -2533,6 +2581,7 @@ void symbol__exit(void)
strlist__delete(symbol_conf.comm_list);
intlist__delete(symbol_conf.tid_list);
intlist__delete(symbol_conf.pid_list);
+ intlist__delete(symbol_conf.addr_list);
vmlinux_path__exit();
symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
symbol_conf.bt_stop_list = NULL;
diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h
index b18f9c8dbb75..a70b3ec09dac 100644
--- a/tools/perf/util/symbol_conf.h
+++ b/tools/perf/util/symbol_conf.h
@@ -70,11 +70,13 @@ struct symbol_conf {
*sym_to_list,
*bt_stop_list;
struct intlist *pid_list,
- *tid_list;
+ *tid_list,
+ *addr_list;
const char *symfs;
int res_sample;
int pad_output_len_dso;
int group_sort_idx;
+ int addr_range;
};
extern struct symbol_conf symbol_conf;