summaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/bpf_lock_contention.c57
-rw-r--r--tools/perf/util/bpf_skel/lock_contention.bpf.c38
-rw-r--r--tools/perf/util/debug.c4
-rw-r--r--tools/perf/util/dlfilter.c2
-rw-r--r--tools/perf/util/hist.c10
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/lock-contention.h10
-rw-r--r--tools/perf/util/scripting-engines/Build2
-rw-r--r--tools/perf/util/setup.py13
-rw-r--r--tools/perf/util/sort.c129
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/srcline.c20
-rw-r--r--tools/perf/util/symbol-elf.c28
-rw-r--r--tools/perf/util/symbol-minimal.c5
-rw-r--r--tools/perf/util/symbol.h1
15 files changed, 293 insertions, 28 deletions
diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
index 8e1b791dc58f..0236334fd69b 100644
--- a/tools/perf/util/bpf_lock_contention.c
+++ b/tools/perf/util/bpf_lock_contention.c
@@ -20,7 +20,7 @@ static struct lock_contention_bpf *skel;
int lock_contention_prepare(struct lock_contention *con)
{
int i, fd;
- int ncpus = 1, ntasks = 1;
+ int ncpus = 1, ntasks = 1, ntypes = 1, naddrs = 1;
struct evlist *evlist = con->evlist;
struct target *target = con->target;
@@ -46,9 +46,42 @@ int lock_contention_prepare(struct lock_contention *con)
ncpus = perf_cpu_map__nr(evlist->core.user_requested_cpus);
if (target__has_task(target))
ntasks = perf_thread_map__nr(evlist->core.threads);
+ if (con->filters->nr_types)
+ ntypes = con->filters->nr_types;
+
+ /* resolve lock name filters to addr */
+ if (con->filters->nr_syms) {
+ struct symbol *sym;
+ struct map *kmap;
+ unsigned long *addrs;
+
+ for (i = 0; i < con->filters->nr_syms; i++) {
+ sym = machine__find_kernel_symbol_by_name(con->machine,
+ con->filters->syms[i],
+ &kmap);
+ if (sym == NULL) {
+ pr_warning("ignore unknown symbol: %s\n",
+ con->filters->syms[i]);
+ continue;
+ }
+
+ addrs = realloc(con->filters->addrs,
+ (con->filters->nr_addrs + 1) * sizeof(*addrs));
+ if (addrs == NULL) {
+ pr_warning("memory allocation failure\n");
+ continue;
+ }
+
+ addrs[con->filters->nr_addrs++] = kmap->unmap_ip(kmap, sym->start);
+ con->filters->addrs = addrs;
+ }
+ naddrs = con->filters->nr_addrs;
+ }
bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus);
bpf_map__set_max_entries(skel->maps.task_filter, ntasks);
+ bpf_map__set_max_entries(skel->maps.type_filter, ntypes);
+ bpf_map__set_max_entries(skel->maps.addr_filter, naddrs);
if (lock_contention_bpf__load(skel) < 0) {
pr_err("Failed to load lock-contention BPF skeleton\n");
@@ -90,6 +123,26 @@ int lock_contention_prepare(struct lock_contention *con)
bpf_map_update_elem(fd, &pid, &val, BPF_ANY);
}
+ if (con->filters->nr_types) {
+ u8 val = 1;
+
+ skel->bss->has_type = 1;
+ fd = bpf_map__fd(skel->maps.type_filter);
+
+ for (i = 0; i < con->filters->nr_types; i++)
+ bpf_map_update_elem(fd, &con->filters->types[i], &val, BPF_ANY);
+ }
+
+ if (con->filters->nr_addrs) {
+ u8 val = 1;
+
+ skel->bss->has_addr = 1;
+ fd = bpf_map__fd(skel->maps.addr_filter);
+
+ for (i = 0; i < con->filters->nr_addrs; i++)
+ bpf_map_update_elem(fd, &con->filters->addrs[i], &val, BPF_ANY);
+ }
+
/* these don't work well if in the rodata section */
skel->bss->stack_skip = con->stack_skip;
skel->bss->aggr_mode = con->aggr_mode;
@@ -215,7 +268,7 @@ int lock_contention_read(struct lock_contention *con)
break;
}
- if (verbose) {
+ if (verbose > 0) {
st->callstack = memdup(stack_trace, stack_size);
if (st->callstack == NULL)
break;
diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
index 11b0fc7ee53b..ad0ca5d50557 100644
--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
+++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
@@ -62,10 +62,26 @@ struct {
__uint(max_entries, 1);
} task_filter SEC(".maps");
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(key_size, sizeof(__u32));
+ __uint(value_size, sizeof(__u8));
+ __uint(max_entries, 1);
+} type_filter SEC(".maps");
+
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(key_size, sizeof(__u64));
+ __uint(value_size, sizeof(__u8));
+ __uint(max_entries, 1);
+} addr_filter SEC(".maps");
+
/* control flags */
int enabled;
int has_cpu;
int has_task;
+int has_type;
+int has_addr;
int stack_skip;
/* determine the key of lock stat */
@@ -74,7 +90,7 @@ int aggr_mode;
/* error stat */
int lost;
-static inline int can_record(void)
+static inline int can_record(u64 *ctx)
{
if (has_cpu) {
__u32 cpu = bpf_get_smp_processor_id();
@@ -94,6 +110,24 @@ static inline int can_record(void)
return 0;
}
+ if (has_type) {
+ __u8 *ok;
+ __u32 flags = (__u32)ctx[1];
+
+ ok = bpf_map_lookup_elem(&type_filter, &flags);
+ if (!ok)
+ return 0;
+ }
+
+ if (has_addr) {
+ __u8 *ok;
+ __u64 addr = ctx[0];
+
+ ok = bpf_map_lookup_elem(&addr_filter, &addr);
+ if (!ok)
+ return 0;
+ }
+
return 1;
}
@@ -116,7 +150,7 @@ int contention_begin(u64 *ctx)
__u32 pid;
struct tstamp_data *pelem;
- if (!enabled || !can_record())
+ if (!enabled || !can_record(ctx))
return 0;
pid = bpf_get_current_pid_tgid();
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 65e6c22f38e4..190e818a0717 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -241,6 +241,10 @@ int perf_quiet_option(void)
opt++;
}
+ /* For debug variables that are used as bool types, set to 0. */
+ redirect_to_stderr = 0;
+ debug_peo_args = 0;
+
return 0;
}
diff --git a/tools/perf/util/dlfilter.c b/tools/perf/util/dlfilter.c
index 54e4d4495e00..37beb7530288 100644
--- a/tools/perf/util/dlfilter.c
+++ b/tools/perf/util/dlfilter.c
@@ -579,7 +579,7 @@ static void list_filters(const char *dirname)
if (!get_filter_desc(dirname, entry->d_name, &desc, &long_desc))
continue;
printf(" %-36s %s\n", entry->d_name, desc ? desc : "");
- if (verbose) {
+ if (verbose > 0) {
char *p = long_desc;
char *line;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 17a05e943b44..b6e4b4edde43 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1781,8 +1781,8 @@ static void hierarchy_insert_output_entry(struct rb_root_cached *root,
/* update column width of dynamic entry */
perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
- if (perf_hpp__is_dynamic_entry(fmt))
- fmt->sort(fmt, he, NULL);
+ if (fmt->init)
+ fmt->init(fmt, he);
}
}
@@ -1879,10 +1879,10 @@ static void __hists__insert_output_entry(struct rb_root_cached *entries,
rb_link_node(&he->rb_node, parent, p);
rb_insert_color_cached(&he->rb_node, entries, leftmost);
+ /* update column width of dynamic entries */
perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) {
- if (perf_hpp__is_dynamic_entry(fmt) &&
- perf_hpp__defined_dynamic_entry(fmt, he->hists))
- fmt->sort(fmt, he, NULL); /* update column width */
+ if (fmt->init)
+ fmt->init(fmt, he);
}
}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ebd8a8f783ee..d93a4e510dc7 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -272,6 +272,7 @@ struct perf_hpp_fmt {
struct hists *hists, int line, int *span);
int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
struct hists *hists);
+ void (*init)(struct perf_hpp_fmt *fmt, struct hist_entry *he);
int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
struct hist_entry *he);
int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
diff --git a/tools/perf/util/lock-contention.h b/tools/perf/util/lock-contention.h
index 47fd47fb56c1..b99e83fccf5c 100644
--- a/tools/perf/util/lock-contention.h
+++ b/tools/perf/util/lock-contention.h
@@ -5,6 +5,15 @@
#include <linux/list.h>
#include <linux/rbtree.h>
+struct lock_filter {
+ int nr_types;
+ int nr_addrs;
+ int nr_syms;
+ unsigned int *types;
+ unsigned long *addrs;
+ char **syms;
+};
+
struct lock_stat {
struct hlist_node hash_entry;
struct rb_node rb; /* used for sorting */
@@ -113,6 +122,7 @@ struct lock_contention {
struct target *target;
struct machine *machine;
struct hlist_head *result;
+ struct lock_filter *filters;
unsigned long map_nr_entries;
int lost;
int max_stack;
diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
index d47820c0b4d4..2c96aa3cc1ec 100644
--- a/tools/perf/util/scripting-engines/Build
+++ b/tools/perf/util/scripting-engines/Build
@@ -5,4 +5,4 @@ endif
CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default -Wno-bad-function-cast -Wno-declaration-after-statement -Wno-switch-enum
-CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-deprecated-declarations
+CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-deprecated-declarations -Wno-switch-enum
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 4f265d0222c4..c294db713677 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -3,11 +3,20 @@ from subprocess import Popen, PIPE
from re import sub
cc = getenv("CC")
-cc_is_clang = b"clang version" in Popen([cc.split()[0], "-v"], stderr=PIPE).stderr.readline()
+
+# Check if CC has options, as is the case in yocto, where it uses CC="cc --sysroot..."
+cc_tokens = cc.split()
+if len(cc_tokens) > 1:
+ cc = cc_tokens[0]
+ cc_options = " ".join([str(e) for e in cc_tokens[1:]]) + " "
+else:
+ cc_options = ""
+
+cc_is_clang = b"clang version" in Popen([cc, "-v"], stderr=PIPE).stderr.readline()
src_feature_tests = getenv('srctree') + '/tools/build/feature'
def clang_has_option(option):
- cc_output = Popen([cc.split()[0], str(cc.split()[1:]) + option, path.join(src_feature_tests, "test-hello.c") ], stderr=PIPE).stderr.readlines()
+ cc_output = Popen([cc, cc_options + option, path.join(src_feature_tests, "test-hello.c") ], stderr=PIPE).stderr.readlines()
return [o for o in cc_output if ((b"unknown argument" in o) or (b"is not supported" in o))] == [ ]
if cc_is_clang:
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 0ecc2cb13792..e188f74698dd 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -374,6 +374,18 @@ char *hist_entry__srcline(struct hist_entry *he)
static int64_t
sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
{
+ int64_t ret;
+
+ ret = _sort__addr_cmp(left->ip, right->ip);
+ if (ret)
+ return ret;
+
+ return sort__dso_cmp(left, right);
+}
+
+static int64_t
+sort__srcline_collapse(struct hist_entry *left, struct hist_entry *right)
+{
if (!left->srcline)
left->srcline = hist_entry__srcline(left);
if (!right->srcline)
@@ -382,18 +394,31 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
return strcmp(right->srcline, left->srcline);
}
-static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
- size_t size, unsigned int width)
+static int64_t
+sort__srcline_sort(struct hist_entry *left, struct hist_entry *right)
+{
+ return sort__srcline_collapse(left, right);
+}
+
+static void
+sort__srcline_init(struct hist_entry *he)
{
if (!he->srcline)
he->srcline = hist_entry__srcline(he);
+}
+static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
+ size_t size, unsigned int width)
+{
return repsep_snprintf(bf, size, "%-.*s", width, he->srcline);
}
struct sort_entry sort_srcline = {
.se_header = "Source:Line",
.se_cmp = sort__srcline_cmp,
+ .se_collapse = sort__srcline_collapse,
+ .se_sort = sort__srcline_sort,
+ .se_init = sort__srcline_init,
.se_snprintf = hist_entry__srcline_snprintf,
.se_width_idx = HISTC_SRCLINE,
};
@@ -408,6 +433,12 @@ static char *addr_map_symbol__srcline(struct addr_map_symbol *ams)
static int64_t
sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
{
+ return left->branch_info->from.addr - right->branch_info->from.addr;
+}
+
+static int64_t
+sort__srcline_from_collapse(struct hist_entry *left, struct hist_entry *right)
+{
if (!left->branch_info->srcline_from)
left->branch_info->srcline_from = addr_map_symbol__srcline(&left->branch_info->from);
@@ -417,6 +448,18 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
}
+static int64_t
+sort__srcline_from_sort(struct hist_entry *left, struct hist_entry *right)
+{
+ return sort__srcline_from_collapse(left, right);
+}
+
+static void sort__srcline_from_init(struct hist_entry *he)
+{
+ if (!he->branch_info->srcline_from)
+ he->branch_info->srcline_from = addr_map_symbol__srcline(&he->branch_info->from);
+}
+
static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
@@ -426,6 +469,9 @@ static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf,
struct sort_entry sort_srcline_from = {
.se_header = "From Source:Line",
.se_cmp = sort__srcline_from_cmp,
+ .se_collapse = sort__srcline_from_collapse,
+ .se_sort = sort__srcline_from_sort,
+ .se_init = sort__srcline_from_init,
.se_snprintf = hist_entry__srcline_from_snprintf,
.se_width_idx = HISTC_SRCLINE_FROM,
};
@@ -435,6 +481,12 @@ struct sort_entry sort_srcline_from = {
static int64_t
sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
{
+ return left->branch_info->to.addr - right->branch_info->to.addr;
+}
+
+static int64_t
+sort__srcline_to_collapse(struct hist_entry *left, struct hist_entry *right)
+{
if (!left->branch_info->srcline_to)
left->branch_info->srcline_to = addr_map_symbol__srcline(&left->branch_info->to);
@@ -444,6 +496,18 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
}
+static int64_t
+sort__srcline_to_sort(struct hist_entry *left, struct hist_entry *right)
+{
+ return sort__srcline_to_collapse(left, right);
+}
+
+static void sort__srcline_to_init(struct hist_entry *he)
+{
+ if (!he->branch_info->srcline_to)
+ he->branch_info->srcline_to = addr_map_symbol__srcline(&he->branch_info->to);
+}
+
static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
@@ -453,6 +517,9 @@ static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf,
struct sort_entry sort_srcline_to = {
.se_header = "To Source:Line",
.se_cmp = sort__srcline_to_cmp,
+ .se_collapse = sort__srcline_to_collapse,
+ .se_sort = sort__srcline_to_sort,
+ .se_init = sort__srcline_to_init,
.se_snprintf = hist_entry__srcline_to_snprintf,
.se_width_idx = HISTC_SRCLINE_TO,
};
@@ -544,18 +611,41 @@ sort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right)
return strcmp(right->srcfile, left->srcfile);
}
-static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf,
- size_t size, unsigned int width)
+static int64_t
+sort__srcfile_collapse(struct hist_entry *left, struct hist_entry *right)
+{
+ if (!left->srcfile)
+ left->srcfile = hist_entry__get_srcfile(left);
+ if (!right->srcfile)
+ right->srcfile = hist_entry__get_srcfile(right);
+
+ return strcmp(right->srcfile, left->srcfile);
+}
+
+static int64_t
+sort__srcfile_sort(struct hist_entry *left, struct hist_entry *right)
+{
+ return sort__srcfile_collapse(left, right);
+}
+
+static void sort__srcfile_init(struct hist_entry *he)
{
if (!he->srcfile)
he->srcfile = hist_entry__get_srcfile(he);
+}
+static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf,
+ size_t size, unsigned int width)
+{
return repsep_snprintf(bf, size, "%-.*s", width, he->srcfile);
}
struct sort_entry sort_srcfile = {
.se_header = "Source File",
.se_cmp = sort__srcfile_cmp,
+ .se_collapse = sort__srcfile_collapse,
+ .se_sort = sort__srcfile_sort,
+ .se_init = sort__srcfile_init,
.se_snprintf = hist_entry__srcfile_snprintf,
.se_width_idx = HISTC_SRCFILE,
};
@@ -2251,6 +2341,19 @@ static void hse_free(struct perf_hpp_fmt *fmt)
free(hse);
}
+static void hse_init(struct perf_hpp_fmt *fmt, struct hist_entry *he)
+{
+ struct hpp_sort_entry *hse;
+
+ if (!perf_hpp__is_sort_entry(fmt))
+ return;
+
+ hse = container_of(fmt, struct hpp_sort_entry, hpp);
+
+ if (hse->se->se_init)
+ hse->se->se_init(he);
+}
+
static struct hpp_sort_entry *
__sort_dimension__alloc_hpp(struct sort_dimension *sd, int level)
{
@@ -2274,6 +2377,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd, int level)
hse->hpp.sort = __sort__hpp_sort;
hse->hpp.equal = __sort__hpp_equal;
hse->hpp.free = hse_free;
+ hse->hpp.init = hse_init;
INIT_LIST_HEAD(&hse->hpp.list);
INIT_LIST_HEAD(&hse->hpp.sort_list);
@@ -2556,11 +2660,6 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
- if (b == NULL) {
- update_dynamic_len(hde, a);
- return 0;
- }
-
field = hde->field;
if (field->flags & TEP_FIELD_IS_DYNAMIC) {
unsigned long long dyn;
@@ -2610,6 +2709,17 @@ static void hde_free(struct perf_hpp_fmt *fmt)
free(hde);
}
+static void __sort__hde_init(struct perf_hpp_fmt *fmt, struct hist_entry *he)
+{
+ struct hpp_dynamic_entry *hde;
+
+ if (!perf_hpp__is_dynamic_entry(fmt))
+ return;
+
+ hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+ update_dynamic_len(hde, he);
+}
+
static struct hpp_dynamic_entry *
__alloc_dynamic_entry(struct evsel *evsel, struct tep_format_field *field,
int level)
@@ -2632,6 +2742,7 @@ __alloc_dynamic_entry(struct evsel *evsel, struct tep_format_field *field,
hde->hpp.entry = __sort__hde_entry;
hde->hpp.color = NULL;
+ hde->hpp.init = __sort__hde_init;
hde->hpp.cmp = __sort__hde_cmp;
hde->hpp.collapse = __sort__hde_cmp;
hde->hpp.sort = __sort__hde_cmp;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 04ff8b61a2a7..921715e6aec4 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -282,6 +282,7 @@ struct sort_entry {
int (*se_snprintf)(struct hist_entry *he, char *bf, size_t size,
unsigned int width);
int (*se_filter)(struct hist_entry *he, int type, const void *arg);
+ void (*se_init)(struct hist_entry *he);
u8 se_width_idx;
};
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index af468e3bb6fa..33321867416b 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -550,6 +550,9 @@ static int addr2line(const char *dso_name, u64 addr,
size_t inline_count = 0;
if (!a2l) {
+ if (!filename__has_section(dso_name, ".debug_line"))
+ goto out;
+
dso->a2l = addr2line_subprocess_init(dso_name);
a2l = dso->a2l;
}
@@ -570,13 +573,15 @@ static int addr2line(const char *dso_name, u64 addr,
* "??"/"??:0" lines.
*/
if (fprintf(a2l->to_child, "%016"PRIx64"\n,\n", addr) < 0 || fflush(a2l->to_child) != 0) {
- pr_warning("%s %s: could not send request\n", __func__, dso_name);
+ if (!symbol_conf.disable_add2line_warn)
+ pr_warning("%s %s: could not send request\n", __func__, dso_name);
goto out;
}
switch (read_addr2line_record(a2l, &record_function, &record_filename, &record_line_nr)) {
case -1:
- pr_warning("%s %s: could not read first record\n", __func__, dso_name);
+ if (!symbol_conf.disable_add2line_warn)
+ pr_warning("%s %s: could not read first record\n", __func__, dso_name);
goto out;
case 0:
/*
@@ -585,14 +590,17 @@ static int addr2line(const char *dso_name, u64 addr,
*/
switch (read_addr2line_record(a2l, NULL, NULL, NULL)) {
case -1:
- pr_warning("%s %s: could not read delimiter record\n", __func__, dso_name);
+ if (!symbol_conf.disable_add2line_warn)
+ pr_warning("%s %s: could not read delimiter record\n",
+ __func__, dso_name);
break;
case 0:
/* As expected. */
break;
default:
- pr_warning("%s %s: unexpected record instead of sentinel",
- __func__, dso_name);
+ if (!symbol_conf.disable_add2line_warn)
+ pr_warning("%s %s: unexpected record instead of sentinel",
+ __func__, dso_name);
break;
}
goto out;
@@ -716,7 +724,7 @@ out:
if (!show_addr)
return (show_sym && sym) ?
- strndup(sym->name, sym->namelen) : NULL;
+ strndup(sym->name, sym->namelen) : SRCLINE_UNKNOWN;
if (sym) {
if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 80345695b136..96767d1b3f1c 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -233,6 +233,34 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
return NULL;
}
+bool filename__has_section(const char *filename, const char *sec)
+{
+ int fd;
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
+ bool found = false;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return false;
+
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+ if (elf == NULL)
+ goto out;
+
+ if (gelf_getehdr(elf, &ehdr) == NULL)
+ goto elf_out;
+
+ found = !!elf_section_by_name(elf, &ehdr, &shdr, sec, NULL);
+
+elf_out:
+ elf_end(elf);
+out:
+ close(fd);
+ return found;
+}
+
static int elf_read_program_header(Elf *elf, u64 vaddr, GElf_Phdr *phdr)
{
size_t i, phdrnum;
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index f9eb0bee7f15..a81a14769bd1 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -385,3 +385,8 @@ char *dso__demangle_sym(struct dso *dso __maybe_unused,
{
return NULL;
}
+
+bool filename__has_section(const char *filename __maybe_unused, const char *sec __maybe_unused)
+{
+ return false;
+}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index e297de14184c..f735108c4d4e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -165,6 +165,7 @@ int modules__parse(const char *filename, void *arg,
u64 start, u64 size));
int filename__read_debuglink(const char *filename, char *debuglink,
size_t size);
+bool filename__has_section(const char *filename, const char *sec);
struct perf_env;
int symbol__init(struct perf_env *env);