aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Makefile.perf24
-rw-r--r--tools/perf/arch/x86/Makefile5
-rw-r--r--tools/perf/arch/x86/util/unwind-libdw.c51
-rw-r--r--tools/perf/config/Makefile232
-rw-r--r--tools/perf/config/feature-checks/Makefile6
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c13
-rw-r--r--tools/perf/tests/make25
-rw-r--r--tools/perf/util/dso.c4
-rw-r--r--tools/perf/util/symbol-elf.c2
-rw-r--r--tools/perf/util/symbol.c61
-rw-r--r--tools/perf/util/unwind-libdw.c210
-rw-r--r--tools/perf/util/unwind-libdw.h21
13 files changed, 569 insertions, 90 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 77b153fa23a5..1f7ec48ac959 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -7,6 +7,8 @@ include config/utilities.mak
7 7
8# Define V to have a more verbose compile. 8# Define V to have a more verbose compile.
9# 9#
10# Define VF to have a more verbose feature check output.
11#
10# Define O to save output files in a separate directory. 12# Define O to save output files in a separate directory.
11# 13#
12# Define ARCH as name of target architecture if you want cross-builds. 14# Define ARCH as name of target architecture if you want cross-builds.
@@ -55,6 +57,9 @@ include config/utilities.mak
55# Define NO_LIBAUDIT if you do not want libaudit support 57# Define NO_LIBAUDIT if you do not want libaudit support
56# 58#
57# Define NO_LIBBIONIC if you do not want bionic support 59# Define NO_LIBBIONIC if you do not want bionic support
60#
61# Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support
62# for dwarf backtrace post unwind.
58 63
59ifeq ($(srctree),) 64ifeq ($(srctree),)
60srctree := $(patsubst %/,%,$(dir $(shell pwd))) 65srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -404,7 +409,7 @@ endif
404LIB_OBJS += $(OUTPUT)tests/code-reading.o 409LIB_OBJS += $(OUTPUT)tests/code-reading.o
405LIB_OBJS += $(OUTPUT)tests/sample-parsing.o 410LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
406LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o 411LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
407ifndef NO_LIBUNWIND 412ifndef NO_DWARF_UNWIND
408ifeq ($(ARCH),x86) 413ifeq ($(ARCH),x86)
409LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o 414LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
410endif 415endif
@@ -476,6 +481,11 @@ ifndef NO_DWARF
476endif # NO_DWARF 481endif # NO_DWARF
477endif # NO_LIBELF 482endif # NO_LIBELF
478 483
484ifndef NO_LIBDW_DWARF_UNWIND
485 LIB_OBJS += $(OUTPUT)util/unwind-libdw.o
486 LIB_H += util/unwind-libdw.h
487endif
488
479ifndef NO_LIBUNWIND 489ifndef NO_LIBUNWIND
480 LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o 490 LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o
481endif 491endif
@@ -712,9 +722,15 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
712# we depend the various files onto their directories. 722# we depend the various files onto their directories.
713DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS) 723DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
714DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h 724DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
715$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS))) 725# no need to add flex objects, because they depend on bison ones
726DIRECTORY_DEPS += $(OUTPUT)util/parse-events-bison.c
727DIRECTORY_DEPS += $(OUTPUT)util/pmu-bison.c
728
729OUTPUT_DIRECTORIES := $(sort $(dir $(DIRECTORY_DEPS)))
730
731$(DIRECTORY_DEPS): | $(OUTPUT_DIRECTORIES)
716# In the second step, we make a rule to actually create these directories 732# In the second step, we make a rule to actually create these directories
717$(sort $(dir $(DIRECTORY_DEPS))): 733$(OUTPUT_DIRECTORIES):
718 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null 734 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
719 735
720$(LIB_FILE): $(LIB_OBJS) 736$(LIB_FILE): $(LIB_OBJS)
@@ -891,7 +907,7 @@ config-clean:
891clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 907clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
892 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 908 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
893 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 909 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
894 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 910 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
895 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 911 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
896 $(python-clean) 912 $(python-clean)
897 913
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 4fa9be983ad1..1641542e3636 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -4,6 +4,11 @@ LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 4endif
5ifndef NO_LIBUNWIND 5ifndef NO_LIBUNWIND
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o 6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
7endif
8ifndef NO_LIBDW_DWARF_UNWIND
9LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
10endif
11ifndef NO_DWARF_UNWIND
7LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o 12LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
8LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o 13LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
9endif 14endif
diff --git a/tools/perf/arch/x86/util/unwind-libdw.c b/tools/perf/arch/x86/util/unwind-libdw.c
new file mode 100644
index 000000000000..c4b72176ca83
--- /dev/null
+++ b/tools/perf/arch/x86/util/unwind-libdw.c
@@ -0,0 +1,51 @@
1#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h"
4
5bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
6{
7 struct unwind_info *ui = arg;
8 struct regs_dump *user_regs = &ui->sample->user_regs;
9 Dwarf_Word dwarf_regs[17];
10 unsigned nregs;
11
12#define REG(r) ({ \
13 Dwarf_Word val = 0; \
14 perf_reg_value(&val, user_regs, PERF_REG_X86_##r); \
15 val; \
16})
17
18 if (user_regs->abi == PERF_SAMPLE_REGS_ABI_32) {
19 dwarf_regs[0] = REG(AX);
20 dwarf_regs[1] = REG(CX);
21 dwarf_regs[2] = REG(DX);
22 dwarf_regs[3] = REG(BX);
23 dwarf_regs[4] = REG(SP);
24 dwarf_regs[5] = REG(BP);
25 dwarf_regs[6] = REG(SI);
26 dwarf_regs[7] = REG(DI);
27 dwarf_regs[8] = REG(IP);
28 nregs = 9;
29 } else {
30 dwarf_regs[0] = REG(AX);
31 dwarf_regs[1] = REG(DX);
32 dwarf_regs[2] = REG(CX);
33 dwarf_regs[3] = REG(BX);
34 dwarf_regs[4] = REG(SI);
35 dwarf_regs[5] = REG(DI);
36 dwarf_regs[6] = REG(BP);
37 dwarf_regs[7] = REG(SP);
38 dwarf_regs[8] = REG(R8);
39 dwarf_regs[9] = REG(R9);
40 dwarf_regs[10] = REG(R10);
41 dwarf_regs[11] = REG(R11);
42 dwarf_regs[12] = REG(R12);
43 dwarf_regs[13] = REG(R13);
44 dwarf_regs[14] = REG(R14);
45 dwarf_regs[15] = REG(R15);
46 dwarf_regs[16] = REG(IP);
47 nregs = 17;
48 }
49
50 return dwfl_thread_state_registers(thread, 0, nregs, dwarf_regs);
51}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 1686583ff7fc..f7c81d3e2422 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -59,6 +59,18 @@ ifeq ($(NO_PERF_REGS),0)
59 CFLAGS += -DHAVE_PERF_REGS_SUPPORT 59 CFLAGS += -DHAVE_PERF_REGS_SUPPORT
60endif 60endif
61 61
62ifndef NO_LIBELF
63 # for linking with debug library, run like:
64 # make DEBUG=1 LIBDW_DIR=/opt/libdw/
65 ifdef LIBDW_DIR
66 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
67 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
68
69 FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
70 FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
71 endif
72endif
73
62# include ARCH specific config 74# include ARCH specific config
63-include $(src-perf)/arch/$(ARCH)/Makefile 75-include $(src-perf)/arch/$(ARCH)/Makefile
64 76
@@ -147,7 +159,35 @@ CORE_FEATURE_TESTS = \
147 libunwind \ 159 libunwind \
148 on-exit \ 160 on-exit \
149 stackprotector-all \ 161 stackprotector-all \
150 timerfd 162 timerfd \
163 libdw-dwarf-unwind
164
165LIB_FEATURE_TESTS = \
166 dwarf \
167 glibc \
168 gtk2 \
169 libaudit \
170 libbfd \
171 libelf \
172 libnuma \
173 libperl \
174 libpython \
175 libslang \
176 libunwind \
177 libdw-dwarf-unwind
178
179VF_FEATURE_TESTS = \
180 backtrace \
181 fortify-source \
182 gtk2-infobar \
183 libelf-getphdrnum \
184 libelf-mmap \
185 libpython-version \
186 on-exit \
187 stackprotector-all \
188 timerfd \
189 libunwind-debug-frame \
190 bionic
151 191
152# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. 192# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
153# If in the future we need per-feature checks/flags for features not 193# If in the future we need per-feature checks/flags for features not
@@ -161,17 +201,6 @@ endef
161$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat))) 201$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
162 202
163# 203#
164# So here we detect whether test-all was rebuilt, to be able
165# to skip the print-out of the long features list if the file
166# existed before and after it was built:
167#
168ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),)
169 test-all-failed := 1
170else
171 test-all-failed := 0
172endif
173
174#
175# Special fast-path for the 'all features are available' case: 204# Special fast-path for the 'all features are available' case:
176# 205#
177$(call feature_check,all,$(MSG)) 206$(call feature_check,all,$(MSG))
@@ -180,15 +209,6 @@ $(call feature_check,all,$(MSG))
180# Just in case the build freshly failed, make sure we print the 209# Just in case the build freshly failed, make sure we print the
181# feature matrix: 210# feature matrix:
182# 211#
183ifeq ($(feature-all), 0)
184 test-all-failed := 1
185endif
186
187ifeq ($(test-all-failed),1)
188 $(info )
189 $(info Auto-detecting system features:)
190endif
191
192ifeq ($(feature-all), 1) 212ifeq ($(feature-all), 1)
193 # 213 #
194 # test-all.c passed - just set all the core feature flags to 1: 214 # test-all.c passed - just set all the core feature flags to 1:
@@ -199,27 +219,6 @@ else
199 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat))) 219 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
200endif 220endif
201 221
202#
203# Print the result of the feature test:
204#
205feature_print = $(eval $(feature_print_code)) $(info $(MSG))
206
207define feature_print_code
208 ifeq ($(feature-$(1)), 1)
209 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
210 else
211 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
212 endif
213endef
214
215#
216# Only print out our features if we rebuilt the testcases or if a test failed:
217#
218ifeq ($(test-all-failed), 1)
219 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_print,$(feat)))
220 $(info )
221endif
222
223ifeq ($(feature-stackprotector-all), 1) 222ifeq ($(feature-stackprotector-all), 1)
224 CFLAGS += -fstack-protector-all 223 CFLAGS += -fstack-protector-all
225endif 224endif
@@ -264,6 +263,7 @@ ifdef NO_LIBELF
264 NO_DWARF := 1 263 NO_DWARF := 1
265 NO_DEMANGLE := 1 264 NO_DEMANGLE := 1
266 NO_LIBUNWIND := 1 265 NO_LIBUNWIND := 1
266 NO_LIBDW_DWARF_UNWIND := 1
267else 267else
268 ifeq ($(feature-libelf), 0) 268 ifeq ($(feature-libelf), 0)
269 ifeq ($(feature-glibc), 1) 269 ifeq ($(feature-glibc), 1)
@@ -282,13 +282,12 @@ else
282 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); 282 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
283 endif 283 endif
284 else 284 else
285 # for linking with debug library, run like: 285 ifndef NO_LIBDW_DWARF_UNWIND
286 # make DEBUG=1 LIBDW_DIR=/opt/libdw/ 286 ifneq ($(feature-libdw-dwarf-unwind),1)
287 ifdef LIBDW_DIR 287 NO_LIBDW_DWARF_UNWIND := 1
288 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include 288 msg := $(warning No libdw DWARF unwind found, Please install elfutils-devel/libdw-dev >= 0.158 and/or set LIBDW_DIR);
289 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib 289 endif
290 endif 290 endif
291
292 ifneq ($(feature-dwarf), 1) 291 ifneq ($(feature-dwarf), 1)
293 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 292 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
294 NO_DWARF := 1 293 NO_DWARF := 1
@@ -324,25 +323,51 @@ endif # NO_LIBELF
324 323
325ifndef NO_LIBUNWIND 324ifndef NO_LIBUNWIND
326 ifneq ($(feature-libunwind), 1) 325 ifneq ($(feature-libunwind), 1)
327 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1); 326 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
328 NO_LIBUNWIND := 1 327 NO_LIBUNWIND := 1
328 endif
329endif
330
331dwarf-post-unwind := 1
332dwarf-post-unwind-text := BUG
333
334# setup DWARF post unwinder
335ifdef NO_LIBUNWIND
336 ifdef NO_LIBDW_DWARF_UNWIND
337 msg := $(warning Disabling post unwind, no support found.);
338 dwarf-post-unwind := 0
329 else 339 else
330 ifeq ($(ARCH),arm) 340 dwarf-post-unwind-text := libdw
331 $(call feature_check,libunwind-debug-frame) 341 endif
332 ifneq ($(feature-libunwind-debug-frame), 1) 342else
333 msg := $(warning No debug_frame support found in libunwind); 343 dwarf-post-unwind-text := libunwind
334 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME 344 # Enable libunwind support by default.
335 endif 345 ifndef NO_LIBDW_DWARF_UNWIND
336 else 346 NO_LIBDW_DWARF_UNWIND := 1
337 # non-ARM has no dwarf_find_debug_frame() function: 347 endif
348endif
349
350ifeq ($(dwarf-post-unwind),1)
351 CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT
352else
353 NO_DWARF_UNWIND := 1
354endif
355
356ifndef NO_LIBUNWIND
357 ifeq ($(ARCH),arm)
358 $(call feature_check,libunwind-debug-frame)
359 ifneq ($(feature-libunwind-debug-frame), 1)
360 msg := $(warning No debug_frame support found in libunwind);
338 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME 361 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
339 endif 362 endif
340 363 else
341 CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT -DHAVE_LIBUNWIND_SUPPORT 364 # non-ARM has no dwarf_find_debug_frame() function:
342 EXTLIBS += $(LIBUNWIND_LIBS) 365 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
343 CFLAGS += $(LIBUNWIND_CFLAGS) 366 endif
344 LDFLAGS += $(LIBUNWIND_LDFLAGS) 367 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
345 endif # ifneq ($(feature-libunwind), 1) 368 EXTLIBS += $(LIBUNWIND_LIBS)
369 CFLAGS += $(LIBUNWIND_CFLAGS)
370 LDFLAGS += $(LIBUNWIND_LDFLAGS)
346endif 371endif
347 372
348ifndef NO_LIBAUDIT 373ifndef NO_LIBAUDIT
@@ -602,3 +627,84 @@ ifdef DESTDIR
602plugindir=$(libdir)/traceevent/plugins 627plugindir=$(libdir)/traceevent/plugins
603plugindir_SQ= $(subst ','\'',$(plugindir)) 628plugindir_SQ= $(subst ','\'',$(plugindir))
604endif 629endif
630
631#
632# Print the result of the feature test:
633#
634feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
635
636define feature_print_status_code
637 ifeq ($(feature-$(1)), 1)
638 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
639 else
640 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
641 endif
642endef
643
644feature_print_var = $(eval $(feature_print_var_code)) $(info $(MSG))
645define feature_print_var_code
646 MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
647endef
648
649feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
650define feature_print_text_code
651 MSG = $(shell printf '...%30s: %s' $(1) $(2))
652endef
653
654PERF_FEATURES := $(foreach feat,$(LIB_FEATURE_TESTS),feature-$(feat)($(feature-$(feat))))
655PERF_FEATURES_FILE := $(shell touch $(OUTPUT)PERF-FEATURES; cat $(OUTPUT)PERF-FEATURES)
656
657ifeq ($(dwarf-post-unwind),1)
658 PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text))
659endif
660
661# The $(display_lib) controls the default detection message
662# output. It's set if:
663# - detected features differes from stored features from
664# last build (in PERF-FEATURES file)
665# - one of the $(LIB_FEATURE_TESTS) is not detected
666# - VF is enabled
667
668ifneq ("$(PERF_FEATURES)","$(PERF_FEATURES_FILE)")
669 $(shell echo "$(PERF_FEATURES)" > $(OUTPUT)PERF-FEATURES)
670 display_lib := 1
671endif
672
673feature_check = $(eval $(feature_check_code))
674define feature_check_code
675 ifneq ($(feature-$(1)), 1)
676 display_lib := 1
677 endif
678endef
679
680$(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat)))
681
682ifeq ($(VF),1)
683 display_lib := 1
684 display_vf := 1
685endif
686
687ifeq ($(display_lib),1)
688 $(info )
689 $(info Auto-detecting system features:)
690 $(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_print_status,$(feat),))
691
692 ifeq ($(dwarf-post-unwind),1)
693 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
694 endif
695endif
696
697ifeq ($(display_vf),1)
698 $(foreach feat,$(VF_FEATURE_TESTS),$(call feature_print_status,$(feat),))
699 $(info )
700 $(call feature_print_var,prefix)
701 $(call feature_print_var,bindir)
702 $(call feature_print_var,libdir)
703 $(call feature_print_var,sysconfdir)
704 $(call feature_print_var,LIBUNWIND_DIR)
705 $(call feature_print_var,LIBDW_DIR)
706endif
707
708ifeq ($(display_lib),1)
709 $(info )
710endif
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 12e551346fa6..2b492f5480e2 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -26,7 +26,8 @@ FILES= \
26 test-libunwind-debug-frame.bin \ 26 test-libunwind-debug-frame.bin \
27 test-on-exit.bin \ 27 test-on-exit.bin \
28 test-stackprotector-all.bin \ 28 test-stackprotector-all.bin \
29 test-timerfd.bin 29 test-timerfd.bin \
30 test-libdw-dwarf-unwind.bin
30 31
31CC := $(CROSS_COMPILE)gcc -MD 32CC := $(CROSS_COMPILE)gcc -MD
32PKG_CONFIG := $(CROSS_COMPILE)pkg-config 33PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -141,6 +142,9 @@ test-backtrace.bin:
141test-timerfd.bin: 142test-timerfd.bin:
142 $(BUILD) 143 $(BUILD)
143 144
145test-libdw-dwarf-unwind.bin:
146 $(BUILD)
147
144-include *.d 148-include *.d
145 149
146############################### 150###############################
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index 9b8a544155bb..fc37eb3ca17b 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -89,6 +89,10 @@
89# include "test-stackprotector-all.c" 89# include "test-stackprotector-all.c"
90#undef main 90#undef main
91 91
92#define main main_test_libdw_dwarf_unwind
93# include "test-libdw-dwarf-unwind.c"
94#undef main
95
92int main(int argc, char *argv[]) 96int main(int argc, char *argv[])
93{ 97{
94 main_test_libpython(); 98 main_test_libpython();
@@ -111,6 +115,7 @@ int main(int argc, char *argv[])
111 main_test_libnuma(); 115 main_test_libnuma();
112 main_test_timerfd(); 116 main_test_timerfd();
113 main_test_stackprotector_all(); 117 main_test_stackprotector_all();
118 main_test_libdw_dwarf_unwind();
114 119
115 return 0; 120 return 0;
116} 121}
diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
new file mode 100644
index 000000000000..f676a3ff442a
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
@@ -0,0 +1,13 @@
1
2#include <elfutils/libdwfl.h>
3
4int main(void)
5{
6 /*
7 * This function is guarded via: __nonnull_attribute__ (1, 2).
8 * Passing '1' as arguments value. This code is never executed,
9 * only compiled.
10 */
11 dwfl_thread_getframes((void *) 1, (void *) 1, NULL);
12 return 0;
13}
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 00544b8b644b..5daeae1cb4c0 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -27,6 +27,7 @@ make_no_ui := NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
27make_no_demangle := NO_DEMANGLE=1 27make_no_demangle := NO_DEMANGLE=1
28make_no_libelf := NO_LIBELF=1 28make_no_libelf := NO_LIBELF=1
29make_no_libunwind := NO_LIBUNWIND=1 29make_no_libunwind := NO_LIBUNWIND=1
30make_no_libdw_dwarf_unwind := NO_LIBDW_DWARF_UNWIND=1
30make_no_backtrace := NO_BACKTRACE=1 31make_no_backtrace := NO_BACKTRACE=1
31make_no_libnuma := NO_LIBNUMA=1 32make_no_libnuma := NO_LIBNUMA=1
32make_no_libaudit := NO_LIBAUDIT=1 33make_no_libaudit := NO_LIBAUDIT=1
@@ -35,8 +36,9 @@ make_tags := tags
35make_cscope := cscope 36make_cscope := cscope
36make_help := help 37make_help := help
37make_doc := doc 38make_doc := doc
38make_perf_o := perf.o 39make_perf_o := perf.o
39make_util_map_o := util/map.o 40make_util_map_o := util/map.o
41make_util_pmu_bison_o := util/pmu-bison.o
40make_install := install 42make_install := install
41make_install_bin := install-bin 43make_install_bin := install-bin
42make_install_doc := install-doc 44make_install_doc := install-doc
@@ -49,6 +51,7 @@ make_install_pdf := install-pdf
49make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 51make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
50make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 52make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
51make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 53make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
54make_minimal += NO_LIBDW_DWARF_UNWIND=1
52 55
53# $(run) contains all available tests 56# $(run) contains all available tests
54run := make_pure 57run := make_pure
@@ -65,6 +68,7 @@ run += make_no_ui
65run += make_no_demangle 68run += make_no_demangle
66run += make_no_libelf 69run += make_no_libelf
67run += make_no_libunwind 70run += make_no_libunwind
71run += make_no_libdw_dwarf_unwind
68run += make_no_backtrace 72run += make_no_backtrace
69run += make_no_libnuma 73run += make_no_libnuma
70run += make_no_libaudit 74run += make_no_libaudit
@@ -73,6 +77,7 @@ run += make_help
73run += make_doc 77run += make_doc
74run += make_perf_o 78run += make_perf_o
75run += make_util_map_o 79run += make_util_map_o
80run += make_util_pmu_bison_o
76run += make_install 81run += make_install
77run += make_install_bin 82run += make_install_bin
78# FIXME 'install-*' commented out till they're fixed 83# FIXME 'install-*' commented out till they're fixed
@@ -113,8 +118,9 @@ test_make_doc_O := $(test_ok)
113 118
114test_make_python_perf_so := test -f $(PERF)/python/perf.so 119test_make_python_perf_so := test -f $(PERF)/python/perf.so
115 120
116test_make_perf_o := test -f $(PERF)/perf.o 121test_make_perf_o := test -f $(PERF)/perf.o
117test_make_util_map_o := test -f $(PERF)/util/map.o 122test_make_util_map_o := test -f $(PERF)/util/map.o
123test_make_util_pmu_bison_o := test -f $(PERF)/util/pmu-bison.o
118 124
119define test_dest_files 125define test_dest_files
120 for file in $(1); do \ 126 for file in $(1); do \
@@ -167,13 +173,10 @@ test_make_install_info_O := $(test_ok)
167test_make_install_pdf := $(test_ok) 173test_make_install_pdf := $(test_ok)
168test_make_install_pdf_O := $(test_ok) 174test_make_install_pdf_O := $(test_ok)
169 175
170# Kbuild tests only 176test_make_python_perf_so_O := test -f $$TMP_O/python/perf.so
171#test_make_python_perf_so_O := test -f $$TMP/tools/perf/python/perf.so 177test_make_perf_o_O := test -f $$TMP_O/perf.o
172#test_make_perf_o_O := test -f $$TMP/tools/perf/perf.o 178test_make_util_map_o_O := test -f $$TMP_O/util/map.o
173#test_make_util_map_o_O := test -f $$TMP/tools/perf/util/map.o 179test_make_util_pmu_bison_o_O := test -f $$TMP_O/util/pmu-bison.o
174
175test_make_perf_o_O := true
176test_make_util_map_o_O := true
177 180
178test_default = test -x $(PERF)/perf 181test_default = test -x $(PERF)/perf
179test = $(if $(test_$1),$(test_$1),$(test_default)) 182test = $(if $(test_$1),$(test_$1),$(test_default))
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 4045d086d9d9..64453d63b971 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -45,8 +45,8 @@ int dso__read_binary_type_filename(const struct dso *dso,
45 debuglink--; 45 debuglink--;
46 if (*debuglink == '/') 46 if (*debuglink == '/')
47 debuglink++; 47 debuglink++;
48 filename__read_debuglink(dso->long_name, debuglink, 48 ret = filename__read_debuglink(dso->long_name, debuglink,
49 size - (debuglink - filename)); 49 size - (debuglink - filename));
50 } 50 }
51 break; 51 break;
52 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 52 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 3e9f336740fa..8ac4a4fe2abd 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -506,6 +506,8 @@ int filename__read_debuglink(const char *filename, char *debuglink,
506 /* the start of this section is a zero-terminated string */ 506 /* the start of this section is a zero-terminated string */
507 strncpy(debuglink, data->d_buf, size); 507 strncpy(debuglink, data->d_buf, size);
508 508
509 err = 0;
510
509out_elf_end: 511out_elf_end:
510 elf_end(elf); 512 elf_end(elf);
511out_close: 513out_close:
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 46e2ede12c51..0ada68b3b096 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1251,6 +1251,46 @@ out_failure:
1251 return -1; 1251 return -1;
1252} 1252}
1253 1253
1254static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1255 enum dso_binary_type type)
1256{
1257 switch (type) {
1258 case DSO_BINARY_TYPE__JAVA_JIT:
1259 case DSO_BINARY_TYPE__DEBUGLINK:
1260 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
1261 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
1262 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
1263 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
1264 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
1265 return !kmod && dso->kernel == DSO_TYPE_USER;
1266
1267 case DSO_BINARY_TYPE__KALLSYMS:
1268 case DSO_BINARY_TYPE__VMLINUX:
1269 case DSO_BINARY_TYPE__KCORE:
1270 return dso->kernel == DSO_TYPE_KERNEL;
1271
1272 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
1273 case DSO_BINARY_TYPE__GUEST_VMLINUX:
1274 case DSO_BINARY_TYPE__GUEST_KCORE:
1275 return dso->kernel == DSO_TYPE_GUEST_KERNEL;
1276
1277 case DSO_BINARY_TYPE__GUEST_KMODULE:
1278 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1279 /*
1280 * kernel modules know their symtab type - it's set when
1281 * creating a module dso in machine__new_module().
1282 */
1283 return kmod && dso->symtab_type == type;
1284
1285 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
1286 return true;
1287
1288 case DSO_BINARY_TYPE__NOT_FOUND:
1289 default:
1290 return false;
1291 }
1292}
1293
1254int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 1294int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1255{ 1295{
1256 char *name; 1296 char *name;
@@ -1261,6 +1301,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1261 int ss_pos = 0; 1301 int ss_pos = 0;
1262 struct symsrc ss_[2]; 1302 struct symsrc ss_[2];
1263 struct symsrc *syms_ss = NULL, *runtime_ss = NULL; 1303 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
1304 bool kmod;
1264 1305
1265 dso__set_loaded(dso, map->type); 1306 dso__set_loaded(dso, map->type);
1266 1307
@@ -1301,7 +1342,11 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1301 if (!name) 1342 if (!name)
1302 return -1; 1343 return -1;
1303 1344
1304 /* Iterate over candidate debug images. 1345 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1346 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
1347
1348 /*
1349 * Iterate over candidate debug images.
1305 * Keep track of "interesting" ones (those which have a symtab, dynsym, 1350 * Keep track of "interesting" ones (those which have a symtab, dynsym,
1306 * and/or opd section) for processing. 1351 * and/or opd section) for processing.
1307 */ 1352 */
@@ -1311,6 +1356,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1311 1356
1312 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1357 enum dso_binary_type symtab_type = binary_type_symtab[i];
1313 1358
1359 if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type))
1360 continue;
1361
1314 if (dso__read_binary_type_filename(dso, symtab_type, 1362 if (dso__read_binary_type_filename(dso, symtab_type,
1315 root_dir, name, PATH_MAX)) 1363 root_dir, name, PATH_MAX))
1316 continue; 1364 continue;
@@ -1351,15 +1399,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1351 if (!runtime_ss && syms_ss) 1399 if (!runtime_ss && syms_ss)
1352 runtime_ss = syms_ss; 1400 runtime_ss = syms_ss;
1353 1401
1354 if (syms_ss) { 1402 if (syms_ss)
1355 int km; 1403 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod);
1356 1404 else
1357 km = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1358 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
1359 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, km);
1360 } else {
1361 ret = -1; 1405 ret = -1;
1362 }
1363 1406
1364 if (ret > 0) { 1407 if (ret > 0) {
1365 int nr_plt; 1408 int nr_plt;
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
new file mode 100644
index 000000000000..67db73ec3dab
--- /dev/null
+++ b/tools/perf/util/unwind-libdw.c
@@ -0,0 +1,210 @@
1#include <linux/compiler.h>
2#include <elfutils/libdw.h>
3#include <elfutils/libdwfl.h>
4#include <inttypes.h>
5#include <errno.h>
6#include "unwind.h"
7#include "unwind-libdw.h"
8#include "machine.h"
9#include "thread.h"
10#include "types.h"
11#include "event.h"
12#include "perf_regs.h"
13
14static char *debuginfo_path;
15
16static const Dwfl_Callbacks offline_callbacks = {
17 .find_debuginfo = dwfl_standard_find_debuginfo,
18 .debuginfo_path = &debuginfo_path,
19 .section_address = dwfl_offline_section_address,
20};
21
22static int __report_module(struct addr_location *al, u64 ip,
23 struct unwind_info *ui)
24{
25 Dwfl_Module *mod;
26 struct dso *dso = NULL;
27
28 thread__find_addr_location(ui->thread, ui->machine,
29 PERF_RECORD_MISC_USER,
30 MAP__FUNCTION, ip, al);
31
32 if (al->map)
33 dso = al->map->dso;
34
35 if (!dso)
36 return 0;
37
38 mod = dwfl_addrmodule(ui->dwfl, ip);
39 if (!mod)
40 mod = dwfl_report_elf(ui->dwfl, dso->short_name,
41 dso->long_name, -1, al->map->start,
42 false);
43
44 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
45}
46
47static int report_module(u64 ip, struct unwind_info *ui)
48{
49 struct addr_location al;
50
51 return __report_module(&al, ip, ui);
52}
53
54static int entry(u64 ip, struct unwind_info *ui)
55
56{
57 struct unwind_entry e;
58 struct addr_location al;
59
60 if (__report_module(&al, ip, ui))
61 return -1;
62
63 e.ip = ip;
64 e.map = al.map;
65 e.sym = al.sym;
66
67 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
68 al.sym ? al.sym->name : "''",
69 ip,
70 al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
71
72 return ui->cb(&e, ui->arg);
73}
74
75static pid_t next_thread(Dwfl *dwfl, void *arg, void **thread_argp)
76{
77 /* We want only single thread to be processed. */
78 if (*thread_argp != NULL)
79 return 0;
80
81 *thread_argp = arg;
82 return dwfl_pid(dwfl);
83}
84
85static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
86 Dwarf_Word *data)
87{
88 struct addr_location al;
89 ssize_t size;
90
91 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
92 MAP__FUNCTION, addr, &al);
93 if (!al.map) {
94 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
95 return -1;
96 }
97
98 if (!al.map->dso)
99 return -1;
100
101 size = dso__data_read_addr(al.map->dso, al.map, ui->machine,
102 addr, (u8 *) data, sizeof(*data));
103
104 return !(size == sizeof(*data));
105}
106
107static bool memory_read(Dwfl *dwfl __maybe_unused, Dwarf_Addr addr, Dwarf_Word *result,
108 void *arg)
109{
110 struct unwind_info *ui = arg;
111 struct stack_dump *stack = &ui->sample->user_stack;
112 u64 start, end;
113 int offset;
114 int ret;
115
116 ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
117 if (ret)
118 return false;
119
120 end = start + stack->size;
121
122 /* Check overflow. */
123 if (addr + sizeof(Dwarf_Word) < addr)
124 return false;
125
126 if (addr < start || addr + sizeof(Dwarf_Word) > end) {
127 ret = access_dso_mem(ui, addr, result);
128 if (ret) {
129 pr_debug("unwind: access_mem 0x%" PRIx64 " not inside range"
130 " 0x%" PRIx64 "-0x%" PRIx64 "\n",
131 addr, start, end);
132 return false;
133 }
134 return true;
135 }
136
137 offset = addr - start;
138 *result = *(Dwarf_Word *)&stack->data[offset];
139 pr_debug("unwind: access_mem addr 0x%" PRIx64 ", val %lx, offset %d\n",
140 addr, (unsigned long)*result, offset);
141 return true;
142}
143
144static const Dwfl_Thread_Callbacks callbacks = {
145 .next_thread = next_thread,
146 .memory_read = memory_read,
147 .set_initial_registers = libdw__arch_set_initial_registers,
148};
149
150static int
151frame_callback(Dwfl_Frame *state, void *arg)
152{
153 struct unwind_info *ui = arg;
154 Dwarf_Addr pc;
155
156 if (!dwfl_frame_pc(state, &pc, NULL)) {
157 pr_err("%s", dwfl_errmsg(-1));
158 return DWARF_CB_ABORT;
159 }
160
161 return entry(pc, ui) || !(--ui->max_stack) ?
162 DWARF_CB_ABORT : DWARF_CB_OK;
163}
164
165int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
166 struct machine *machine, struct thread *thread,
167 struct perf_sample *data,
168 int max_stack)
169{
170 struct unwind_info ui = {
171 .sample = data,
172 .thread = thread,
173 .machine = machine,
174 .cb = cb,
175 .arg = arg,
176 .max_stack = max_stack,
177 };
178 Dwarf_Word ip;
179 int err = -EINVAL;
180
181 if (!data->user_regs.regs)
182 return -EINVAL;
183
184 ui.dwfl = dwfl_begin(&offline_callbacks);
185 if (!ui.dwfl)
186 goto out;
187
188 err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
189 if (err)
190 goto out;
191
192 err = report_module(ip, &ui);
193 if (err)
194 goto out;
195
196 if (!dwfl_attach_state(ui.dwfl, EM_NONE, thread->tid, &callbacks, &ui))
197 goto out;
198
199 err = dwfl_getthread_frames(ui.dwfl, thread->tid, frame_callback, &ui);
200
201 if (err && !ui.max_stack)
202 err = 0;
203
204 out:
205 if (err)
206 pr_debug("unwind: failed with '%s'\n", dwfl_errmsg(-1));
207
208 dwfl_end(ui.dwfl);
209 return 0;
210}
diff --git a/tools/perf/util/unwind-libdw.h b/tools/perf/util/unwind-libdw.h
new file mode 100644
index 000000000000..417a1426f3ad
--- /dev/null
+++ b/tools/perf/util/unwind-libdw.h
@@ -0,0 +1,21 @@
1#ifndef __PERF_UNWIND_LIBDW_H
2#define __PERF_UNWIND_LIBDW_H
3
4#include <elfutils/libdwfl.h>
5#include "event.h"
6#include "thread.h"
7#include "unwind.h"
8
9bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg);
10
11struct unwind_info {
12 Dwfl *dwfl;
13 struct perf_sample *sample;
14 struct machine *machine;
15 struct thread *thread;
16 unwind_entry_cb_t cb;
17 void *arg;
18 int max_stack;
19};
20
21#endif /* __PERF_UNWIND_LIBDW_H */