diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-02-27 06:44:06 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-02-27 06:44:06 -0500 |
commit | e65312fe868da53077780de618e213a53dc90d00 (patch) | |
tree | 6240f24f99260832b8eef9ddaae73154e4f8a939 /tools | |
parent | 4a2345937c17722bd2979f662ae909846b4a052a (diff) | |
parent | 1029f9fedf87fa6f52096991588fa54ffd159584 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
* Add support for the new DWARF unwinder library in elfutils (Jiri Olsa)
* Fix build race in the generation of bison files (Jiri Olsa)
* Further streamline the feature detection display, trimming it a bit to
show just the libraries detected, using VF=1 gets a more verbose output,
showing the less interesting feature checks as well (Jiri Olsa).
* Check compatible symtab type before loading dso (Namhyung Kim)
* Check return value of filename__read_debuglink() (Stephane Eranian)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Makefile.perf | 24 | ||||
-rw-r--r-- | tools/perf/arch/x86/Makefile | 5 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/unwind-libdw.c | 51 | ||||
-rw-r--r-- | tools/perf/config/Makefile | 232 | ||||
-rw-r--r-- | tools/perf/config/feature-checks/Makefile | 6 | ||||
-rw-r--r-- | tools/perf/config/feature-checks/test-all.c | 5 | ||||
-rw-r--r-- | tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c | 13 | ||||
-rw-r--r-- | tools/perf/tests/make | 25 | ||||
-rw-r--r-- | tools/perf/util/dso.c | 4 | ||||
-rw-r--r-- | tools/perf/util/symbol-elf.c | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 61 | ||||
-rw-r--r-- | tools/perf/util/unwind-libdw.c | 210 | ||||
-rw-r--r-- | tools/perf/util/unwind-libdw.h | 21 |
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 | ||
59 | ifeq ($(srctree),) | 64 | ifeq ($(srctree),) |
60 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) | 65 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) |
@@ -404,7 +409,7 @@ endif | |||
404 | LIB_OBJS += $(OUTPUT)tests/code-reading.o | 409 | LIB_OBJS += $(OUTPUT)tests/code-reading.o |
405 | LIB_OBJS += $(OUTPUT)tests/sample-parsing.o | 410 | LIB_OBJS += $(OUTPUT)tests/sample-parsing.o |
406 | LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o | 411 | LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o |
407 | ifndef NO_LIBUNWIND | 412 | ifndef NO_DWARF_UNWIND |
408 | ifeq ($(ARCH),x86) | 413 | ifeq ($(ARCH),x86) |
409 | LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o | 414 | LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o |
410 | endif | 415 | endif |
@@ -476,6 +481,11 @@ ifndef NO_DWARF | |||
476 | endif # NO_DWARF | 481 | endif # NO_DWARF |
477 | endif # NO_LIBELF | 482 | endif # NO_LIBELF |
478 | 483 | ||
484 | ifndef NO_LIBDW_DWARF_UNWIND | ||
485 | LIB_OBJS += $(OUTPUT)util/unwind-libdw.o | ||
486 | LIB_H += util/unwind-libdw.h | ||
487 | endif | ||
488 | |||
479 | ifndef NO_LIBUNWIND | 489 | ifndef NO_LIBUNWIND |
480 | LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o | 490 | LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o |
481 | endif | 491 | endif |
@@ -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. |
713 | DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS) | 723 | DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS) |
714 | DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h | 724 | DIRECTORY_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 |
726 | DIRECTORY_DEPS += $(OUTPUT)util/parse-events-bison.c | ||
727 | DIRECTORY_DEPS += $(OUTPUT)util/pmu-bison.c | ||
728 | |||
729 | OUTPUT_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: | |||
891 | clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean | 907 | clean: $(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 | |||
4 | endif | 4 | endif |
5 | ifndef NO_LIBUNWIND | 5 | ifndef NO_LIBUNWIND |
6 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o | 6 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o |
7 | endif | ||
8 | ifndef NO_LIBDW_DWARF_UNWIND | ||
9 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o | ||
10 | endif | ||
11 | ifndef NO_DWARF_UNWIND | ||
7 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o | 12 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o |
8 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o | 13 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o |
9 | endif | 14 | endif |
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 | |||
5 | bool 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 |
60 | endif | 60 | endif |
61 | 61 | ||
62 | ifndef 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 | ||
72 | endif | ||
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 | |||
165 | LIB_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 | |||
179 | VF_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 | # | ||
168 | ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),) | ||
169 | test-all-failed := 1 | ||
170 | else | ||
171 | test-all-failed := 0 | ||
172 | endif | ||
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 | # |
183 | ifeq ($(feature-all), 0) | ||
184 | test-all-failed := 1 | ||
185 | endif | ||
186 | |||
187 | ifeq ($(test-all-failed),1) | ||
188 | $(info ) | ||
189 | $(info Auto-detecting system features:) | ||
190 | endif | ||
191 | |||
192 | ifeq ($(feature-all), 1) | 212 | ifeq ($(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))) |
200 | endif | 220 | endif |
201 | 221 | ||
202 | # | ||
203 | # Print the result of the feature test: | ||
204 | # | ||
205 | feature_print = $(eval $(feature_print_code)) $(info $(MSG)) | ||
206 | |||
207 | define 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 | ||
213 | endef | ||
214 | |||
215 | # | ||
216 | # Only print out our features if we rebuilt the testcases or if a test failed: | ||
217 | # | ||
218 | ifeq ($(test-all-failed), 1) | ||
219 | $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_print,$(feat))) | ||
220 | $(info ) | ||
221 | endif | ||
222 | |||
223 | ifeq ($(feature-stackprotector-all), 1) | 222 | ifeq ($(feature-stackprotector-all), 1) |
224 | CFLAGS += -fstack-protector-all | 223 | CFLAGS += -fstack-protector-all |
225 | endif | 224 | endif |
@@ -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 | ||
267 | else | 267 | else |
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 | ||
325 | ifndef NO_LIBUNWIND | 324 | ifndef 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 | ||
329 | endif | ||
330 | |||
331 | dwarf-post-unwind := 1 | ||
332 | dwarf-post-unwind-text := BUG | ||
333 | |||
334 | # setup DWARF post unwinder | ||
335 | ifdef 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) | 342 | else |
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 |
348 | endif | ||
349 | |||
350 | ifeq ($(dwarf-post-unwind),1) | ||
351 | CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT | ||
352 | else | ||
353 | NO_DWARF_UNWIND := 1 | ||
354 | endif | ||
355 | |||
356 | ifndef 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) | ||
346 | endif | 371 | endif |
347 | 372 | ||
348 | ifndef NO_LIBAUDIT | 373 | ifndef NO_LIBAUDIT |
@@ -602,3 +627,84 @@ ifdef DESTDIR | |||
602 | plugindir=$(libdir)/traceevent/plugins | 627 | plugindir=$(libdir)/traceevent/plugins |
603 | plugindir_SQ= $(subst ','\'',$(plugindir)) | 628 | plugindir_SQ= $(subst ','\'',$(plugindir)) |
604 | endif | 629 | endif |
630 | |||
631 | # | ||
632 | # Print the result of the feature test: | ||
633 | # | ||
634 | feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG)) | ||
635 | |||
636 | define 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 | ||
642 | endef | ||
643 | |||
644 | feature_print_var = $(eval $(feature_print_var_code)) $(info $(MSG)) | ||
645 | define feature_print_var_code | ||
646 | MSG = $(shell printf '...%30s: %s' $(1) $($(1))) | ||
647 | endef | ||
648 | |||
649 | feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG)) | ||
650 | define feature_print_text_code | ||
651 | MSG = $(shell printf '...%30s: %s' $(1) $(2)) | ||
652 | endef | ||
653 | |||
654 | PERF_FEATURES := $(foreach feat,$(LIB_FEATURE_TESTS),feature-$(feat)($(feature-$(feat)))) | ||
655 | PERF_FEATURES_FILE := $(shell touch $(OUTPUT)PERF-FEATURES; cat $(OUTPUT)PERF-FEATURES) | ||
656 | |||
657 | ifeq ($(dwarf-post-unwind),1) | ||
658 | PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text)) | ||
659 | endif | ||
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 | |||
668 | ifneq ("$(PERF_FEATURES)","$(PERF_FEATURES_FILE)") | ||
669 | $(shell echo "$(PERF_FEATURES)" > $(OUTPUT)PERF-FEATURES) | ||
670 | display_lib := 1 | ||
671 | endif | ||
672 | |||
673 | feature_check = $(eval $(feature_check_code)) | ||
674 | define feature_check_code | ||
675 | ifneq ($(feature-$(1)), 1) | ||
676 | display_lib := 1 | ||
677 | endif | ||
678 | endef | ||
679 | |||
680 | $(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat))) | ||
681 | |||
682 | ifeq ($(VF),1) | ||
683 | display_lib := 1 | ||
684 | display_vf := 1 | ||
685 | endif | ||
686 | |||
687 | ifeq ($(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 | ||
695 | endif | ||
696 | |||
697 | ifeq ($(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) | ||
706 | endif | ||
707 | |||
708 | ifeq ($(display_lib),1) | ||
709 | $(info ) | ||
710 | endif | ||
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 | ||
31 | CC := $(CROSS_COMPILE)gcc -MD | 32 | CC := $(CROSS_COMPILE)gcc -MD |
32 | PKG_CONFIG := $(CROSS_COMPILE)pkg-config | 33 | PKG_CONFIG := $(CROSS_COMPILE)pkg-config |
@@ -141,6 +142,9 @@ test-backtrace.bin: | |||
141 | test-timerfd.bin: | 142 | test-timerfd.bin: |
142 | $(BUILD) | 143 | $(BUILD) |
143 | 144 | ||
145 | test-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 | |||
92 | int main(int argc, char *argv[]) | 96 | int 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 | |||
4 | int 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 | |||
27 | make_no_demangle := NO_DEMANGLE=1 | 27 | make_no_demangle := NO_DEMANGLE=1 |
28 | make_no_libelf := NO_LIBELF=1 | 28 | make_no_libelf := NO_LIBELF=1 |
29 | make_no_libunwind := NO_LIBUNWIND=1 | 29 | make_no_libunwind := NO_LIBUNWIND=1 |
30 | make_no_libdw_dwarf_unwind := NO_LIBDW_DWARF_UNWIND=1 | ||
30 | make_no_backtrace := NO_BACKTRACE=1 | 31 | make_no_backtrace := NO_BACKTRACE=1 |
31 | make_no_libnuma := NO_LIBNUMA=1 | 32 | make_no_libnuma := NO_LIBNUMA=1 |
32 | make_no_libaudit := NO_LIBAUDIT=1 | 33 | make_no_libaudit := NO_LIBAUDIT=1 |
@@ -35,8 +36,9 @@ make_tags := tags | |||
35 | make_cscope := cscope | 36 | make_cscope := cscope |
36 | make_help := help | 37 | make_help := help |
37 | make_doc := doc | 38 | make_doc := doc |
38 | make_perf_o := perf.o | 39 | make_perf_o := perf.o |
39 | make_util_map_o := util/map.o | 40 | make_util_map_o := util/map.o |
41 | make_util_pmu_bison_o := util/pmu-bison.o | ||
40 | make_install := install | 42 | make_install := install |
41 | make_install_bin := install-bin | 43 | make_install_bin := install-bin |
42 | make_install_doc := install-doc | 44 | make_install_doc := install-doc |
@@ -49,6 +51,7 @@ make_install_pdf := install-pdf | |||
49 | make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 | 51 | make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 |
50 | make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 | 52 | make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 |
51 | make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 | 53 | make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 |
54 | make_minimal += NO_LIBDW_DWARF_UNWIND=1 | ||
52 | 55 | ||
53 | # $(run) contains all available tests | 56 | # $(run) contains all available tests |
54 | run := make_pure | 57 | run := make_pure |
@@ -65,6 +68,7 @@ run += make_no_ui | |||
65 | run += make_no_demangle | 68 | run += make_no_demangle |
66 | run += make_no_libelf | 69 | run += make_no_libelf |
67 | run += make_no_libunwind | 70 | run += make_no_libunwind |
71 | run += make_no_libdw_dwarf_unwind | ||
68 | run += make_no_backtrace | 72 | run += make_no_backtrace |
69 | run += make_no_libnuma | 73 | run += make_no_libnuma |
70 | run += make_no_libaudit | 74 | run += make_no_libaudit |
@@ -73,6 +77,7 @@ run += make_help | |||
73 | run += make_doc | 77 | run += make_doc |
74 | run += make_perf_o | 78 | run += make_perf_o |
75 | run += make_util_map_o | 79 | run += make_util_map_o |
80 | run += make_util_pmu_bison_o | ||
76 | run += make_install | 81 | run += make_install |
77 | run += make_install_bin | 82 | run += 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 | ||
114 | test_make_python_perf_so := test -f $(PERF)/python/perf.so | 119 | test_make_python_perf_so := test -f $(PERF)/python/perf.so |
115 | 120 | ||
116 | test_make_perf_o := test -f $(PERF)/perf.o | 121 | test_make_perf_o := test -f $(PERF)/perf.o |
117 | test_make_util_map_o := test -f $(PERF)/util/map.o | 122 | test_make_util_map_o := test -f $(PERF)/util/map.o |
123 | test_make_util_pmu_bison_o := test -f $(PERF)/util/pmu-bison.o | ||
118 | 124 | ||
119 | define test_dest_files | 125 | define 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) | |||
167 | test_make_install_pdf := $(test_ok) | 173 | test_make_install_pdf := $(test_ok) |
168 | test_make_install_pdf_O := $(test_ok) | 174 | test_make_install_pdf_O := $(test_ok) |
169 | 175 | ||
170 | # Kbuild tests only | 176 | test_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 | 177 | test_make_perf_o_O := test -f $$TMP_O/perf.o |
172 | #test_make_perf_o_O := test -f $$TMP/tools/perf/perf.o | 178 | test_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 | 179 | test_make_util_pmu_bison_o_O := test -f $$TMP_O/util/pmu-bison.o |
174 | |||
175 | test_make_perf_o_O := true | ||
176 | test_make_util_map_o_O := true | ||
177 | 180 | ||
178 | test_default = test -x $(PERF)/perf | 181 | test_default = test -x $(PERF)/perf |
179 | test = $(if $(test_$1),$(test_$1),$(test_default)) | 182 | test = $(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 | |||
509 | out_elf_end: | 511 | out_elf_end: |
510 | elf_end(elf); | 512 | elf_end(elf); |
511 | out_close: | 513 | out_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 | ||
1254 | static 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 | |||
1254 | int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | 1294 | int 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 | |||
14 | static char *debuginfo_path; | ||
15 | |||
16 | static 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 | |||
22 | static 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 | |||
47 | static 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 | |||
54 | static 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 | |||
75 | static 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 | |||
85 | static 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 | |||
107 | static 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 | |||
144 | static 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 | |||
150 | static int | ||
151 | frame_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 | |||
165 | int 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 | |||
9 | bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg); | ||
10 | |||
11 | struct 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 */ | ||