Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf srcline: Add configuration support for the addr2line style

Allow the addr2line style to be specified on the `perf report` command
line or in the .perfconfig file.

Committer testing:

The methods:

# perf probe -x ~/bin/perf -F *__addr2line
cmd__addr2line
libbfd__addr2line
libdw__addr2line
llvm__addr2line
#

So if we configure one of them, say 'addr2line':

# perf config addr2line.style=addr2line
# perf config addr2line.style
addr2line.style=addr2line
#

And have probes on all of them:

# perf probe -x ~/bin/perf *__addr2line
Added new events:
probe_perf:cmd__addr2line (on *__addr2line in /home/acme/bin/perf)
probe_perf:llvm__addr2line (on *__addr2line in /home/acme/bin/perf)
probe_perf:libbfd__addr2line (on *__addr2line in /home/acme/bin/perf)
probe_perf:libdw__addr2line (on *__addr2line in /home/acme/bin/perf)

You can now use it in all perf tools, such as:

perf record -e probe_perf:libdw__addr2line -aR sleep 1

#

Only the selected method should be used:

# perf stat -e probe_perf:*_addr2line perf report -f --dso perf --stdio -s srcfile,srcline
# Total Lost Samples: 0
#
# Samples: 4K of event 'cpu/cycles/Pu'
# Event count (approx.): 5535180842
#
# Overhead Source File Source:Line
# ........ ............ ...............
#
99.04% inlineloop.c inlineloop.c:21
0.46% inlineloop.c inlineloop.c:20

#
# (Tip: For hierarchical output, try: perf report --hierarchy)
#

Performance counter stats for 'perf report -f --dso perf --stdio -s srcfile,srcline':

44 probe_perf:cmd__addr2line
0 probe_perf:llvm__addr2line
0 probe_perf:libbfd__addr2line
0 probe_perf:libdw__addr2line

0.035915611 seconds time elapsed

0.028008000 seconds user
0.009051000 seconds sys
#

I checked and that is the case for the other methods.

Also when using:

# perf config addr2line.style=libdw,llvm

Performance counter stats for 'perf report -f --dso perf --stdio -s srcfile,srcline':

0 probe_perf:cmd__addr2line
23 probe_perf:llvm__addr2line
0 probe_perf:libbfd__addr2line
44 probe_perf:libdw__addr2line

Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Brennan <stephen.s.brennan@oracle.com>
Cc: Tony Jones <tonyj@suse.de>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
a2297e74 ec942665

+113 -11
+10
tools/perf/builtin-report.c
··· 1271 1271 return 0; 1272 1272 } 1273 1273 1274 + static int 1275 + report_parse_addr2line_config(const struct option *opt __maybe_unused, 1276 + const char *arg, int unset __maybe_unused) 1277 + { 1278 + return addr2line_configure("addr2line.style", arg, NULL); 1279 + } 1280 + 1274 1281 static int process_attr(const struct perf_tool *tool __maybe_unused, 1275 1282 union perf_event *event, 1276 1283 struct evlist **pevlist) ··· 1454 1447 "objdump binary to use for disassembly and annotations"), 1455 1448 OPT_STRING(0, "addr2line", &addr2line_path, "path", 1456 1449 "addr2line binary to use for line numbers"), 1450 + OPT_CALLBACK(0, "addr2line-style", NULL, "addr2line style", 1451 + "addr2line styles (libdw,llvm,libbfd,addr2line)", 1452 + report_parse_addr2line_config), 1457 1453 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 1458 1454 "Symbol demangling. Enabled by default, use --no-demangle to disable."), 1459 1455 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
+4
tools/perf/util/config.c
··· 20 20 #include "util/stat.h" /* perf_stat__set_big_num */ 21 21 #include "util/evsel.h" /* evsel__hw_names, evsel__use_bpf_counters */ 22 22 #include "util/addr2line.h" /* addr2line_timeout_ms */ 23 + #include "srcline.h" 23 24 #include "build-id.h" 24 25 #include "debug.h" 25 26 #include "config.h" ··· 519 518 520 519 if (strstarts(var, "stat.")) 521 520 return perf_stat_config(var, value); 521 + 522 + if (strstarts(var, "addr2line.")) 523 + return addr2line_configure(var, value, dummy); 522 524 523 525 /* Add other config variables here. */ 524 526 return 0;
+87 -11
tools/perf/util/srcline.c
··· 7 7 #include "llvm.h" 8 8 #include "symbol.h" 9 9 #include "libdw.h" 10 + #include "debug.h" 10 11 11 12 #include <inttypes.h> 12 13 #include <string.h> 14 + #include <linux/string.h> 13 15 14 16 bool srcline_full_filename; 15 17 ··· 140 138 struct dso *dso, bool unwind_inlines, struct inline_node *node, 141 139 struct symbol *sym) 142 140 { 143 - int ret; 141 + int ret = 0; 144 142 145 - ret = libdw__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, node, sym); 146 - if (ret > 0) 147 - return ret; 143 + if (symbol_conf.addr2line_style[0] == A2L_STYLE_UNKNOWN) { 144 + int i = 0; 148 145 149 - ret = llvm__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, node, sym); 150 - if (ret > 0) 151 - return ret; 146 + /* Default addr2line fallback order. */ 147 + #ifdef HAVE_LIBDW_SUPPORT 148 + symbol_conf.addr2line_style[i++] = A2L_STYLE_LIBDW; 149 + #endif 150 + #ifdef HAVE_LIBLLVM_SUPPORT 151 + symbol_conf.addr2line_style[i++] = A2L_STYLE_LLVM; 152 + #endif 153 + #ifdef HAVE_LIBBFD_SUPPORT 154 + symbol_conf.addr2line_style[i++] = A2L_STYLE_LIBBFD; 155 + #endif 156 + symbol_conf.addr2line_style[i++] = A2L_STYLE_CMD; 157 + } 152 158 153 - ret = libbfd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, node, sym); 154 - if (ret > 0) 155 - return ret; 159 + for (size_t i = 0; i < ARRAY_SIZE(symbol_conf.addr2line_style); i++) { 160 + switch (symbol_conf.addr2line_style[i]) { 161 + case A2L_STYLE_LIBDW: 162 + ret = libdw__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, 163 + node, sym); 164 + break; 165 + case A2L_STYLE_LLVM: 166 + ret = llvm__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, 167 + node, sym); 168 + break; 169 + case A2L_STYLE_LIBBFD: 170 + ret = libbfd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, 171 + node, sym); 172 + break; 173 + case A2L_STYLE_CMD: 174 + ret = cmd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, 175 + node, sym); 176 + break; 177 + case A2L_STYLE_UNKNOWN: 178 + default: 179 + break; 180 + } 181 + if (ret > 0) 182 + return ret; 183 + } 156 184 157 - return cmd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, node, sym); 185 + return 0; 186 + } 187 + 188 + int addr2line_configure(const char *var, const char *value, void *cb __maybe_unused) 189 + { 190 + static const char * const a2l_style_names[] = { 191 + [A2L_STYLE_LIBDW] = "libdw", 192 + [A2L_STYLE_LLVM] = "llvm", 193 + [A2L_STYLE_LIBBFD] = "libbfd", 194 + [A2L_STYLE_CMD] = "addr2line", 195 + NULL 196 + }; 197 + 198 + char *s, *p, *saveptr; 199 + size_t i = 0; 200 + 201 + if (strcmp(var, "addr2line.style")) 202 + return 0; 203 + 204 + if (!value) 205 + return -1; 206 + 207 + s = strdup(value); 208 + if (!s) 209 + return -1; 210 + 211 + p = strtok_r(s, ",", &saveptr); 212 + while (p && i < ARRAY_SIZE(symbol_conf.addr2line_style)) { 213 + bool found = false; 214 + char *q = strim(p); 215 + 216 + for (size_t j = A2L_STYLE_LIBDW; j < MAX_A2L_STYLE; j++) { 217 + if (!strcasecmp(q, a2l_style_names[j])) { 218 + symbol_conf.addr2line_style[i++] = j; 219 + found = true; 220 + break; 221 + } 222 + } 223 + if (!found) 224 + pr_warning("Unknown addr2line style: %s\n", q); 225 + p = strtok_r(NULL, ",", &saveptr); 226 + } 227 + 228 + free(s); 229 + return 0; 158 230 } 159 231 160 232 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
+2
tools/perf/util/srcline.h
··· 63 63 struct symbol *base_sym, 64 64 const char *funcname); 65 65 66 + int addr2line_configure(const char *var, const char *value, void *cb); 67 + 66 68 #endif /* PERF_SRCLINE_H */
+10
tools/perf/util/symbol_conf.h
··· 9 9 struct strlist; 10 10 struct intlist; 11 11 12 + enum a2l_style { 13 + A2L_STYLE_UNKNOWN = 0, 14 + A2L_STYLE_LIBDW, 15 + A2L_STYLE_LLVM, 16 + A2L_STYLE_LIBBFD, 17 + A2L_STYLE_CMD, 18 + }; 19 + #define MAX_A2L_STYLE (A2L_STYLE_CMD + 1) 20 + 12 21 struct symbol_conf { 13 22 bool nanosecs; 14 23 unsigned short priv_size; ··· 79 70 *col_width_list_str, 80 71 *bt_stop_list_str; 81 72 const char *addr2line_path; 73 + enum a2l_style addr2line_style[MAX_A2L_STYLE]; 82 74 unsigned long time_quantum; 83 75 struct strlist *dso_list, 84 76 *comm_list,