diff options
Diffstat (limited to 'tools')
51 files changed, 447 insertions, 183 deletions
diff --git a/tools/include/asm-generic/bitops.h b/tools/include/asm-generic/bitops.h index 6eedba1f7732..653d1bad77de 100644 --- a/tools/include/asm-generic/bitops.h +++ b/tools/include/asm-generic/bitops.h | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #error only <linux/bitops.h> can be included directly | 22 | #error only <linux/bitops.h> can be included directly |
| 23 | #endif | 23 | #endif |
| 24 | 24 | ||
| 25 | #include <asm-generic/bitops/hweight.h> | ||
| 26 | |||
| 25 | #include <asm-generic/bitops/atomic.h> | 27 | #include <asm-generic/bitops/atomic.h> |
| 26 | 28 | ||
| 27 | #endif /* __TOOLS_ASM_GENERIC_BITOPS_H */ | 29 | #endif /* __TOOLS_ASM_GENERIC_BITOPS_H */ |
diff --git a/tools/include/asm-generic/bitops/arch_hweight.h b/tools/include/asm-generic/bitops/arch_hweight.h new file mode 100644 index 000000000000..318bb2b202b0 --- /dev/null +++ b/tools/include/asm-generic/bitops/arch_hweight.h | |||
| @@ -0,0 +1 @@ | |||
| #include "../../../../include/asm-generic/bitops/arch_hweight.h" | |||
diff --git a/tools/include/asm-generic/bitops/const_hweight.h b/tools/include/asm-generic/bitops/const_hweight.h new file mode 100644 index 000000000000..0afd644aff83 --- /dev/null +++ b/tools/include/asm-generic/bitops/const_hweight.h | |||
| @@ -0,0 +1 @@ | |||
| #include "../../../../include/asm-generic/bitops/const_hweight.h" | |||
diff --git a/tools/include/asm-generic/bitops/hweight.h b/tools/include/asm-generic/bitops/hweight.h new file mode 100644 index 000000000000..290120c01a8e --- /dev/null +++ b/tools/include/asm-generic/bitops/hweight.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | #ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ | ||
| 2 | #define _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ | ||
| 3 | |||
| 4 | #include <asm-generic/bitops/arch_hweight.h> | ||
| 5 | #include <asm-generic/bitops/const_hweight.h> | ||
| 6 | |||
| 7 | #endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ */ | ||
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h index 26005a15e7e2..5ad9ee1dd7f6 100644 --- a/tools/include/linux/bitops.h +++ b/tools/include/linux/bitops.h | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | #ifndef _TOOLS_LINUX_BITOPS_H_ | 1 | #ifndef _TOOLS_LINUX_BITOPS_H_ |
| 2 | #define _TOOLS_LINUX_BITOPS_H_ | 2 | #define _TOOLS_LINUX_BITOPS_H_ |
| 3 | 3 | ||
| 4 | #include <asm/types.h> | ||
| 4 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
| 5 | #include <linux/compiler.h> | 6 | #include <linux/compiler.h> |
| 6 | #include <asm/hweight.h> | ||
| 7 | 7 | ||
| 8 | #ifndef __WORDSIZE | 8 | #ifndef __WORDSIZE |
| 9 | #define __WORDSIZE (__SIZEOF_LONG__ * 8) | 9 | #define __WORDSIZE (__SIZEOF_LONG__ * 8) |
| @@ -19,6 +19,11 @@ | |||
| 19 | #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) | 19 | #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) |
| 20 | #define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE) | 20 | #define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE) |
| 21 | 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); | ||
| 26 | |||
| 22 | /* | 27 | /* |
| 23 | * Include this here because some architectures need generic_ffs/fls in | 28 | * Include this here because some architectures need generic_ffs/fls in |
| 24 | * scope | 29 | * scope |
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c index a74fba6d7743..86ea2d7b8845 100644 --- a/tools/lib/api/fs/debugfs.c +++ b/tools/lib/api/fs/debugfs.c | |||
| @@ -67,7 +67,7 @@ int debugfs_valid_mountpoint(const char *debugfs) | |||
| 67 | 67 | ||
| 68 | if (statfs(debugfs, &st_fs) < 0) | 68 | if (statfs(debugfs, &st_fs) < 0) |
| 69 | return -ENOENT; | 69 | return -ENOENT; |
| 70 | else if (st_fs.f_type != (long) DEBUGFS_MAGIC) | 70 | else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC) |
| 71 | return -ENOENT; | 71 | return -ENOENT; |
| 72 | 72 | ||
| 73 | return 0; | 73 | return 0; |
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c index 65d9be3f9887..128ef6332a6b 100644 --- a/tools/lib/api/fs/fs.c +++ b/tools/lib/api/fs/fs.c | |||
| @@ -79,7 +79,7 @@ static int fs__valid_mount(const char *fs, long magic) | |||
| 79 | 79 | ||
| 80 | if (statfs(fs, &st_fs) < 0) | 80 | if (statfs(fs, &st_fs) < 0) |
| 81 | return -ENOENT; | 81 | return -ENOENT; |
| 82 | else if (st_fs.f_type != magic) | 82 | else if ((long)st_fs.f_type != magic) |
| 83 | return -ENOENT; | 83 | return -ENOENT; |
| 84 | 84 | ||
| 85 | return 0; | 85 | return 0; |
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c index 6f803609e498..0b0112c80f22 100644 --- a/tools/lib/lockdep/preload.c +++ b/tools/lib/lockdep/preload.c | |||
| @@ -317,7 +317,7 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex) | |||
| 317 | * | 317 | * |
| 318 | * TODO: Hook into free() and add that check there as well. | 318 | * TODO: Hook into free() and add that check there as well. |
| 319 | */ | 319 | */ |
| 320 | debug_check_no_locks_freed(mutex, mutex + sizeof(*mutex)); | 320 | debug_check_no_locks_freed(mutex, sizeof(*mutex)); |
| 321 | __del_lock(__get_lock(mutex)); | 321 | __del_lock(__get_lock(mutex)); |
| 322 | return ll_pthread_mutex_destroy(mutex); | 322 | return ll_pthread_mutex_destroy(mutex); |
| 323 | } | 323 | } |
| @@ -341,7 +341,7 @@ int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) | |||
| 341 | { | 341 | { |
| 342 | try_init_preload(); | 342 | try_init_preload(); |
| 343 | 343 | ||
| 344 | debug_check_no_locks_freed(rwlock, rwlock + sizeof(*rwlock)); | 344 | debug_check_no_locks_freed(rwlock, sizeof(*rwlock)); |
| 345 | __del_lock(__get_lock(rwlock)); | 345 | __del_lock(__get_lock(rwlock)); |
| 346 | return ll_pthread_rwlock_destroy(rwlock); | 346 | return ll_pthread_rwlock_destroy(rwlock); |
| 347 | } | 347 | } |
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index 83e2887f91a3..fbbfdc39271d 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
| @@ -6,12 +6,15 @@ tools/lib/symbol/kallsyms.c | |||
| 6 | tools/lib/symbol/kallsyms.h | 6 | tools/lib/symbol/kallsyms.h |
| 7 | tools/lib/util/find_next_bit.c | 7 | tools/lib/util/find_next_bit.c |
| 8 | tools/include/asm/bug.h | 8 | tools/include/asm/bug.h |
| 9 | tools/include/asm-generic/bitops/arch_hweight.h | ||
| 9 | tools/include/asm-generic/bitops/atomic.h | 10 | tools/include/asm-generic/bitops/atomic.h |
| 11 | tools/include/asm-generic/bitops/const_hweight.h | ||
| 10 | tools/include/asm-generic/bitops/__ffs.h | 12 | tools/include/asm-generic/bitops/__ffs.h |
| 11 | tools/include/asm-generic/bitops/__fls.h | 13 | tools/include/asm-generic/bitops/__fls.h |
| 12 | tools/include/asm-generic/bitops/find.h | 14 | tools/include/asm-generic/bitops/find.h |
| 13 | tools/include/asm-generic/bitops/fls64.h | 15 | tools/include/asm-generic/bitops/fls64.h |
| 14 | tools/include/asm-generic/bitops/fls.h | 16 | tools/include/asm-generic/bitops/fls.h |
| 17 | tools/include/asm-generic/bitops/hweight.h | ||
| 15 | tools/include/asm-generic/bitops.h | 18 | tools/include/asm-generic/bitops.h |
| 16 | tools/include/linux/bitops.h | 19 | tools/include/linux/bitops.h |
| 17 | tools/include/linux/compiler.h | 20 | tools/include/linux/compiler.h |
| @@ -19,6 +22,8 @@ tools/include/linux/export.h | |||
| 19 | tools/include/linux/hash.h | 22 | tools/include/linux/hash.h |
| 20 | tools/include/linux/log2.h | 23 | tools/include/linux/log2.h |
| 21 | tools/include/linux/types.h | 24 | tools/include/linux/types.h |
| 25 | include/asm-generic/bitops/arch_hweight.h | ||
| 26 | include/asm-generic/bitops/const_hweight.h | ||
| 22 | include/asm-generic/bitops/fls64.h | 27 | include/asm-generic/bitops/fls64.h |
| 23 | include/asm-generic/bitops/__fls.h | 28 | include/asm-generic/bitops/__fls.h |
| 24 | include/asm-generic/bitops/fls.h | 29 | include/asm-generic/bitops/fls.h |
| @@ -29,6 +34,7 @@ include/linux/list.h | |||
| 29 | include/linux/hash.h | 34 | include/linux/hash.h |
| 30 | include/linux/stringify.h | 35 | include/linux/stringify.h |
| 31 | lib/find_next_bit.c | 36 | lib/find_next_bit.c |
| 37 | lib/hweight.c | ||
| 32 | lib/rbtree.c | 38 | lib/rbtree.c |
| 33 | include/linux/swab.h | 39 | include/linux/swab.h |
| 34 | arch/*/include/asm/unistd*.h | 40 | arch/*/include/asm/unistd*.h |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 67a03a825b3c..aa6a50447c32 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
| @@ -232,12 +232,15 @@ LIB_H += ../include/linux/hash.h | |||
| 232 | LIB_H += ../../include/linux/stringify.h | 232 | LIB_H += ../../include/linux/stringify.h |
| 233 | LIB_H += util/include/linux/bitmap.h | 233 | LIB_H += util/include/linux/bitmap.h |
| 234 | LIB_H += ../include/linux/bitops.h | 234 | LIB_H += ../include/linux/bitops.h |
| 235 | LIB_H += ../include/asm-generic/bitops/arch_hweight.h | ||
| 235 | LIB_H += ../include/asm-generic/bitops/atomic.h | 236 | LIB_H += ../include/asm-generic/bitops/atomic.h |
| 237 | LIB_H += ../include/asm-generic/bitops/const_hweight.h | ||
| 236 | LIB_H += ../include/asm-generic/bitops/find.h | 238 | LIB_H += ../include/asm-generic/bitops/find.h |
| 237 | LIB_H += ../include/asm-generic/bitops/fls64.h | 239 | LIB_H += ../include/asm-generic/bitops/fls64.h |
| 238 | LIB_H += ../include/asm-generic/bitops/fls.h | 240 | LIB_H += ../include/asm-generic/bitops/fls.h |
| 239 | LIB_H += ../include/asm-generic/bitops/__ffs.h | 241 | LIB_H += ../include/asm-generic/bitops/__ffs.h |
| 240 | LIB_H += ../include/asm-generic/bitops/__fls.h | 242 | LIB_H += ../include/asm-generic/bitops/__fls.h |
| 243 | LIB_H += ../include/asm-generic/bitops/hweight.h | ||
| 241 | LIB_H += ../include/asm-generic/bitops.h | 244 | LIB_H += ../include/asm-generic/bitops.h |
| 242 | LIB_H += ../include/linux/compiler.h | 245 | LIB_H += ../include/linux/compiler.h |
| 243 | LIB_H += ../include/linux/log2.h | 246 | LIB_H += ../include/linux/log2.h |
| @@ -255,7 +258,6 @@ LIB_H += util/include/linux/linkage.h | |||
| 255 | LIB_H += util/include/asm/asm-offsets.h | 258 | LIB_H += util/include/asm/asm-offsets.h |
| 256 | LIB_H += ../include/asm/bug.h | 259 | LIB_H += ../include/asm/bug.h |
| 257 | LIB_H += util/include/asm/byteorder.h | 260 | LIB_H += util/include/asm/byteorder.h |
| 258 | LIB_H += util/include/asm/hweight.h | ||
| 259 | LIB_H += util/include/asm/swab.h | 261 | LIB_H += util/include/asm/swab.h |
| 260 | LIB_H += util/include/asm/system.h | 262 | LIB_H += util/include/asm/system.h |
| 261 | LIB_H += util/include/asm/uaccess.h | 263 | LIB_H += util/include/asm/uaccess.h |
| @@ -462,10 +464,12 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o | |||
| 462 | # Benchmark modules | 464 | # Benchmark modules |
| 463 | BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o | 465 | BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o |
| 464 | BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o | 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 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o | 469 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o |
| 467 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o | 470 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o |
| 468 | endif | 471 | endif |
| 472 | endif | ||
| 469 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o | 473 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o |
| 470 | BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o | 474 | BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o |
| 471 | BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o | 475 | BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o |
| @@ -743,6 +747,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS | |||
| 743 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS | 747 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS |
| 744 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | 748 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< |
| 745 | 749 | ||
| 750 | $(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS | ||
| 751 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | ||
| 752 | |||
| 746 | $(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS | 753 | $(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS |
| 747 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | 754 | $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< |
| 748 | 755 | ||
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c index 3bb50eac5542..0c370f81e002 100644 --- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c +++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c | |||
| @@ -103,7 +103,7 @@ static Dwarf_Frame *get_eh_frame(Dwfl_Module *mod, Dwarf_Addr pc) | |||
| 103 | return NULL; | 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 | if (result) { | 107 | if (result) { |
| 108 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); | 108 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); |
| 109 | return NULL; | 109 | return NULL; |
| @@ -128,7 +128,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc) | |||
| 128 | return NULL; | 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 | if (result) { | 132 | if (result) { |
| 133 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); | 133 | pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); |
| 134 | return NULL; | 134 | return NULL; |
| @@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc) | |||
| 145 | * yet used) | 145 | * yet used) |
| 146 | * -1 in case of errors | 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 | int rc = -1; | 150 | int rc = -1; |
| 151 | Dwfl *dwfl; | 151 | Dwfl *dwfl; |
| @@ -155,6 +155,7 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc) | |||
| 155 | Dwarf_Addr start = pc; | 155 | Dwarf_Addr start = pc; |
| 156 | Dwarf_Addr end = pc; | 156 | Dwarf_Addr end = pc; |
| 157 | bool signalp; | 157 | bool signalp; |
| 158 | const char *exec_file = dso->long_name; | ||
| 158 | 159 | ||
| 159 | dwfl = dso->dwfl; | 160 | dwfl = dso->dwfl; |
| 160 | 161 | ||
| @@ -165,8 +166,10 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc) | |||
| 165 | return -1; | 166 | return -1; |
| 166 | } | 167 | } |
| 167 | 168 | ||
| 168 | if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) { | 169 | mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1, |
| 169 | pr_debug("dwfl_report_offline() failed %s\n", | 170 | map_start, false); |
| 171 | if (!mod) { | ||
| 172 | pr_debug("dwfl_report_elf() failed %s\n", | ||
| 170 | dwarf_errmsg(-1)); | 173 | dwarf_errmsg(-1)); |
| 171 | /* | 174 | /* |
| 172 | * We normally cache the DWARF debug info and never | 175 | * We normally cache the DWARF debug info and never |
| @@ -256,10 +259,10 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain) | |||
| 256 | return skip_slot; | 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", | 264 | pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n", |
| 262 | dso->long_name, chain->nr, ip, rc); | 265 | dso->long_name, al.sym->name, ip, rc); |
| 263 | 266 | ||
| 264 | if (rc == 0) { | 267 | if (rc == 0) { |
| 265 | /* | 268 | /* |
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index 07a8d7646a15..005cc283790c 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c | |||
| @@ -19,12 +19,12 @@ | |||
| 19 | #include <stdlib.h> | 19 | #include <stdlib.h> |
| 20 | #include <signal.h> | 20 | #include <signal.h> |
| 21 | #include <sys/wait.h> | 21 | #include <sys/wait.h> |
| 22 | #include <linux/unistd.h> | ||
| 23 | #include <string.h> | 22 | #include <string.h> |
| 24 | #include <errno.h> | 23 | #include <errno.h> |
| 25 | #include <assert.h> | 24 | #include <assert.h> |
| 26 | #include <sys/time.h> | 25 | #include <sys/time.h> |
| 27 | #include <sys/types.h> | 26 | #include <sys/types.h> |
| 27 | #include <sys/syscall.h> | ||
| 28 | 28 | ||
| 29 | #include <pthread.h> | 29 | #include <pthread.h> |
| 30 | 30 | ||
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index e7417fe97a97..747f86103599 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
| @@ -232,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
| 232 | if (nr_samples > 0) { | 232 | if (nr_samples > 0) { |
| 233 | total_nr_samples += nr_samples; | 233 | total_nr_samples += nr_samples; |
| 234 | hists__collapse_resort(hists, NULL); | 234 | hists__collapse_resort(hists, NULL); |
| 235 | hists__output_resort(hists); | 235 | hists__output_resort(hists, NULL); |
| 236 | 236 | ||
| 237 | if (symbol_conf.event_group && | 237 | if (symbol_conf.event_group && |
| 238 | !perf_evsel__is_group_leader(pos)) | 238 | !perf_evsel__is_group_leader(pos)) |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 1ce425d101a9..1fd96c13f199 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
| @@ -545,6 +545,42 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, | |||
| 545 | return __hist_entry__cmp_compute(p_left, p_right, c); | 545 | return __hist_entry__cmp_compute(p_left, p_right, c); |
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | static int64_t | ||
| 549 | hist_entry__cmp_nop(struct hist_entry *left __maybe_unused, | ||
| 550 | struct hist_entry *right __maybe_unused) | ||
| 551 | { | ||
| 552 | return 0; | ||
| 553 | } | ||
| 554 | |||
| 555 | static int64_t | ||
| 556 | hist_entry__cmp_baseline(struct hist_entry *left, struct hist_entry *right) | ||
| 557 | { | ||
| 558 | if (sort_compute) | ||
| 559 | return 0; | ||
| 560 | |||
| 561 | if (left->stat.period == right->stat.period) | ||
| 562 | return 0; | ||
| 563 | return left->stat.period > right->stat.period ? 1 : -1; | ||
| 564 | } | ||
| 565 | |||
| 566 | static int64_t | ||
| 567 | hist_entry__cmp_delta(struct hist_entry *left, struct hist_entry *right) | ||
| 568 | { | ||
| 569 | return hist_entry__cmp_compute(right, left, COMPUTE_DELTA); | ||
| 570 | } | ||
| 571 | |||
| 572 | static int64_t | ||
| 573 | hist_entry__cmp_ratio(struct hist_entry *left, struct hist_entry *right) | ||
| 574 | { | ||
| 575 | return hist_entry__cmp_compute(right, left, COMPUTE_RATIO); | ||
| 576 | } | ||
| 577 | |||
| 578 | static int64_t | ||
| 579 | hist_entry__cmp_wdiff(struct hist_entry *left, struct hist_entry *right) | ||
| 580 | { | ||
| 581 | return hist_entry__cmp_compute(right, left, COMPUTE_WEIGHTED_DIFF); | ||
| 582 | } | ||
| 583 | |||
| 548 | static void insert_hist_entry_by_compute(struct rb_root *root, | 584 | static void insert_hist_entry_by_compute(struct rb_root *root, |
| 549 | struct hist_entry *he, | 585 | struct hist_entry *he, |
| 550 | int c) | 586 | int c) |
| @@ -605,7 +641,7 @@ static void hists__process(struct hists *hists) | |||
| 605 | hists__precompute(hists); | 641 | hists__precompute(hists); |
| 606 | hists__compute_resort(hists); | 642 | hists__compute_resort(hists); |
| 607 | } else { | 643 | } else { |
| 608 | hists__output_resort(hists); | 644 | hists__output_resort(hists, NULL); |
| 609 | } | 645 | } |
| 610 | 646 | ||
| 611 | hists__fprintf(hists, true, 0, 0, 0, stdout); | 647 | hists__fprintf(hists, true, 0, 0, 0, stdout); |
| @@ -1038,27 +1074,35 @@ static void data__hpp_register(struct data__file *d, int idx) | |||
| 1038 | fmt->header = hpp__header; | 1074 | fmt->header = hpp__header; |
| 1039 | fmt->width = hpp__width; | 1075 | fmt->width = hpp__width; |
| 1040 | fmt->entry = hpp__entry_global; | 1076 | fmt->entry = hpp__entry_global; |
| 1077 | fmt->cmp = hist_entry__cmp_nop; | ||
| 1078 | fmt->collapse = hist_entry__cmp_nop; | ||
| 1041 | 1079 | ||
| 1042 | /* TODO more colors */ | 1080 | /* TODO more colors */ |
| 1043 | switch (idx) { | 1081 | switch (idx) { |
| 1044 | case PERF_HPP_DIFF__BASELINE: | 1082 | case PERF_HPP_DIFF__BASELINE: |
| 1045 | fmt->color = hpp__color_baseline; | 1083 | fmt->color = hpp__color_baseline; |
| 1084 | fmt->sort = hist_entry__cmp_baseline; | ||
| 1046 | break; | 1085 | break; |
| 1047 | case PERF_HPP_DIFF__DELTA: | 1086 | case PERF_HPP_DIFF__DELTA: |
| 1048 | fmt->color = hpp__color_delta; | 1087 | fmt->color = hpp__color_delta; |
| 1088 | fmt->sort = hist_entry__cmp_delta; | ||
| 1049 | break; | 1089 | break; |
| 1050 | case PERF_HPP_DIFF__RATIO: | 1090 | case PERF_HPP_DIFF__RATIO: |
| 1051 | fmt->color = hpp__color_ratio; | 1091 | fmt->color = hpp__color_ratio; |
| 1092 | fmt->sort = hist_entry__cmp_ratio; | ||
| 1052 | break; | 1093 | break; |
| 1053 | case PERF_HPP_DIFF__WEIGHTED_DIFF: | 1094 | case PERF_HPP_DIFF__WEIGHTED_DIFF: |
| 1054 | fmt->color = hpp__color_wdiff; | 1095 | fmt->color = hpp__color_wdiff; |
| 1096 | fmt->sort = hist_entry__cmp_wdiff; | ||
| 1055 | break; | 1097 | break; |
| 1056 | default: | 1098 | default: |
| 1099 | fmt->sort = hist_entry__cmp_nop; | ||
| 1057 | break; | 1100 | break; |
| 1058 | } | 1101 | } |
| 1059 | 1102 | ||
| 1060 | init_header(d, dfmt); | 1103 | init_header(d, dfmt); |
| 1061 | perf_hpp__column_register(fmt); | 1104 | perf_hpp__column_register(fmt); |
| 1105 | perf_hpp__register_sort_field(fmt); | ||
| 1062 | } | 1106 | } |
| 1063 | 1107 | ||
| 1064 | static void ui_init(void) | 1108 | static void ui_init(void) |
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 011195e38f21..198f3c3aff95 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c | |||
| @@ -19,7 +19,9 @@ | |||
| 19 | int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | 19 | int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) |
| 20 | { | 20 | { |
| 21 | int i; | 21 | int i; |
| 22 | const struct option list_options[] = { | 22 | bool raw_dump = false; |
| 23 | struct option list_options[] = { | ||
| 24 | OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"), | ||
| 23 | OPT_END() | 25 | OPT_END() |
| 24 | }; | 26 | }; |
| 25 | const char * const list_usage[] = { | 27 | const char * const list_usage[] = { |
| @@ -27,11 +29,18 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 27 | NULL | 29 | NULL |
| 28 | }; | 30 | }; |
| 29 | 31 | ||
| 32 | set_option_flag(list_options, 0, "raw-dump", PARSE_OPT_HIDDEN); | ||
| 33 | |||
| 30 | argc = parse_options(argc, argv, list_options, list_usage, | 34 | argc = parse_options(argc, argv, list_options, list_usage, |
| 31 | PARSE_OPT_STOP_AT_NON_OPTION); | 35 | PARSE_OPT_STOP_AT_NON_OPTION); |
| 32 | 36 | ||
| 33 | setup_pager(); | 37 | setup_pager(); |
| 34 | 38 | ||
| 39 | if (raw_dump) { | ||
| 40 | print_events(NULL, true); | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 35 | if (argc == 0) { | 44 | if (argc == 0) { |
| 36 | print_events(NULL, false); | 45 | print_events(NULL, false); |
| 37 | return 0; | 46 | return 0; |
| @@ -53,8 +62,6 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 53 | print_hwcache_events(NULL, false); | 62 | print_hwcache_events(NULL, false); |
| 54 | else if (strcmp(argv[i], "pmu") == 0) | 63 | else if (strcmp(argv[i], "pmu") == 0) |
| 55 | print_pmu_events(NULL, false); | 64 | print_pmu_events(NULL, false); |
| 56 | else if (strcmp(argv[i], "--raw-dump") == 0) | ||
| 57 | print_events(NULL, true); | ||
| 58 | else { | 65 | else { |
| 59 | char *sep = strchr(argv[i], ':'), *s; | 66 | char *sep = strchr(argv[i], ':'), *s; |
| 60 | int sep_idx; | 67 | int sep_idx; |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 39367609c707..072ae8ad67fc 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -457,6 +457,19 @@ static void report__collapse_hists(struct report *rep) | |||
| 457 | ui_progress__finish(); | 457 | ui_progress__finish(); |
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | static void report__output_resort(struct report *rep) | ||
| 461 | { | ||
| 462 | struct ui_progress prog; | ||
| 463 | struct perf_evsel *pos; | ||
| 464 | |||
| 465 | ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); | ||
| 466 | |||
| 467 | evlist__for_each(rep->session->evlist, pos) | ||
| 468 | hists__output_resort(evsel__hists(pos), &prog); | ||
| 469 | |||
| 470 | ui_progress__finish(); | ||
| 471 | } | ||
| 472 | |||
| 460 | static int __cmd_report(struct report *rep) | 473 | static int __cmd_report(struct report *rep) |
| 461 | { | 474 | { |
| 462 | int ret; | 475 | int ret; |
| @@ -505,13 +518,20 @@ static int __cmd_report(struct report *rep) | |||
| 505 | if (session_done()) | 518 | if (session_done()) |
| 506 | return 0; | 519 | return 0; |
| 507 | 520 | ||
| 521 | /* | ||
| 522 | * recalculate number of entries after collapsing since it | ||
| 523 | * might be changed during the collapse phase. | ||
| 524 | */ | ||
| 525 | rep->nr_entries = 0; | ||
| 526 | evlist__for_each(session->evlist, pos) | ||
| 527 | rep->nr_entries += evsel__hists(pos)->nr_entries; | ||
| 528 | |||
| 508 | if (rep->nr_entries == 0) { | 529 | if (rep->nr_entries == 0) { |
| 509 | ui__error("The %s file has no samples!\n", file->path); | 530 | ui__error("The %s file has no samples!\n", file->path); |
| 510 | return 0; | 531 | return 0; |
| 511 | } | 532 | } |
| 512 | 533 | ||
| 513 | evlist__for_each(session->evlist, pos) | 534 | report__output_resort(rep); |
| 514 | hists__output_resort(evsel__hists(pos)); | ||
| 515 | 535 | ||
| 516 | return report__browse_hists(rep); | 536 | return report__browse_hists(rep); |
| 517 | } | 537 | } |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 0aa7747ff139..616f0fcb4701 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
| @@ -66,7 +66,6 @@ | |||
| 66 | #include <sys/utsname.h> | 66 | #include <sys/utsname.h> |
| 67 | #include <sys/mman.h> | 67 | #include <sys/mman.h> |
| 68 | 68 | ||
| 69 | #include <linux/unistd.h> | ||
| 70 | #include <linux/types.h> | 69 | #include <linux/types.h> |
| 71 | 70 | ||
| 72 | static volatile int done; | 71 | static volatile int done; |
| @@ -285,7 +284,7 @@ static void perf_top__print_sym_table(struct perf_top *top) | |||
| 285 | } | 284 | } |
| 286 | 285 | ||
| 287 | hists__collapse_resort(hists, NULL); | 286 | hists__collapse_resort(hists, NULL); |
| 288 | hists__output_resort(hists); | 287 | hists__output_resort(hists, NULL); |
| 289 | 288 | ||
| 290 | hists__output_recalc_col_len(hists, top->print_entries - printed); | 289 | hists__output_recalc_col_len(hists, top->print_entries - printed); |
| 291 | putchar('\n'); | 290 | putchar('\n'); |
| @@ -554,7 +553,7 @@ static void perf_top__sort_new_samples(void *arg) | |||
| 554 | } | 553 | } |
| 555 | 554 | ||
| 556 | hists__collapse_resort(hists, NULL); | 555 | hists__collapse_resort(hists, NULL); |
| 557 | hists__output_resort(hists); | 556 | hists__output_resort(hists, NULL); |
| 558 | } | 557 | } |
| 559 | 558 | ||
| 560 | static void *display_thread_tui(void *arg) | 559 | static void *display_thread_tui(void *arg) |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 5d4b039fe1ed..648e31ff4021 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
| @@ -20,7 +20,7 @@ NO_PERF_REGS := 1 | |||
| 20 | 20 | ||
| 21 | # Additional ARCH settings for x86 | 21 | # Additional ARCH settings for x86 |
| 22 | ifeq ($(ARCH),x86) | 22 | ifeq ($(ARCH),x86) |
| 23 | ifeq (${IS_X86_64}, 1) | 23 | ifeq (${IS_64_BIT}, 1) |
| 24 | CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT | 24 | CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT |
| 25 | ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S | 25 | ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S |
| 26 | LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 | 26 | LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 |
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch index 851cd0172a76..ff95a68741d1 100644 --- a/tools/perf/config/Makefile.arch +++ b/tools/perf/config/Makefile.arch | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | 1 | ||
| 2 | uname_M := $(shell uname -m 2>/dev/null || echo not) | 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 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | 5 | -e s/arm.*/arm/ -e s/sa110/arm/ \ |
| 6 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | 6 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ |
| 7 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ | 7 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ |
| @@ -9,23 +9,23 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | |||
| 9 | -e s/tile.*/tile/ ) | 9 | -e s/tile.*/tile/ ) |
| 10 | 10 | ||
| 11 | # Additional ARCH settings for x86 | 11 | # Additional ARCH settings for x86 |
| 12 | ifeq ($(ARCH),i386) | 12 | ifeq ($(RAW_ARCH),i386) |
| 13 | override ARCH := x86 | 13 | ARCH ?= x86 |
| 14 | endif | 14 | endif |
| 15 | 15 | ||
| 16 | ifeq ($(ARCH),x86_64) | 16 | ifeq ($(RAW_ARCH),x86_64) |
| 17 | override ARCH := x86 | 17 | ARCH ?= x86 |
| 18 | IS_X86_64 := 0 | 18 | |
| 19 | ifeq (, $(findstring m32,$(CFLAGS))) | 19 | ifneq (, $(findstring m32,$(CFLAGS))) |
| 20 | IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) | 20 | RAW_ARCH := x86_32 |
| 21 | RAW_ARCH := x86_64 | ||
| 22 | endif | 21 | endif |
| 23 | endif | 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 | IS_64_BIT := 1 | 28 | IS_64_BIT := 1 |
| 27 | else ifeq ($(ARCH),x86) | ||
| 28 | IS_64_BIT := 0 | ||
| 29 | else | 29 | else |
| 30 | IS_64_BIT := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) | 30 | IS_64_BIT := 0 |
| 31 | endif | 31 | endif |
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h index a3b13d7dc1d4..6ef68165c9db 100644 --- a/tools/perf/perf-sys.h +++ b/tools/perf/perf-sys.h | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include <sys/syscall.h> | 6 | #include <sys/syscall.h> |
| 7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
| 8 | #include <linux/perf_event.h> | 8 | #include <linux/perf_event.h> |
| 9 | #include <asm/unistd.h> | ||
| 10 | 9 | ||
| 11 | #if defined(__i386__) | 10 | #if defined(__i386__) |
| 12 | #define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") | 11 | #define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") |
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c index 790ceba6ad3f..28431d1bbcf5 100644 --- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c +++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c | |||
| @@ -5,7 +5,10 @@ | |||
| 5 | * ANY CHANGES MADE HERE WILL BE LOST! | 5 | * ANY CHANGES MADE HERE WILL BE LOST! |
| 6 | * | 6 | * |
| 7 | */ | 7 | */ |
| 8 | 8 | #include <stdbool.h> | |
| 9 | #ifndef HAS_BOOL | ||
| 10 | # define HAS_BOOL 1 | ||
| 11 | #endif | ||
| 9 | #line 1 "Context.xs" | 12 | #line 1 "Context.xs" |
| 10 | /* | 13 | /* |
| 11 | * Context.xs. XS interfaces for perf script. | 14 | * Context.xs. XS interfaces for perf script. |
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index ab28cca2cb97..0bf06bec68c7 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c | |||
| @@ -11,6 +11,9 @@ | |||
| 11 | #include "thread.h" | 11 | #include "thread.h" |
| 12 | #include "callchain.h" | 12 | #include "callchain.h" |
| 13 | 13 | ||
| 14 | /* For bsearch. We try to unwind functions in shared object. */ | ||
| 15 | #include <stdlib.h> | ||
| 16 | |||
| 14 | static int mmap_handler(struct perf_tool *tool __maybe_unused, | 17 | static int mmap_handler(struct perf_tool *tool __maybe_unused, |
| 15 | union perf_event *event, | 18 | union perf_event *event, |
| 16 | struct perf_sample *sample __maybe_unused, | 19 | struct perf_sample *sample __maybe_unused, |
| @@ -28,7 +31,7 @@ static int init_live_machine(struct machine *machine) | |||
| 28 | mmap_handler, machine, true); | 31 | mmap_handler, machine, true); |
| 29 | } | 32 | } |
| 30 | 33 | ||
| 31 | #define MAX_STACK 6 | 34 | #define MAX_STACK 8 |
| 32 | 35 | ||
| 33 | static int unwind_entry(struct unwind_entry *entry, void *arg) | 36 | static int unwind_entry(struct unwind_entry *entry, void *arg) |
| 34 | { | 37 | { |
| @@ -37,6 +40,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) | |||
| 37 | static const char *funcs[MAX_STACK] = { | 40 | static const char *funcs[MAX_STACK] = { |
| 38 | "test__arch_unwind_sample", | 41 | "test__arch_unwind_sample", |
| 39 | "unwind_thread", | 42 | "unwind_thread", |
| 43 | "compare", | ||
| 44 | "bsearch", | ||
| 40 | "krava_3", | 45 | "krava_3", |
| 41 | "krava_2", | 46 | "krava_2", |
| 42 | "krava_1", | 47 | "krava_1", |
| @@ -88,10 +93,37 @@ static int unwind_thread(struct thread *thread) | |||
| 88 | return err; | 93 | return err; |
| 89 | } | 94 | } |
| 90 | 95 | ||
| 96 | static int global_unwind_retval = -INT_MAX; | ||
| 97 | |||
| 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 | |||
| 91 | __attribute__ ((noinline)) | 110 | __attribute__ ((noinline)) |
| 92 | static int krava_3(struct thread *thread) | 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 | __attribute__ ((noinline)) | 129 | __attribute__ ((noinline)) |
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index 614d5c4978ab..8d110dec393e 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c | |||
| @@ -187,7 +187,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec | |||
| 187 | * function since TEST_ASSERT_VAL() returns in case of failure. | 187 | * function since TEST_ASSERT_VAL() returns in case of failure. |
| 188 | */ | 188 | */ |
| 189 | hists__collapse_resort(hists, NULL); | 189 | hists__collapse_resort(hists, NULL); |
| 190 | hists__output_resort(hists); | 190 | hists__output_resort(hists, NULL); |
| 191 | 191 | ||
| 192 | if (verbose > 2) { | 192 | if (verbose > 2) { |
| 193 | pr_info("use callchain: %d, cumulate callchain: %d\n", | 193 | pr_info("use callchain: %d, cumulate callchain: %d\n", |
| @@ -454,12 +454,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) | |||
| 454 | * 30.00% 10.00% perf perf [.] cmd_record | 454 | * 30.00% 10.00% perf perf [.] cmd_record |
| 455 | * 20.00% 0.00% bash libc [.] malloc | 455 | * 20.00% 0.00% bash libc [.] malloc |
| 456 | * 10.00% 10.00% bash [kernel] [k] page_fault | 456 | * 10.00% 10.00% bash [kernel] [k] page_fault |
| 457 | * 10.00% 10.00% perf [kernel] [k] schedule | 457 | * 10.00% 10.00% bash bash [.] xmalloc |
| 458 | * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open | ||
| 459 | * 10.00% 10.00% perf [kernel] [k] page_fault | 458 | * 10.00% 10.00% perf [kernel] [k] page_fault |
| 460 | * 10.00% 10.00% perf libc [.] free | ||
| 461 | * 10.00% 10.00% perf libc [.] malloc | 459 | * 10.00% 10.00% perf libc [.] malloc |
| 462 | * 10.00% 10.00% bash bash [.] xmalloc | 460 | * 10.00% 10.00% perf [kernel] [k] schedule |
| 461 | * 10.00% 10.00% perf libc [.] free | ||
| 462 | * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open | ||
| 463 | */ | 463 | */ |
| 464 | struct result expected[] = { | 464 | struct result expected[] = { |
| 465 | { 7000, 2000, "perf", "perf", "main" }, | 465 | { 7000, 2000, "perf", "perf", "main" }, |
| @@ -468,12 +468,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) | |||
| 468 | { 3000, 1000, "perf", "perf", "cmd_record" }, | 468 | { 3000, 1000, "perf", "perf", "cmd_record" }, |
| 469 | { 2000, 0, "bash", "libc", "malloc" }, | 469 | { 2000, 0, "bash", "libc", "malloc" }, |
| 470 | { 1000, 1000, "bash", "[kernel]", "page_fault" }, | 470 | { 1000, 1000, "bash", "[kernel]", "page_fault" }, |
| 471 | { 1000, 1000, "perf", "[kernel]", "schedule" }, | 471 | { 1000, 1000, "bash", "bash", "xmalloc" }, |
| 472 | { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, | ||
| 473 | { 1000, 1000, "perf", "[kernel]", "page_fault" }, | 472 | { 1000, 1000, "perf", "[kernel]", "page_fault" }, |
| 473 | { 1000, 1000, "perf", "[kernel]", "schedule" }, | ||
| 474 | { 1000, 1000, "perf", "libc", "free" }, | 474 | { 1000, 1000, "perf", "libc", "free" }, |
| 475 | { 1000, 1000, "perf", "libc", "malloc" }, | 475 | { 1000, 1000, "perf", "libc", "malloc" }, |
| 476 | { 1000, 1000, "bash", "bash", "xmalloc" }, | 476 | { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, |
| 477 | }; | 477 | }; |
| 478 | 478 | ||
| 479 | symbol_conf.use_callchain = false; | 479 | symbol_conf.use_callchain = false; |
| @@ -537,10 +537,13 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
| 537 | * malloc | 537 | * malloc |
| 538 | * main | 538 | * main |
| 539 | * | 539 | * |
| 540 | * 10.00% 10.00% perf [kernel] [k] schedule | 540 | * 10.00% 10.00% bash bash [.] xmalloc |
| 541 | * | | 541 | * | |
| 542 | * --- schedule | 542 | * --- xmalloc |
| 543 | * run_command | 543 | * malloc |
| 544 | * xmalloc <--- NOTE: there's a cycle | ||
| 545 | * malloc | ||
| 546 | * xmalloc | ||
| 544 | * main | 547 | * main |
| 545 | * | 548 | * |
| 546 | * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open | 549 | * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open |
| @@ -556,6 +559,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
| 556 | * run_command | 559 | * run_command |
| 557 | * main | 560 | * main |
| 558 | * | 561 | * |
| 562 | * 10.00% 10.00% perf [kernel] [k] schedule | ||
| 563 | * | | ||
| 564 | * --- schedule | ||
| 565 | * run_command | ||
| 566 | * main | ||
| 567 | * | ||
| 559 | * 10.00% 10.00% perf libc [.] free | 568 | * 10.00% 10.00% perf libc [.] free |
| 560 | * | | 569 | * | |
| 561 | * --- free | 570 | * --- free |
| @@ -570,15 +579,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
| 570 | * run_command | 579 | * run_command |
| 571 | * main | 580 | * main |
| 572 | * | 581 | * |
| 573 | * 10.00% 10.00% bash bash [.] xmalloc | ||
| 574 | * | | ||
| 575 | * --- xmalloc | ||
| 576 | * malloc | ||
| 577 | * xmalloc <--- NOTE: there's a cycle | ||
| 578 | * malloc | ||
| 579 | * xmalloc | ||
| 580 | * main | ||
| 581 | * | ||
| 582 | */ | 582 | */ |
| 583 | struct result expected[] = { | 583 | struct result expected[] = { |
| 584 | { 7000, 2000, "perf", "perf", "main" }, | 584 | { 7000, 2000, "perf", "perf", "main" }, |
| @@ -587,12 +587,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
| 587 | { 3000, 1000, "perf", "perf", "cmd_record" }, | 587 | { 3000, 1000, "perf", "perf", "cmd_record" }, |
| 588 | { 2000, 0, "bash", "libc", "malloc" }, | 588 | { 2000, 0, "bash", "libc", "malloc" }, |
| 589 | { 1000, 1000, "bash", "[kernel]", "page_fault" }, | 589 | { 1000, 1000, "bash", "[kernel]", "page_fault" }, |
| 590 | { 1000, 1000, "perf", "[kernel]", "schedule" }, | 590 | { 1000, 1000, "bash", "bash", "xmalloc" }, |
| 591 | { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, | 591 | { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, |
| 592 | { 1000, 1000, "perf", "[kernel]", "page_fault" }, | 592 | { 1000, 1000, "perf", "[kernel]", "page_fault" }, |
| 593 | { 1000, 1000, "perf", "[kernel]", "schedule" }, | ||
| 593 | { 1000, 1000, "perf", "libc", "free" }, | 594 | { 1000, 1000, "perf", "libc", "free" }, |
| 594 | { 1000, 1000, "perf", "libc", "malloc" }, | 595 | { 1000, 1000, "perf", "libc", "malloc" }, |
| 595 | { 1000, 1000, "bash", "bash", "xmalloc" }, | ||
| 596 | }; | 596 | }; |
| 597 | struct callchain_result expected_callchain[] = { | 597 | struct callchain_result expected_callchain[] = { |
| 598 | { | 598 | { |
| @@ -622,9 +622,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
| 622 | { "bash", "main" }, }, | 622 | { "bash", "main" }, }, |
| 623 | }, | 623 | }, |
| 624 | { | 624 | { |
| 625 | 3, { { "[kernel]", "schedule" }, | 625 | 6, { { "bash", "xmalloc" }, |
| 626 | { "perf", "run_command" }, | 626 | { "libc", "malloc" }, |
| 627 | { "perf", "main" }, }, | 627 | { "bash", "xmalloc" }, |
| 628 | { "libc", "malloc" }, | ||
| 629 | { "bash", "xmalloc" }, | ||
| 630 | { "bash", "main" }, }, | ||
| 628 | }, | 631 | }, |
| 629 | { | 632 | { |
| 630 | 3, { { "[kernel]", "sys_perf_event_open" }, | 633 | 3, { { "[kernel]", "sys_perf_event_open" }, |
| @@ -638,6 +641,11 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
| 638 | { "perf", "main" }, }, | 641 | { "perf", "main" }, }, |
| 639 | }, | 642 | }, |
| 640 | { | 643 | { |
| 644 | 3, { { "[kernel]", "schedule" }, | ||
| 645 | { "perf", "run_command" }, | ||
| 646 | { "perf", "main" }, }, | ||
| 647 | }, | ||
| 648 | { | ||
| 641 | 4, { { "libc", "free" }, | 649 | 4, { { "libc", "free" }, |
| 642 | { "perf", "cmd_record" }, | 650 | { "perf", "cmd_record" }, |
| 643 | { "perf", "run_command" }, | 651 | { "perf", "run_command" }, |
| @@ -649,14 +657,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
| 649 | { "perf", "run_command" }, | 657 | { "perf", "run_command" }, |
| 650 | { "perf", "main" }, }, | 658 | { "perf", "main" }, }, |
| 651 | }, | 659 | }, |
| 652 | { | ||
| 653 | 6, { { "bash", "xmalloc" }, | ||
| 654 | { "libc", "malloc" }, | ||
| 655 | { "bash", "xmalloc" }, | ||
| 656 | { "libc", "malloc" }, | ||
| 657 | { "bash", "xmalloc" }, | ||
| 658 | { "bash", "main" }, }, | ||
| 659 | }, | ||
| 660 | }; | 660 | }; |
| 661 | 661 | ||
| 662 | symbol_conf.use_callchain = true; | 662 | symbol_conf.use_callchain = true; |
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 74f257a81265..59e53db7914c 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c | |||
| @@ -138,7 +138,7 @@ int test__hists_filter(void) | |||
| 138 | struct hists *hists = evsel__hists(evsel); | 138 | struct hists *hists = evsel__hists(evsel); |
| 139 | 139 | ||
| 140 | hists__collapse_resort(hists, NULL); | 140 | hists__collapse_resort(hists, NULL); |
| 141 | hists__output_resort(hists); | 141 | hists__output_resort(hists, NULL); |
| 142 | 142 | ||
| 143 | if (verbose > 2) { | 143 | if (verbose > 2) { |
| 144 | pr_info("Normal histogram\n"); | 144 | pr_info("Normal histogram\n"); |
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index a748f2be1222..f5547610da02 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c | |||
| @@ -152,7 +152,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine) | |||
| 152 | goto out; | 152 | goto out; |
| 153 | 153 | ||
| 154 | hists__collapse_resort(hists, NULL); | 154 | hists__collapse_resort(hists, NULL); |
| 155 | hists__output_resort(hists); | 155 | hists__output_resort(hists, NULL); |
| 156 | 156 | ||
| 157 | if (verbose > 2) { | 157 | if (verbose > 2) { |
| 158 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 158 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
| @@ -252,7 +252,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine) | |||
| 252 | goto out; | 252 | goto out; |
| 253 | 253 | ||
| 254 | hists__collapse_resort(hists, NULL); | 254 | hists__collapse_resort(hists, NULL); |
| 255 | hists__output_resort(hists); | 255 | hists__output_resort(hists, NULL); |
| 256 | 256 | ||
| 257 | if (verbose > 2) { | 257 | if (verbose > 2) { |
| 258 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 258 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
| @@ -306,7 +306,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) | |||
| 306 | goto out; | 306 | goto out; |
| 307 | 307 | ||
| 308 | hists__collapse_resort(hists, NULL); | 308 | hists__collapse_resort(hists, NULL); |
| 309 | hists__output_resort(hists); | 309 | hists__output_resort(hists, NULL); |
| 310 | 310 | ||
| 311 | if (verbose > 2) { | 311 | if (verbose > 2) { |
| 312 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 312 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
| @@ -384,7 +384,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
| 384 | goto out; | 384 | goto out; |
| 385 | 385 | ||
| 386 | hists__collapse_resort(hists, NULL); | 386 | hists__collapse_resort(hists, NULL); |
| 387 | hists__output_resort(hists); | 387 | hists__output_resort(hists, NULL); |
| 388 | 388 | ||
| 389 | if (verbose > 2) { | 389 | if (verbose > 2) { |
| 390 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 390 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
| @@ -487,7 +487,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine) | |||
| 487 | goto out; | 487 | goto out; |
| 488 | 488 | ||
| 489 | hists__collapse_resort(hists, NULL); | 489 | hists__collapse_resort(hists, NULL); |
| 490 | hists__output_resort(hists); | 490 | hists__output_resort(hists, NULL); |
| 491 | 491 | ||
| 492 | if (verbose > 2) { | 492 | if (verbose > 2) { |
| 493 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | 493 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index e6bb04b5b09b..788506eef567 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
| @@ -550,7 +550,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, | |||
| 550 | bool need_percent; | 550 | bool need_percent; |
| 551 | 551 | ||
| 552 | node = rb_first(root); | 552 | node = rb_first(root); |
| 553 | need_percent = !!rb_next(node); | 553 | need_percent = node && rb_next(node); |
| 554 | 554 | ||
| 555 | while (node) { | 555 | while (node) { |
| 556 | struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); | 556 | struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); |
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index dc0d095f318c..482adae3cc44 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
| @@ -204,6 +204,9 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b, | |||
| 204 | if (ret) | 204 | if (ret) |
| 205 | return ret; | 205 | return ret; |
| 206 | 206 | ||
| 207 | if (a->thread != b->thread || !symbol_conf.use_callchain) | ||
| 208 | return 0; | ||
| 209 | |||
| 207 | ret = b->callchain->max_depth - a->callchain->max_depth; | 210 | ret = b->callchain->max_depth - a->callchain->max_depth; |
| 208 | } | 211 | } |
| 209 | return ret; | 212 | return ret; |
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 2f612562978c..3c38f25b1695 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c | |||
| @@ -1,5 +1,8 @@ | |||
| 1 | #include <signal.h> | 1 | #include <signal.h> |
| 2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
| 3 | #ifdef HAVE_BACKTRACE_SUPPORT | ||
| 4 | #include <execinfo.h> | ||
| 5 | #endif | ||
| 3 | 6 | ||
| 4 | #include "../../util/cache.h" | 7 | #include "../../util/cache.h" |
| 5 | #include "../../util/debug.h" | 8 | #include "../../util/debug.h" |
| @@ -88,6 +91,25 @@ int ui__getch(int delay_secs) | |||
| 88 | return SLkp_getkey(); | 91 | return SLkp_getkey(); |
| 89 | } | 92 | } |
| 90 | 93 | ||
| 94 | #ifdef HAVE_BACKTRACE_SUPPORT | ||
| 95 | static void ui__signal_backtrace(int sig) | ||
| 96 | { | ||
| 97 | void *stackdump[32]; | ||
| 98 | size_t size; | ||
| 99 | |||
| 100 | ui__exit(false); | ||
| 101 | psignal(sig, "perf"); | ||
| 102 | |||
| 103 | printf("-------- backtrace --------\n"); | ||
| 104 | size = backtrace(stackdump, ARRAY_SIZE(stackdump)); | ||
| 105 | backtrace_symbols_fd(stackdump, size, STDOUT_FILENO); | ||
| 106 | |||
| 107 | exit(0); | ||
| 108 | } | ||
| 109 | #else | ||
| 110 | # define ui__signal_backtrace ui__signal | ||
| 111 | #endif | ||
| 112 | |||
| 91 | static void ui__signal(int sig) | 113 | static void ui__signal(int sig) |
| 92 | { | 114 | { |
| 93 | ui__exit(false); | 115 | ui__exit(false); |
| @@ -122,8 +144,8 @@ int ui__init(void) | |||
| 122 | ui_browser__init(); | 144 | ui_browser__init(); |
| 123 | tui_progress__init(); | 145 | tui_progress__init(); |
| 124 | 146 | ||
| 125 | signal(SIGSEGV, ui__signal); | 147 | signal(SIGSEGV, ui__signal_backtrace); |
| 126 | signal(SIGFPE, ui__signal); | 148 | signal(SIGFPE, ui__signal_backtrace); |
| 127 | signal(SIGINT, ui__signal); | 149 | signal(SIGINT, ui__signal); |
| 128 | signal(SIGQUIT, ui__signal); | 150 | signal(SIGQUIT, ui__signal); |
| 129 | signal(SIGTERM, ui__signal); | 151 | signal(SIGTERM, ui__signal); |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 79999ceaf2be..01bc4e23a2cf 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
| @@ -177,14 +177,17 @@ static int lock__parse(struct ins_operands *ops) | |||
| 177 | goto out_free_ops; | 177 | goto out_free_ops; |
| 178 | 178 | ||
| 179 | ops->locked.ins = ins__find(name); | 179 | ops->locked.ins = ins__find(name); |
| 180 | free(name); | ||
| 181 | |||
| 180 | if (ops->locked.ins == NULL) | 182 | if (ops->locked.ins == NULL) |
| 181 | goto out_free_ops; | 183 | goto out_free_ops; |
| 182 | 184 | ||
| 183 | if (!ops->locked.ins->ops) | 185 | if (!ops->locked.ins->ops) |
| 184 | return 0; | 186 | return 0; |
| 185 | 187 | ||
| 186 | if (ops->locked.ins->ops->parse) | 188 | if (ops->locked.ins->ops->parse && |
| 187 | ops->locked.ins->ops->parse(ops->locked.ops); | 189 | ops->locked.ins->ops->parse(ops->locked.ops) < 0) |
| 190 | goto out_free_ops; | ||
| 188 | 191 | ||
| 189 | return 0; | 192 | return 0; |
| 190 | 193 | ||
| @@ -208,6 +211,13 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size, | |||
| 208 | 211 | ||
| 209 | static void lock__delete(struct ins_operands *ops) | 212 | static void lock__delete(struct ins_operands *ops) |
| 210 | { | 213 | { |
| 214 | struct ins *ins = ops->locked.ins; | ||
| 215 | |||
| 216 | if (ins && ins->ops->free) | ||
| 217 | ins->ops->free(ops->locked.ops); | ||
| 218 | else | ||
| 219 | ins__delete(ops->locked.ops); | ||
| 220 | |||
| 211 | zfree(&ops->locked.ops); | 221 | zfree(&ops->locked.ops); |
| 212 | zfree(&ops->target.raw); | 222 | zfree(&ops->target.raw); |
| 213 | zfree(&ops->target.name); | 223 | zfree(&ops->target.name); |
| @@ -531,8 +541,8 @@ static void disasm_line__init_ins(struct disasm_line *dl) | |||
| 531 | if (!dl->ins->ops) | 541 | if (!dl->ins->ops) |
| 532 | return; | 542 | return; |
| 533 | 543 | ||
| 534 | if (dl->ins->ops->parse) | 544 | if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops) < 0) |
| 535 | dl->ins->ops->parse(&dl->ops); | 545 | dl->ins = NULL; |
| 536 | } | 546 | } |
| 537 | 547 | ||
| 538 | static int disasm_line__parse(char *line, char **namep, char **rawp) | 548 | static int disasm_line__parse(char *line, char **namep, char **rawp) |
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 0784a9420528..cadbdc90a5cb 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
| @@ -116,11 +116,6 @@ struct annotation { | |||
| 116 | struct annotated_source *src; | 116 | struct annotated_source *src; |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | struct sannotation { | ||
| 120 | struct annotation annotation; | ||
| 121 | struct symbol symbol; | ||
| 122 | }; | ||
| 123 | |||
| 124 | static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) | 119 | static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) |
| 125 | { | 120 | { |
| 126 | return (((void *)¬es->src->histograms) + | 121 | return (((void *)¬es->src->histograms) + |
| @@ -129,8 +124,7 @@ static inline struct sym_hist *annotation__histogram(struct annotation *notes, i | |||
| 129 | 124 | ||
| 130 | static inline struct annotation *symbol__annotation(struct symbol *sym) | 125 | static inline struct annotation *symbol__annotation(struct symbol *sym) |
| 131 | { | 126 | { |
| 132 | struct sannotation *a = container_of(sym, struct sannotation, symbol); | 127 | return (void *)sym - symbol_conf.priv_size; |
| 133 | return &a->annotation; | ||
| 134 | } | 128 | } |
| 135 | 129 | ||
| 136 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); | 130 | int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 5cf9e1b5989d..d04d770d90f6 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
| @@ -71,7 +71,9 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2 | |||
| 71 | extern char *perf_pathdup(const char *fmt, ...) | 71 | extern char *perf_pathdup(const char *fmt, ...) |
| 72 | __attribute__((format (printf, 1, 2))); | 72 | __attribute__((format (printf, 1, 2))); |
| 73 | 73 | ||
| 74 | #ifndef __UCLIBC__ | ||
| 74 | /* Matches the libc/libbsd function attribute so we declare this unconditionally: */ | 75 | /* Matches the libc/libbsd function attribute so we declare this unconditionally: */ |
| 75 | extern size_t strlcpy(char *dest, const char *src, size_t size); | 76 | extern size_t strlcpy(char *dest, const char *src, size_t size); |
| 77 | #endif | ||
| 76 | 78 | ||
| 77 | #endif /* __PERF_CACHE_H */ | 79 | #endif /* __PERF_CACHE_H */ |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 64b377e591e4..14e7a123d43b 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
| @@ -841,3 +841,33 @@ char *callchain_list__sym_name(struct callchain_list *cl, | |||
| 841 | 841 | ||
| 842 | return bf; | 842 | return bf; |
| 843 | } | 843 | } |
| 844 | |||
| 845 | static void free_callchain_node(struct callchain_node *node) | ||
| 846 | { | ||
| 847 | struct callchain_list *list, *tmp; | ||
| 848 | struct callchain_node *child; | ||
| 849 | struct rb_node *n; | ||
| 850 | |||
| 851 | list_for_each_entry_safe(list, tmp, &node->val, list) { | ||
| 852 | list_del(&list->list); | ||
| 853 | free(list); | ||
| 854 | } | ||
| 855 | |||
| 856 | n = rb_first(&node->rb_root_in); | ||
| 857 | while (n) { | ||
| 858 | child = container_of(n, struct callchain_node, rb_node_in); | ||
| 859 | n = rb_next(n); | ||
| 860 | rb_erase(&child->rb_node_in, &node->rb_root_in); | ||
| 861 | |||
| 862 | free_callchain_node(child); | ||
| 863 | free(child); | ||
| 864 | } | ||
| 865 | } | ||
| 866 | |||
| 867 | void free_callchain(struct callchain_root *root) | ||
| 868 | { | ||
| 869 | if (!symbol_conf.use_callchain) | ||
| 870 | return; | ||
| 871 | |||
| 872 | free_callchain_node(&root->node); | ||
| 873 | } | ||
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index dbc08cf5f970..c0ec1acc38e4 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
| @@ -198,4 +198,6 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, | |||
| 198 | char *callchain_list__sym_name(struct callchain_list *cl, | 198 | char *callchain_list__sym_name(struct callchain_list *cl, |
| 199 | char *bf, size_t bfsize, bool show_dso); | 199 | char *bf, size_t bfsize, bool show_dso); |
| 200 | 200 | ||
| 201 | void free_callchain(struct callchain_root *root); | ||
| 202 | |||
| 201 | #endif /* __PERF_CALLCHAIN_H */ | 203 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index cbab1fb77b1d..2e507b5025a3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -1445,7 +1445,7 @@ int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused, | |||
| 1445 | case ENOENT: | 1445 | case ENOENT: |
| 1446 | scnprintf(buf, size, "%s", | 1446 | scnprintf(buf, size, "%s", |
| 1447 | "Error:\tUnable to find debugfs\n" | 1447 | "Error:\tUnable to find debugfs\n" |
| 1448 | "Hint:\tWas your kernel was compiled with debugfs support?\n" | 1448 | "Hint:\tWas your kernel compiled with debugfs support?\n" |
| 1449 | "Hint:\tIs the debugfs filesystem mounted?\n" | 1449 | "Hint:\tIs the debugfs filesystem mounted?\n" |
| 1450 | "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); | 1450 | "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); |
| 1451 | break; | 1451 | break; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 6e88b9e395df..182395546ddc 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "evlist.h" | 6 | #include "evlist.h" |
| 7 | #include "evsel.h" | 7 | #include "evsel.h" |
| 8 | #include "annotate.h" | 8 | #include "annotate.h" |
| 9 | #include "ui/progress.h" | ||
| 9 | #include <math.h> | 10 | #include <math.h> |
| 10 | 11 | ||
| 11 | static bool hists__filter_entry_by_dso(struct hists *hists, | 12 | static bool hists__filter_entry_by_dso(struct hists *hists, |
| @@ -303,7 +304,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, | |||
| 303 | size_t callchain_size = 0; | 304 | size_t callchain_size = 0; |
| 304 | struct hist_entry *he; | 305 | struct hist_entry *he; |
| 305 | 306 | ||
| 306 | if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) | 307 | if (symbol_conf.use_callchain) |
| 307 | callchain_size = sizeof(struct callchain_root); | 308 | callchain_size = sizeof(struct callchain_root); |
| 308 | 309 | ||
| 309 | he = zalloc(sizeof(*he) + callchain_size); | 310 | he = zalloc(sizeof(*he) + callchain_size); |
| @@ -736,7 +737,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter, | |||
| 736 | iter->he = he; | 737 | iter->he = he; |
| 737 | he_cache[iter->curr++] = he; | 738 | he_cache[iter->curr++] = he; |
| 738 | 739 | ||
| 739 | callchain_append(he->callchain, &callchain_cursor, sample->period); | 740 | hist_entry__append_callchain(he, sample); |
| 740 | 741 | ||
| 741 | /* | 742 | /* |
| 742 | * We need to re-initialize the cursor since callchain_append() | 743 | * We need to re-initialize the cursor since callchain_append() |
| @@ -809,7 +810,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter, | |||
| 809 | iter->he = he; | 810 | iter->he = he; |
| 810 | he_cache[iter->curr++] = he; | 811 | he_cache[iter->curr++] = he; |
| 811 | 812 | ||
| 812 | callchain_append(he->callchain, &cursor, sample->period); | 813 | if (symbol_conf.use_callchain) |
| 814 | callchain_append(he->callchain, &cursor, sample->period); | ||
| 813 | return 0; | 815 | return 0; |
| 814 | } | 816 | } |
| 815 | 817 | ||
| @@ -945,6 +947,7 @@ void hist_entry__free(struct hist_entry *he) | |||
| 945 | zfree(&he->mem_info); | 947 | zfree(&he->mem_info); |
| 946 | zfree(&he->stat_acc); | 948 | zfree(&he->stat_acc); |
| 947 | free_srcline(he->srcline); | 949 | free_srcline(he->srcline); |
| 950 | free_callchain(he->callchain); | ||
| 948 | free(he); | 951 | free(he); |
| 949 | } | 952 | } |
| 950 | 953 | ||
| @@ -987,6 +990,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, | |||
| 987 | else | 990 | else |
| 988 | p = &(*p)->rb_right; | 991 | p = &(*p)->rb_right; |
| 989 | } | 992 | } |
| 993 | hists->nr_entries++; | ||
| 990 | 994 | ||
| 991 | rb_link_node(&he->rb_node_in, parent, p); | 995 | rb_link_node(&he->rb_node_in, parent, p); |
| 992 | rb_insert_color(&he->rb_node_in, root); | 996 | rb_insert_color(&he->rb_node_in, root); |
| @@ -1024,7 +1028,10 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) | |||
| 1024 | if (!sort__need_collapse) | 1028 | if (!sort__need_collapse) |
| 1025 | return; | 1029 | return; |
| 1026 | 1030 | ||
| 1031 | hists->nr_entries = 0; | ||
| 1032 | |||
| 1027 | root = hists__get_rotate_entries_in(hists); | 1033 | root = hists__get_rotate_entries_in(hists); |
| 1034 | |||
| 1028 | next = rb_first(root); | 1035 | next = rb_first(root); |
| 1029 | 1036 | ||
| 1030 | while (next) { | 1037 | while (next) { |
| @@ -1119,7 +1126,7 @@ static void __hists__insert_output_entry(struct rb_root *entries, | |||
| 1119 | rb_insert_color(&he->rb_node, entries); | 1126 | rb_insert_color(&he->rb_node, entries); |
| 1120 | } | 1127 | } |
| 1121 | 1128 | ||
| 1122 | void hists__output_resort(struct hists *hists) | 1129 | void hists__output_resort(struct hists *hists, struct ui_progress *prog) |
| 1123 | { | 1130 | { |
| 1124 | struct rb_root *root; | 1131 | struct rb_root *root; |
| 1125 | struct rb_node *next; | 1132 | struct rb_node *next; |
| @@ -1148,6 +1155,9 @@ void hists__output_resort(struct hists *hists) | |||
| 1148 | 1155 | ||
| 1149 | if (!n->filtered) | 1156 | if (!n->filtered) |
| 1150 | hists__calc_col_len(hists, n); | 1157 | hists__calc_col_len(hists, n); |
| 1158 | |||
| 1159 | if (prog) | ||
| 1160 | ui_progress__update(prog, 1); | ||
| 1151 | } | 1161 | } |
| 1152 | } | 1162 | } |
| 1153 | 1163 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index d0ef9a19a744..46bd50344f85 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
| @@ -121,7 +121,7 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, | |||
| 121 | struct hists *hists); | 121 | struct hists *hists); |
| 122 | void hist_entry__free(struct hist_entry *); | 122 | void hist_entry__free(struct hist_entry *); |
| 123 | 123 | ||
| 124 | void hists__output_resort(struct hists *hists); | 124 | void hists__output_resort(struct hists *hists, struct ui_progress *prog); |
| 125 | void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); | 125 | void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); |
| 126 | 126 | ||
| 127 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); | 127 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); |
diff --git a/tools/perf/util/hweight.c b/tools/perf/util/hweight.c deleted file mode 100644 index 5c1d0d099f0d..000000000000 --- a/tools/perf/util/hweight.c +++ /dev/null | |||
| @@ -1,31 +0,0 @@ | |||
| 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 | } | ||
diff --git a/tools/perf/util/include/asm/hweight.h b/tools/perf/util/include/asm/hweight.h deleted file mode 100644 index 36cf26d434a5..000000000000 --- a/tools/perf/util/include/asm/hweight.h +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | #ifndef PERF_HWEIGHT_H | ||
| 2 | #define PERF_HWEIGHT_H | ||
| 3 | |||
| 4 | #include <linux/types.h> | ||
| 5 | unsigned int hweight32(unsigned int w); | ||
| 6 | unsigned long hweight64(__u64 w); | ||
| 7 | |||
| 8 | #endif /* PERF_HWEIGHT_H */ | ||
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 94de3e48b490..1bca3a9f2b16 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
| @@ -389,7 +389,6 @@ static struct thread *__machine__findnew_thread(struct machine *machine, | |||
| 389 | if (th != NULL) { | 389 | if (th != NULL) { |
| 390 | rb_link_node(&th->rb_node, parent, p); | 390 | rb_link_node(&th->rb_node, parent, p); |
| 391 | rb_insert_color(&th->rb_node, &machine->threads); | 391 | rb_insert_color(&th->rb_node, &machine->threads); |
| 392 | machine->last_match = th; | ||
| 393 | 392 | ||
| 394 | /* | 393 | /* |
| 395 | * We have to initialize map_groups separately | 394 | * We have to initialize map_groups separately |
| @@ -400,9 +399,12 @@ static struct thread *__machine__findnew_thread(struct machine *machine, | |||
| 400 | * leader and that would screwed the rb tree. | 399 | * leader and that would screwed the rb tree. |
| 401 | */ | 400 | */ |
| 402 | if (thread__init_map_groups(th, machine)) { | 401 | if (thread__init_map_groups(th, machine)) { |
| 402 | rb_erase(&th->rb_node, &machine->threads); | ||
| 403 | thread__delete(th); | 403 | thread__delete(th); |
| 404 | return NULL; | 404 | return NULL; |
| 405 | } | 405 | } |
| 406 | |||
| 407 | machine->last_match = th; | ||
| 406 | } | 408 | } |
| 407 | 409 | ||
| 408 | return th; | 410 | return th; |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 6951a9d42339..0e42438b1e59 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
| @@ -116,6 +116,22 @@ struct thread; | |||
| 116 | #define map__for_each_symbol(map, pos, n) \ | 116 | #define map__for_each_symbol(map, pos, n) \ |
| 117 | dso__for_each_symbol(map->dso, pos, n, map->type) | 117 | dso__for_each_symbol(map->dso, pos, n, map->type) |
| 118 | 118 | ||
| 119 | /* map__for_each_symbol_with_name - iterate over the symbols in the given map | ||
| 120 | * that have the given name | ||
| 121 | * | ||
| 122 | * @map: the 'struct map *' in which symbols itereated | ||
| 123 | * @sym_name: the symbol name | ||
| 124 | * @pos: the 'struct symbol *' to use as a loop cursor | ||
| 125 | * @filter: to use when loading the DSO | ||
| 126 | */ | ||
| 127 | #define __map__for_each_symbol_by_name(map, sym_name, pos, filter) \ | ||
| 128 | for (pos = map__find_symbol_by_name(map, sym_name, filter); \ | ||
| 129 | pos && strcmp(pos->name, sym_name) == 0; \ | ||
| 130 | pos = symbol__next_by_name(pos)) | ||
| 131 | |||
| 132 | #define map__for_each_symbol_by_name(map, sym_name, pos) \ | ||
| 133 | __map__for_each_symbol_by_name(map, sym_name, (pos), NULL) | ||
| 134 | |||
| 119 | typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); | 135 | typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); |
| 120 | 136 | ||
| 121 | void map__init(struct map *map, enum map_type type, | 137 | void map__init(struct map *map, enum map_type type, |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 28eb1417cb2a..919937eb0be2 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -446,7 +446,7 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs, | |||
| 446 | } | 446 | } |
| 447 | 447 | ||
| 448 | for (i = 0; i < ntevs; i++) { | 448 | for (i = 0; i < ntevs; i++) { |
| 449 | if (tevs[i].point.address) { | 449 | if (tevs[i].point.address && !tevs[i].point.retprobe) { |
| 450 | tmp = strdup(reloc_sym->name); | 450 | tmp = strdup(reloc_sym->name); |
| 451 | if (!tmp) | 451 | if (!tmp) |
| 452 | return -ENOMEM; | 452 | return -ENOMEM; |
| @@ -495,9 +495,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | if (ntevs == 0) { /* No error but failed to find probe point. */ | 497 | if (ntevs == 0) { /* No error but failed to find probe point. */ |
| 498 | pr_warning("Probe point '%s' not found.\n", | 498 | pr_warning("Probe point '%s' not found in debuginfo.\n", |
| 499 | synthesize_perf_probe_point(&pev->point)); | 499 | synthesize_perf_probe_point(&pev->point)); |
| 500 | return -ENOENT; | 500 | if (need_dwarf) |
| 501 | return -ENOENT; | ||
| 502 | return 0; | ||
| 501 | } | 503 | } |
| 502 | /* Error path : ntevs < 0 */ | 504 | /* Error path : ntevs < 0 */ |
| 503 | pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); | 505 | pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); |
| @@ -2050,9 +2052,11 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev) | |||
| 2050 | pr_debug("Writing event: %s\n", buf); | 2052 | pr_debug("Writing event: %s\n", buf); |
| 2051 | if (!probe_event_dry_run) { | 2053 | if (!probe_event_dry_run) { |
| 2052 | ret = write(fd, buf, strlen(buf)); | 2054 | ret = write(fd, buf, strlen(buf)); |
| 2053 | if (ret <= 0) | 2055 | if (ret <= 0) { |
| 2056 | ret = -errno; | ||
| 2054 | pr_warning("Failed to write event: %s\n", | 2057 | pr_warning("Failed to write event: %s\n", |
| 2055 | strerror_r(errno, sbuf, sizeof(sbuf))); | 2058 | strerror_r(errno, sbuf, sizeof(sbuf))); |
| 2059 | } | ||
| 2056 | } | 2060 | } |
| 2057 | free(buf); | 2061 | free(buf); |
| 2058 | return ret; | 2062 | return ret; |
| @@ -2189,18 +2193,17 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
| 2189 | return ret; | 2193 | return ret; |
| 2190 | } | 2194 | } |
| 2191 | 2195 | ||
| 2192 | static char *looking_function_name; | 2196 | static int find_probe_functions(struct map *map, char *name) |
| 2193 | static int num_matched_functions; | ||
| 2194 | |||
| 2195 | static int probe_function_filter(struct map *map __maybe_unused, | ||
| 2196 | struct symbol *sym) | ||
| 2197 | { | 2197 | { |
| 2198 | if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && | 2198 | int found = 0; |
| 2199 | strcmp(looking_function_name, sym->name) == 0) { | 2199 | struct symbol *sym; |
| 2200 | num_matched_functions++; | 2200 | |
| 2201 | return 0; | 2201 | map__for_each_symbol_by_name(map, name, sym) { |
| 2202 | if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) | ||
| 2203 | found++; | ||
| 2202 | } | 2204 | } |
| 2203 | return 1; | 2205 | |
| 2206 | return found; | ||
| 2204 | } | 2207 | } |
| 2205 | 2208 | ||
| 2206 | #define strdup_or_goto(str, label) \ | 2209 | #define strdup_or_goto(str, label) \ |
| @@ -2218,10 +2221,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
| 2218 | struct kmap *kmap = NULL; | 2221 | struct kmap *kmap = NULL; |
| 2219 | struct ref_reloc_sym *reloc_sym = NULL; | 2222 | struct ref_reloc_sym *reloc_sym = NULL; |
| 2220 | struct symbol *sym; | 2223 | struct symbol *sym; |
| 2221 | struct rb_node *nd; | ||
| 2222 | struct probe_trace_event *tev; | 2224 | struct probe_trace_event *tev; |
| 2223 | struct perf_probe_point *pp = &pev->point; | 2225 | struct perf_probe_point *pp = &pev->point; |
| 2224 | struct probe_trace_point *tp; | 2226 | struct probe_trace_point *tp; |
| 2227 | int num_matched_functions; | ||
| 2225 | int ret, i; | 2228 | int ret, i; |
| 2226 | 2229 | ||
| 2227 | /* Init maps of given executable or kernel */ | 2230 | /* Init maps of given executable or kernel */ |
| @@ -2238,10 +2241,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
| 2238 | * Load matched symbols: Since the different local symbols may have | 2241 | * Load matched symbols: Since the different local symbols may have |
| 2239 | * same name but different addresses, this lists all the symbols. | 2242 | * same name but different addresses, this lists all the symbols. |
| 2240 | */ | 2243 | */ |
| 2241 | num_matched_functions = 0; | 2244 | num_matched_functions = find_probe_functions(map, pp->function); |
| 2242 | looking_function_name = pp->function; | 2245 | if (num_matched_functions == 0) { |
| 2243 | ret = map__load(map, probe_function_filter); | ||
| 2244 | if (ret || num_matched_functions == 0) { | ||
| 2245 | pr_err("Failed to find symbol %s in %s\n", pp->function, | 2246 | pr_err("Failed to find symbol %s in %s\n", pp->function, |
| 2246 | target ? : "kernel"); | 2247 | target ? : "kernel"); |
| 2247 | ret = -ENOENT; | 2248 | ret = -ENOENT; |
| @@ -2253,7 +2254,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
| 2253 | goto out; | 2254 | goto out; |
| 2254 | } | 2255 | } |
| 2255 | 2256 | ||
| 2256 | if (!pev->uprobes) { | 2257 | if (!pev->uprobes && !pp->retprobe) { |
| 2257 | kmap = map__kmap(map); | 2258 | kmap = map__kmap(map); |
| 2258 | reloc_sym = kmap->ref_reloc_sym; | 2259 | reloc_sym = kmap->ref_reloc_sym; |
| 2259 | if (!reloc_sym) { | 2260 | if (!reloc_sym) { |
| @@ -2271,7 +2272,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
| 2271 | } | 2272 | } |
| 2272 | 2273 | ||
| 2273 | ret = 0; | 2274 | ret = 0; |
| 2274 | map__for_each_symbol(map, sym, nd) { | 2275 | |
| 2276 | map__for_each_symbol_by_name(map, pp->function, sym) { | ||
| 2275 | tev = (*tevs) + ret; | 2277 | tev = (*tevs) + ret; |
| 2276 | tp = &tev->point; | 2278 | tp = &tev->point; |
| 2277 | if (ret == num_matched_functions) { | 2279 | if (ret == num_matched_functions) { |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index c7918f83b300..b5247d777f0e 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -989,8 +989,24 @@ static int debuginfo__find_probes(struct debuginfo *dbg, | |||
| 989 | int ret = 0; | 989 | int ret = 0; |
| 990 | 990 | ||
| 991 | #if _ELFUTILS_PREREQ(0, 142) | 991 | #if _ELFUTILS_PREREQ(0, 142) |
| 992 | Elf *elf; | ||
| 993 | GElf_Ehdr ehdr; | ||
| 994 | GElf_Shdr shdr; | ||
| 995 | |||
| 992 | /* Get the call frame information from this dwarf */ | 996 | /* Get the call frame information from this dwarf */ |
| 993 | pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg)); | 997 | elf = dwarf_getelf(dbg->dbg); |
| 998 | if (elf == NULL) | ||
| 999 | return -EINVAL; | ||
| 1000 | |||
| 1001 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
| 1002 | return -EINVAL; | ||
| 1003 | |||
| 1004 | if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) && | ||
| 1005 | shdr.sh_type == SHT_PROGBITS) { | ||
| 1006 | pf->cfi = dwarf_getcfi_elf(elf); | ||
| 1007 | } else { | ||
| 1008 | pf->cfi = dwarf_getcfi(dbg->dbg); | ||
| 1009 | } | ||
| 994 | #endif | 1010 | #endif |
| 995 | 1011 | ||
| 996 | off = 0; | 1012 | off = 0; |
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 16a475a7d492..6c6a6953fa93 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources | |||
| @@ -10,7 +10,7 @@ util/ctype.c | |||
| 10 | util/evlist.c | 10 | util/evlist.c |
| 11 | util/evsel.c | 11 | util/evsel.c |
| 12 | util/cpumap.c | 12 | util/cpumap.c |
| 13 | util/hweight.c | 13 | ../../lib/hweight.c |
| 14 | util/thread_map.c | 14 | util/thread_map.c |
| 15 | util/util.c | 15 | util/util.c |
| 16 | util/xyarray.c | 16 | util/xyarray.c |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index c24c5b83156c..a194702a0a2f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -396,6 +396,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, | |||
| 396 | const char *name) | 396 | const char *name) |
| 397 | { | 397 | { |
| 398 | struct rb_node *n; | 398 | struct rb_node *n; |
| 399 | struct symbol_name_rb_node *s; | ||
| 399 | 400 | ||
| 400 | if (symbols == NULL) | 401 | if (symbols == NULL) |
| 401 | return NULL; | 402 | return NULL; |
| @@ -403,7 +404,6 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, | |||
| 403 | n = symbols->rb_node; | 404 | n = symbols->rb_node; |
| 404 | 405 | ||
| 405 | while (n) { | 406 | while (n) { |
| 406 | struct symbol_name_rb_node *s; | ||
| 407 | int cmp; | 407 | int cmp; |
| 408 | 408 | ||
| 409 | s = rb_entry(n, struct symbol_name_rb_node, rb_node); | 409 | s = rb_entry(n, struct symbol_name_rb_node, rb_node); |
| @@ -414,10 +414,24 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, | |||
| 414 | else if (cmp > 0) | 414 | else if (cmp > 0) |
| 415 | n = n->rb_right; | 415 | n = n->rb_right; |
| 416 | else | 416 | else |
| 417 | return &s->sym; | 417 | break; |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | return NULL; | 420 | if (n == NULL) |
| 421 | return NULL; | ||
| 422 | |||
| 423 | /* return first symbol that has same name (if any) */ | ||
| 424 | for (n = rb_prev(n); n; n = rb_prev(n)) { | ||
| 425 | struct symbol_name_rb_node *tmp; | ||
| 426 | |||
| 427 | tmp = rb_entry(n, struct symbol_name_rb_node, rb_node); | ||
| 428 | if (strcmp(tmp->sym.name, s->sym.name)) | ||
| 429 | break; | ||
| 430 | |||
| 431 | s = tmp; | ||
| 432 | } | ||
| 433 | |||
| 434 | return &s->sym; | ||
| 421 | } | 435 | } |
| 422 | 436 | ||
| 423 | struct symbol *dso__find_symbol(struct dso *dso, | 437 | struct symbol *dso__find_symbol(struct dso *dso, |
| @@ -436,6 +450,17 @@ struct symbol *dso__next_symbol(struct symbol *sym) | |||
| 436 | return symbols__next(sym); | 450 | return symbols__next(sym); |
| 437 | } | 451 | } |
| 438 | 452 | ||
| 453 | struct symbol *symbol__next_by_name(struct symbol *sym) | ||
| 454 | { | ||
| 455 | struct symbol_name_rb_node *s = container_of(sym, struct symbol_name_rb_node, sym); | ||
| 456 | struct rb_node *n = rb_next(&s->rb_node); | ||
| 457 | |||
| 458 | return n ? &rb_entry(n, struct symbol_name_rb_node, rb_node)->sym : NULL; | ||
| 459 | } | ||
| 460 | |||
| 461 | /* | ||
| 462 | * Teturns first symbol that matched with @name. | ||
| 463 | */ | ||
| 439 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 464 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
| 440 | const char *name) | 465 | const char *name) |
| 441 | { | 466 | { |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 9d602e9c6f59..1650dcb3a67b 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -231,6 +231,7 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, | |||
| 231 | u64 addr); | 231 | u64 addr); |
| 232 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 232 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
| 233 | const char *name); | 233 | const char *name); |
| 234 | struct symbol *symbol__next_by_name(struct symbol *sym); | ||
| 234 | 235 | ||
| 235 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); | 236 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); |
| 236 | struct symbol *dso__next_symbol(struct symbol *sym); | 237 | struct symbol *dso__next_symbol(struct symbol *sym); |
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 371219a6daf1..6edf535f65c2 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
| @@ -185,6 +185,28 @@ static u64 elf_section_offset(int fd, const char *name) | |||
| 185 | return offset; | 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 | struct table_entry { | 210 | struct table_entry { |
| 189 | u32 start_ip_offset; | 211 | u32 start_ip_offset; |
| 190 | u32 fde_offset; | 212 | u32 fde_offset; |
| @@ -322,8 +344,12 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | |||
| 322 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | 344 | #ifndef NO_LIBUNWIND_DEBUG_FRAME |
| 323 | /* Check the .debug_frame section for unwinding info */ | 345 | /* Check the .debug_frame section for unwinding info */ |
| 324 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | 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 | memset(&di, 0, sizeof(di)); | 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 | map->start, map->end)) | 353 | map->start, map->end)) |
| 328 | return dwarf_search_unwind_table(as, ip, &di, pi, | 354 | return dwarf_search_unwind_table(as, ip, &di, pi, |
| 329 | need_unwind_info, arg); | 355 | need_unwind_info, arg); |
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c index 7cdcf88659c7..9ea914378985 100644 --- a/tools/power/cpupower/utils/cpupower.c +++ b/tools/power/cpupower/utils/cpupower.c | |||
| @@ -199,7 +199,7 @@ int main(int argc, const char *argv[]) | |||
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | get_cpu_info(0, &cpupower_cpu_info); | 201 | get_cpu_info(0, &cpupower_cpu_info); |
| 202 | run_as_root = !getuid(); | 202 | run_as_root = !geteuid(); |
| 203 | if (run_as_root) { | 203 | if (run_as_root) { |
| 204 | ret = uname(&uts); | 204 | ret = uname(&uts); |
| 205 | if (!ret && !strcmp(uts.machine, "x86_64") && | 205 | if (!ret && !strcmp(uts.machine, "x86_64") && |
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c index 09afe5d87f2b..4e8fe2c7b054 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.c +++ b/tools/power/cpupower/utils/helpers/sysfs.c | |||
| @@ -361,7 +361,7 @@ unsigned int sysfs_get_idlestate_count(unsigned int cpu) | |||
| 361 | 361 | ||
| 362 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); | 362 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); |
| 363 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) | 363 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) |
| 364 | return -ENODEV; | 364 | return 0; |
| 365 | 365 | ||
| 366 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); | 366 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); |
| 367 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) | 367 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) |
diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c index 33a5c06d95ca..e238c9559caf 100644 --- a/tools/testing/selftests/exec/execveat.c +++ b/tools/testing/selftests/exec/execveat.c | |||
| @@ -62,7 +62,7 @@ static int _check_execveat_fail(int fd, const char *path, int flags, | |||
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static int check_execveat_invoked_rc(int fd, const char *path, int flags, | 64 | static int check_execveat_invoked_rc(int fd, const char *path, int flags, |
| 65 | int expected_rc) | 65 | int expected_rc, int expected_rc2) |
| 66 | { | 66 | { |
| 67 | int status; | 67 | int status; |
| 68 | int rc; | 68 | int rc; |
| @@ -98,9 +98,10 @@ static int check_execveat_invoked_rc(int fd, const char *path, int flags, | |||
| 98 | child, status); | 98 | child, status); |
| 99 | return 1; | 99 | return 1; |
| 100 | } | 100 | } |
| 101 | if (WEXITSTATUS(status) != expected_rc) { | 101 | if ((WEXITSTATUS(status) != expected_rc) && |
| 102 | printf("[FAIL] (child %d exited with %d not %d)\n", | 102 | (WEXITSTATUS(status) != expected_rc2)) { |
| 103 | child, WEXITSTATUS(status), expected_rc); | 103 | printf("[FAIL] (child %d exited with %d not %d nor %d)\n", |
| 104 | child, WEXITSTATUS(status), expected_rc, expected_rc2); | ||
| 104 | return 1; | 105 | return 1; |
| 105 | } | 106 | } |
| 106 | printf("[OK]\n"); | 107 | printf("[OK]\n"); |
| @@ -109,7 +110,7 @@ static int check_execveat_invoked_rc(int fd, const char *path, int flags, | |||
| 109 | 110 | ||
| 110 | static int check_execveat(int fd, const char *path, int flags) | 111 | static int check_execveat(int fd, const char *path, int flags) |
| 111 | { | 112 | { |
| 112 | return check_execveat_invoked_rc(fd, path, flags, 99); | 113 | return check_execveat_invoked_rc(fd, path, flags, 99, 99); |
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | static char *concat(const char *left, const char *right) | 116 | static char *concat(const char *left, const char *right) |
| @@ -179,11 +180,11 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) | |||
| 179 | */ | 180 | */ |
| 180 | fd = open(longpath, O_RDONLY); | 181 | fd = open(longpath, O_RDONLY); |
| 181 | if (fd > 0) { | 182 | if (fd > 0) { |
| 182 | printf("Invoke copy of '%s' via filename of length %lu:\n", | 183 | printf("Invoke copy of '%s' via filename of length %zu:\n", |
| 183 | src, strlen(longpath)); | 184 | src, strlen(longpath)); |
| 184 | fail += check_execveat(fd, "", AT_EMPTY_PATH); | 185 | fail += check_execveat(fd, "", AT_EMPTY_PATH); |
| 185 | } else { | 186 | } else { |
| 186 | printf("Failed to open length %lu filename, errno=%d (%s)\n", | 187 | printf("Failed to open length %zu filename, errno=%d (%s)\n", |
| 187 | strlen(longpath), errno, strerror(errno)); | 188 | strlen(longpath), errno, strerror(errno)); |
| 188 | fail++; | 189 | fail++; |
| 189 | } | 190 | } |
| @@ -192,9 +193,15 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) | |||
| 192 | * Execute as a long pathname relative to ".". If this is a script, | 193 | * Execute as a long pathname relative to ".". If this is a script, |
| 193 | * the interpreter will launch but fail to open the script because its | 194 | * the interpreter will launch but fail to open the script because its |
| 194 | * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX. | 195 | * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX. |
| 196 | * | ||
| 197 | * The failure code is usually 127 (POSIX: "If a command is not found, | ||
| 198 | * the exit status shall be 127."), but some systems give 126 (POSIX: | ||
| 199 | * "If the command name is found, but it is not an executable utility, | ||
| 200 | * the exit status shall be 126."), so allow either. | ||
| 195 | */ | 201 | */ |
| 196 | if (is_script) | 202 | if (is_script) |
| 197 | fail += check_execveat_invoked_rc(dot_dfd, longpath, 0, 127); | 203 | fail += check_execveat_invoked_rc(dot_dfd, longpath, 0, |
| 204 | 127, 126); | ||
| 198 | else | 205 | else |
| 199 | fail += check_execveat(dot_dfd, longpath, 0); | 206 | fail += check_execveat(dot_dfd, longpath, 0); |
| 200 | 207 | ||
diff --git a/tools/testing/selftests/mqueue/mq_perf_tests.c b/tools/testing/selftests/mqueue/mq_perf_tests.c index 94dae65eea41..8519e9ee97e3 100644 --- a/tools/testing/selftests/mqueue/mq_perf_tests.c +++ b/tools/testing/selftests/mqueue/mq_perf_tests.c | |||
| @@ -536,10 +536,9 @@ int main(int argc, char *argv[]) | |||
| 536 | { | 536 | { |
| 537 | struct mq_attr attr; | 537 | struct mq_attr attr; |
| 538 | char *option, *next_option; | 538 | char *option, *next_option; |
| 539 | int i, cpu; | 539 | int i, cpu, rc; |
| 540 | struct sigaction sa; | 540 | struct sigaction sa; |
| 541 | poptContext popt_context; | 541 | poptContext popt_context; |
| 542 | char rc; | ||
| 543 | void *retval; | 542 | void *retval; |
| 544 | 543 | ||
| 545 | main_thread = pthread_self(); | 544 | main_thread = pthread_self(); |
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index 4c4b1f631ecf..077828c889f1 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile | |||
| @@ -7,7 +7,7 @@ BINARIES += transhuge-stress | |||
| 7 | 7 | ||
| 8 | all: $(BINARIES) | 8 | all: $(BINARIES) |
| 9 | %: %.c | 9 | %: %.c |
| 10 | $(CC) $(CFLAGS) -o $@ $^ | 10 | $(CC) $(CFLAGS) -o $@ $^ -lrt |
| 11 | 11 | ||
| 12 | run_tests: all | 12 | run_tests: all |
| 13 | @/bin/sh ./run_vmtests || (echo "vmtests: [FAIL]"; exit 1) | 13 | @/bin/sh ./run_vmtests || (echo "vmtests: [FAIL]"; exit 1) |
