Commit d01de2389c0190f5959f0a1258a2e87d2fe4ca82
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/g…
…it/acme/linux into perf/urgent Pull perf/urgent fixes from Arnaldo Carvalho de Melo: - Fix segfault when using both the map symtab viewer and annotation in the TUI (Namhyung Kim). - uClibc build fixes (Alexey Brodkin, Vineet Gupta). - bitops/hweight were moved from tools/perf/ too tools/include, move some leftovers (Arnaldo Carvalho de Melo) - Fix dwarf unwind x86_64 build error (Namhyung Kim) - Fix __machine__findnew_thread() error path (Namhyung Kim) - Propagate error code when write(2) failed in 'perf probe' (Namhyung Kim) - Use dwfl_report_elf() instead of offline in powerpc bits to properly handle non prelinked DSOs (Sukadev Bhattiprolu). - Fix dwarf unwind using libunwind in 'perf test' (Wang Nan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Showing 24 changed files Side-by-side Diff
- tools/include/asm-generic/bitops.h
- tools/include/asm-generic/bitops/arch_hweight.h
- tools/include/asm-generic/bitops/const_hweight.h
- tools/include/asm-generic/bitops/hweight.h
- tools/include/linux/bitops.h
- tools/lib/api/fs/debugfs.c
- tools/lib/api/fs/fs.c
- tools/perf/MANIFEST
- tools/perf/Makefile.perf
- tools/perf/arch/powerpc/util/skip-callchain-idx.c
- tools/perf/bench/sched-pipe.c
- tools/perf/builtin-top.c
- tools/perf/config/Makefile
- tools/perf/config/Makefile.arch
- tools/perf/perf-sys.h
- tools/perf/tests/dwarf-unwind.c
- tools/perf/util/annotate.h
- tools/perf/util/cache.h
- tools/perf/util/hweight.c
- tools/perf/util/include/asm/hweight.h
- tools/perf/util/machine.c
- tools/perf/util/probe-event.c
- tools/perf/util/python-ext-sources
- tools/perf/util/unwind-libunwind.c
tools/include/asm-generic/bitops.h
tools/include/asm-generic/bitops/arch_hweight.h
1 | +#include "../../../../include/asm-generic/bitops/arch_hweight.h" |
tools/include/asm-generic/bitops/const_hweight.h
1 | +#include "../../../../include/asm-generic/bitops/const_hweight.h" |
tools/include/asm-generic/bitops/hweight.h
tools/include/linux/bitops.h
1 | 1 | #ifndef _TOOLS_LINUX_BITOPS_H_ |
2 | 2 | #define _TOOLS_LINUX_BITOPS_H_ |
3 | 3 | |
4 | +#include <asm/types.h> | |
4 | 5 | #include <linux/kernel.h> |
5 | 6 | #include <linux/compiler.h> |
6 | -#include <asm/hweight.h> | |
7 | 7 | |
8 | 8 | #ifndef __WORDSIZE |
9 | 9 | #define __WORDSIZE (__SIZEOF_LONG__ * 8) |
... | ... | @@ -18,6 +18,11 @@ |
18 | 18 | #define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64)) |
19 | 19 | #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) |
20 | 20 | #define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE) |
21 | + | |
22 | +extern unsigned int __sw_hweight8(unsigned int w); | |
23 | +extern unsigned int __sw_hweight16(unsigned int w); | |
24 | +extern unsigned int __sw_hweight32(unsigned int w); | |
25 | +extern unsigned long __sw_hweight64(__u64 w); | |
21 | 26 | |
22 | 27 | /* |
23 | 28 | * Include this here because some architectures need generic_ffs/fls in |
tools/lib/api/fs/debugfs.c
tools/lib/api/fs/fs.c
tools/perf/MANIFEST
... | ... | @@ -6,12 +6,15 @@ |
6 | 6 | tools/lib/symbol/kallsyms.h |
7 | 7 | tools/lib/util/find_next_bit.c |
8 | 8 | tools/include/asm/bug.h |
9 | +tools/include/asm-generic/bitops/arch_hweight.h | |
9 | 10 | tools/include/asm-generic/bitops/atomic.h |
11 | +tools/include/asm-generic/bitops/const_hweight.h | |
10 | 12 | tools/include/asm-generic/bitops/__ffs.h |
11 | 13 | tools/include/asm-generic/bitops/__fls.h |
12 | 14 | tools/include/asm-generic/bitops/find.h |
13 | 15 | tools/include/asm-generic/bitops/fls64.h |
14 | 16 | tools/include/asm-generic/bitops/fls.h |
17 | +tools/include/asm-generic/bitops/hweight.h | |
15 | 18 | tools/include/asm-generic/bitops.h |
16 | 19 | tools/include/linux/bitops.h |
17 | 20 | tools/include/linux/compiler.h |
... | ... | @@ -19,6 +22,8 @@ |
19 | 22 | tools/include/linux/hash.h |
20 | 23 | tools/include/linux/log2.h |
21 | 24 | tools/include/linux/types.h |
25 | +include/asm-generic/bitops/arch_hweight.h | |
26 | +include/asm-generic/bitops/const_hweight.h | |
22 | 27 | include/asm-generic/bitops/fls64.h |
23 | 28 | include/asm-generic/bitops/__fls.h |
24 | 29 | include/asm-generic/bitops/fls.h |
... | ... | @@ -29,6 +34,7 @@ |
29 | 34 | include/linux/hash.h |
30 | 35 | include/linux/stringify.h |
31 | 36 | lib/find_next_bit.c |
37 | +lib/hweight.c | |
32 | 38 | lib/rbtree.c |
33 | 39 | include/linux/swab.h |
34 | 40 | arch/*/include/asm/unistd*.h |
tools/perf/Makefile.perf
... | ... | @@ -232,12 +232,15 @@ |
232 | 232 | LIB_H += ../../include/linux/stringify.h |
233 | 233 | LIB_H += util/include/linux/bitmap.h |
234 | 234 | LIB_H += ../include/linux/bitops.h |
235 | +LIB_H += ../include/asm-generic/bitops/arch_hweight.h | |
235 | 236 | LIB_H += ../include/asm-generic/bitops/atomic.h |
237 | +LIB_H += ../include/asm-generic/bitops/const_hweight.h | |
236 | 238 | LIB_H += ../include/asm-generic/bitops/find.h |
237 | 239 | LIB_H += ../include/asm-generic/bitops/fls64.h |
238 | 240 | LIB_H += ../include/asm-generic/bitops/fls.h |
239 | 241 | LIB_H += ../include/asm-generic/bitops/__ffs.h |
240 | 242 | LIB_H += ../include/asm-generic/bitops/__fls.h |
243 | +LIB_H += ../include/asm-generic/bitops/hweight.h | |
241 | 244 | LIB_H += ../include/asm-generic/bitops.h |
242 | 245 | LIB_H += ../include/linux/compiler.h |
243 | 246 | LIB_H += ../include/linux/log2.h |
... | ... | @@ -255,7 +258,6 @@ |
255 | 258 | LIB_H += util/include/asm/asm-offsets.h |
256 | 259 | LIB_H += ../include/asm/bug.h |
257 | 260 | LIB_H += util/include/asm/byteorder.h |
258 | -LIB_H += util/include/asm/hweight.h | |
259 | 261 | LIB_H += util/include/asm/swab.h |
260 | 262 | LIB_H += util/include/asm/system.h |
261 | 263 | LIB_H += util/include/asm/uaccess.h |
262 | 264 | |
... | ... | @@ -462,10 +464,12 @@ |
462 | 464 | # Benchmark modules |
463 | 465 | BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o |
464 | 466 | BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o |
465 | -ifeq ($(RAW_ARCH),x86_64) | |
467 | +ifeq ($(ARCH), x86) | |
468 | +ifeq ($(IS_64_BIT), 1) | |
466 | 469 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o |
467 | 470 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o |
468 | 471 | endif |
472 | +endif | |
469 | 473 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o |
470 | 474 | BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o |
471 | 475 | BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o |
... | ... | @@ -741,6 +745,9 @@ |
741 | 745 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $< |
742 | 746 | |
743 | 747 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS |
748 | + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | |
749 | + | |
750 | +$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS | |
744 | 751 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< |
745 | 752 | |
746 | 753 | $(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS |
tools/perf/arch/powerpc/util/skip-callchain-idx.c
... | ... | @@ -103,7 +103,7 @@ |
103 | 103 | return NULL; |
104 | 104 | } |
105 | 105 | |
106 | - result = dwarf_cfi_addrframe(cfi, pc, &frame); | |
106 | + result = dwarf_cfi_addrframe(cfi, pc-bias, &frame); | |
107 | 107 | if (result) { |
108 | 108 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); |
109 | 109 | return NULL; |
... | ... | @@ -128,7 +128,7 @@ |
128 | 128 | return NULL; |
129 | 129 | } |
130 | 130 | |
131 | - result = dwarf_cfi_addrframe(cfi, pc, &frame); | |
131 | + result = dwarf_cfi_addrframe(cfi, pc-bias, &frame); | |
132 | 132 | if (result) { |
133 | 133 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); |
134 | 134 | return NULL; |
... | ... | @@ -145,7 +145,7 @@ |
145 | 145 | * yet used) |
146 | 146 | * -1 in case of errors |
147 | 147 | */ |
148 | -static int check_return_addr(struct dso *dso, Dwarf_Addr pc) | |
148 | +static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc) | |
149 | 149 | { |
150 | 150 | int rc = -1; |
151 | 151 | Dwfl *dwfl; |
... | ... | @@ -155,6 +155,7 @@ |
155 | 155 | Dwarf_Addr start = pc; |
156 | 156 | Dwarf_Addr end = pc; |
157 | 157 | bool signalp; |
158 | + const char *exec_file = dso->long_name; | |
158 | 159 | |
159 | 160 | dwfl = dso->dwfl; |
160 | 161 | |
... | ... | @@ -165,8 +166,10 @@ |
165 | 166 | return -1; |
166 | 167 | } |
167 | 168 | |
168 | - if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) { | |
169 | - pr_debug("dwfl_report_offline() failed %s\n", | |
169 | + mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1, | |
170 | + map_start, false); | |
171 | + if (!mod) { | |
172 | + pr_debug("dwfl_report_elf() failed %s\n", | |
170 | 173 | dwarf_errmsg(-1)); |
171 | 174 | /* |
172 | 175 | * We normally cache the DWARF debug info and never |
173 | 176 | |
... | ... | @@ -256,10 +259,10 @@ |
256 | 259 | return skip_slot; |
257 | 260 | } |
258 | 261 | |
259 | - rc = check_return_addr(dso, ip); | |
262 | + rc = check_return_addr(dso, al.map->start, ip); | |
260 | 263 | |
261 | - pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n", | |
262 | - dso->long_name, chain->nr, ip, rc); | |
264 | + pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n", | |
265 | + dso->long_name, al.sym->name, ip, rc); | |
263 | 266 | |
264 | 267 | if (rc == 0) { |
265 | 268 | /* |
tools/perf/bench/sched-pipe.c
... | ... | @@ -19,12 +19,12 @@ |
19 | 19 | #include <stdlib.h> |
20 | 20 | #include <signal.h> |
21 | 21 | #include <sys/wait.h> |
22 | -#include <linux/unistd.h> | |
23 | 22 | #include <string.h> |
24 | 23 | #include <errno.h> |
25 | 24 | #include <assert.h> |
26 | 25 | #include <sys/time.h> |
27 | 26 | #include <sys/types.h> |
27 | +#include <sys/syscall.h> | |
28 | 28 | |
29 | 29 | #include <pthread.h> |
30 | 30 |
tools/perf/builtin-top.c
tools/perf/config/Makefile
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | |
21 | 21 | # Additional ARCH settings for x86 |
22 | 22 | ifeq ($(ARCH),x86) |
23 | - ifeq (${IS_X86_64}, 1) | |
23 | + ifeq (${IS_64_BIT}, 1) | |
24 | 24 | CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT |
25 | 25 | ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S |
26 | 26 | LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 |
tools/perf/config/Makefile.arch
1 | 1 | |
2 | 2 | uname_M := $(shell uname -m 2>/dev/null || echo not) |
3 | 3 | |
4 | -ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | |
4 | +RAW_ARCH := $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | |
5 | 5 | -e s/arm.*/arm/ -e s/sa110/arm/ \ |
6 | 6 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ |
7 | 7 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ |
8 | 8 | |
9 | 9 | |
10 | 10 | |
11 | 11 | |
... | ... | @@ -9,24 +9,24 @@ |
9 | 9 | -e s/tile.*/tile/ ) |
10 | 10 | |
11 | 11 | # Additional ARCH settings for x86 |
12 | -ifeq ($(ARCH),i386) | |
13 | - override ARCH := x86 | |
12 | +ifeq ($(RAW_ARCH),i386) | |
13 | + ARCH ?= x86 | |
14 | 14 | endif |
15 | 15 | |
16 | -ifeq ($(ARCH),x86_64) | |
17 | - override ARCH := x86 | |
18 | - IS_X86_64 := 0 | |
19 | - ifeq (, $(findstring m32,$(CFLAGS))) | |
20 | - IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) | |
21 | - RAW_ARCH := x86_64 | |
16 | +ifeq ($(RAW_ARCH),x86_64) | |
17 | + ARCH ?= x86 | |
18 | + | |
19 | + ifneq (, $(findstring m32,$(CFLAGS))) | |
20 | + RAW_ARCH := x86_32 | |
22 | 21 | endif |
23 | 22 | endif |
24 | 23 | |
25 | -ifeq (${IS_X86_64}, 1) | |
24 | +ARCH ?= $(RAW_ARCH) | |
25 | + | |
26 | +LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) | |
27 | +ifeq ($(LP64), 1) | |
26 | 28 | IS_64_BIT := 1 |
27 | -else ifeq ($(ARCH),x86) | |
28 | - IS_64_BIT := 0 | |
29 | 29 | else |
30 | - IS_64_BIT := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) | |
30 | + IS_64_BIT := 0 | |
31 | 31 | endif |
tools/perf/perf-sys.h
tools/perf/tests/dwarf-unwind.c
... | ... | @@ -11,6 +11,9 @@ |
11 | 11 | #include "thread.h" |
12 | 12 | #include "callchain.h" |
13 | 13 | |
14 | +/* For bsearch. We try to unwind functions in shared object. */ | |
15 | +#include <stdlib.h> | |
16 | + | |
14 | 17 | static int mmap_handler(struct perf_tool *tool __maybe_unused, |
15 | 18 | union perf_event *event, |
16 | 19 | struct perf_sample *sample __maybe_unused, |
... | ... | @@ -28,7 +31,7 @@ |
28 | 31 | mmap_handler, machine, true); |
29 | 32 | } |
30 | 33 | |
31 | -#define MAX_STACK 6 | |
34 | +#define MAX_STACK 8 | |
32 | 35 | |
33 | 36 | static int unwind_entry(struct unwind_entry *entry, void *arg) |
34 | 37 | { |
... | ... | @@ -37,6 +40,8 @@ |
37 | 40 | static const char *funcs[MAX_STACK] = { |
38 | 41 | "test__arch_unwind_sample", |
39 | 42 | "unwind_thread", |
43 | + "compare", | |
44 | + "bsearch", | |
40 | 45 | "krava_3", |
41 | 46 | "krava_2", |
42 | 47 | "krava_1", |
43 | 48 | |
44 | 49 | |
... | ... | @@ -88,10 +93,37 @@ |
88 | 93 | return err; |
89 | 94 | } |
90 | 95 | |
96 | +static int global_unwind_retval = -INT_MAX; | |
97 | + | |
91 | 98 | __attribute__ ((noinline)) |
99 | +static int compare(void *p1, void *p2) | |
100 | +{ | |
101 | + /* Any possible value should be 'thread' */ | |
102 | + struct thread *thread = *(struct thread **)p1; | |
103 | + | |
104 | + if (global_unwind_retval == -INT_MAX) | |
105 | + global_unwind_retval = unwind_thread(thread); | |
106 | + | |
107 | + return p1 - p2; | |
108 | +} | |
109 | + | |
110 | +__attribute__ ((noinline)) | |
92 | 111 | static int krava_3(struct thread *thread) |
93 | 112 | { |
94 | - return unwind_thread(thread); | |
113 | + struct thread *array[2] = {thread, thread}; | |
114 | + void *fp = &bsearch; | |
115 | + /* | |
116 | + * make _bsearch a volatile function pointer to | |
117 | + * prevent potential optimization, which may expand | |
118 | + * bsearch and call compare directly from this function, | |
119 | + * instead of libc shared object. | |
120 | + */ | |
121 | + void *(*volatile _bsearch)(void *, void *, size_t, | |
122 | + size_t, int (*)(void *, void *)); | |
123 | + | |
124 | + _bsearch = fp; | |
125 | + _bsearch(array, &thread, 2, sizeof(struct thread **), compare); | |
126 | + return global_unwind_retval; | |
95 | 127 | } |
96 | 128 | |
97 | 129 | __attribute__ ((noinline)) |
tools/perf/util/annotate.h
... | ... | @@ -116,11 +116,6 @@ |
116 | 116 | struct annotated_source *src; |
117 | 117 | }; |
118 | 118 | |
119 | -struct sannotation { | |
120 | - struct annotation annotation; | |
121 | - struct symbol symbol; | |
122 | -}; | |
123 | - | |
124 | 119 | static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) |
125 | 120 | { |
126 | 121 | return (((void *)¬es->src->histograms) + |
... | ... | @@ -129,8 +124,7 @@ |
129 | 124 | |
130 | 125 | static inline struct annotation *symbol__annotation(struct symbol *sym) |
131 | 126 | { |
132 | - struct sannotation *a = container_of(sym, struct sannotation, symbol); | |
133 | - return &a->annotation; | |
127 | + return (void *)sym - symbol_conf.priv_size; | |
134 | 128 | } |
135 | 129 | |
136 | 130 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); |
tools/perf/util/cache.h
... | ... | @@ -71,8 +71,10 @@ |
71 | 71 | extern char *perf_pathdup(const char *fmt, ...) |
72 | 72 | __attribute__((format (printf, 1, 2))); |
73 | 73 | |
74 | +#ifndef __UCLIBC__ | |
74 | 75 | /* Matches the libc/libbsd function attribute so we declare this unconditionally: */ |
75 | 76 | extern size_t strlcpy(char *dest, const char *src, size_t size); |
77 | +#endif | |
76 | 78 | |
77 | 79 | #endif /* __PERF_CACHE_H */ |
tools/perf/util/hweight.c
1 | -#include <linux/bitops.h> | |
2 | - | |
3 | -/** | |
4 | - * hweightN - returns the hamming weight of a N-bit word | |
5 | - * @x: the word to weigh | |
6 | - * | |
7 | - * The Hamming Weight of a number is the total number of bits set in it. | |
8 | - */ | |
9 | - | |
10 | -unsigned int hweight32(unsigned int w) | |
11 | -{ | |
12 | - unsigned int res = w - ((w >> 1) & 0x55555555); | |
13 | - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); | |
14 | - res = (res + (res >> 4)) & 0x0F0F0F0F; | |
15 | - res = res + (res >> 8); | |
16 | - return (res + (res >> 16)) & 0x000000FF; | |
17 | -} | |
18 | - | |
19 | -unsigned long hweight64(__u64 w) | |
20 | -{ | |
21 | -#if BITS_PER_LONG == 32 | |
22 | - return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); | |
23 | -#elif BITS_PER_LONG == 64 | |
24 | - __u64 res = w - ((w >> 1) & 0x5555555555555555ul); | |
25 | - res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul); | |
26 | - res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful; | |
27 | - res = res + (res >> 8); | |
28 | - res = res + (res >> 16); | |
29 | - return (res + (res >> 32)) & 0x00000000000000FFul; | |
30 | -#endif | |
31 | -} |
tools/perf/util/include/asm/hweight.h
tools/perf/util/machine.c
... | ... | @@ -389,7 +389,6 @@ |
389 | 389 | if (th != NULL) { |
390 | 390 | rb_link_node(&th->rb_node, parent, p); |
391 | 391 | rb_insert_color(&th->rb_node, &machine->threads); |
392 | - machine->last_match = th; | |
393 | 392 | |
394 | 393 | /* |
395 | 394 | * We have to initialize map_groups separately |
396 | 395 | |
... | ... | @@ -400,9 +399,12 @@ |
400 | 399 | * leader and that would screwed the rb tree. |
401 | 400 | */ |
402 | 401 | if (thread__init_map_groups(th, machine)) { |
402 | + rb_erase(&th->rb_node, &machine->threads); | |
403 | 403 | thread__delete(th); |
404 | 404 | return NULL; |
405 | 405 | } |
406 | + | |
407 | + machine->last_match = th; | |
406 | 408 | } |
407 | 409 | |
408 | 410 | return th; |
tools/perf/util/probe-event.c
... | ... | @@ -2052,9 +2052,11 @@ |
2052 | 2052 | pr_debug("Writing event: %s\n", buf); |
2053 | 2053 | if (!probe_event_dry_run) { |
2054 | 2054 | ret = write(fd, buf, strlen(buf)); |
2055 | - if (ret <= 0) | |
2055 | + if (ret <= 0) { | |
2056 | + ret = -errno; | |
2056 | 2057 | pr_warning("Failed to write event: %s\n", |
2057 | 2058 | strerror_r(errno, sbuf, sizeof(sbuf))); |
2059 | + } | |
2058 | 2060 | } |
2059 | 2061 | free(buf); |
2060 | 2062 | return ret; |
tools/perf/util/python-ext-sources
tools/perf/util/unwind-libunwind.c
... | ... | @@ -185,6 +185,28 @@ |
185 | 185 | return offset; |
186 | 186 | } |
187 | 187 | |
188 | +#ifndef NO_LIBUNWIND_DEBUG_FRAME | |
189 | +static int elf_is_exec(int fd, const char *name) | |
190 | +{ | |
191 | + Elf *elf; | |
192 | + GElf_Ehdr ehdr; | |
193 | + int retval = 0; | |
194 | + | |
195 | + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | |
196 | + if (elf == NULL) | |
197 | + return 0; | |
198 | + if (gelf_getehdr(elf, &ehdr) == NULL) | |
199 | + goto out; | |
200 | + | |
201 | + retval = (ehdr.e_type == ET_EXEC); | |
202 | + | |
203 | +out: | |
204 | + elf_end(elf); | |
205 | + pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval); | |
206 | + return retval; | |
207 | +} | |
208 | +#endif | |
209 | + | |
188 | 210 | struct table_entry { |
189 | 211 | u32 start_ip_offset; |
190 | 212 | u32 fde_offset; |
191 | 213 | |
... | ... | @@ -322,8 +344,12 @@ |
322 | 344 | #ifndef NO_LIBUNWIND_DEBUG_FRAME |
323 | 345 | /* Check the .debug_frame section for unwinding info */ |
324 | 346 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { |
347 | + int fd = dso__data_fd(map->dso, ui->machine); | |
348 | + int is_exec = elf_is_exec(fd, map->dso->name); | |
349 | + unw_word_t base = is_exec ? 0 : map->start; | |
350 | + | |
325 | 351 | memset(&di, 0, sizeof(di)); |
326 | - if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, | |
352 | + if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, | |
327 | 353 | map->start, map->end)) |
328 | 354 | return dwarf_search_unwind_table(as, ip, &di, pi, |
329 | 355 | need_unwind_info, arg); |