perf/urgent fixes:
User visible: - Fix segfault when using both the map symtab viewer and annotation in the TUI (Namhyung Kim). Developer stuff: - 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> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJUuYAMAAoJEBpxZoYYoA7146EH/3VkVgw1PS1DkdA8yn0kOj1T Lus+VDwd6oKiDlPzIaQ7k40RqSnA6hreq6diiZdFpB1Z4eJUGgBK/mfnL40oWxod OR6j44dmk8QaoPMN0Q4/A1Su5gEF7/Gz8ht5EXcbGYlJy+7mGajWq+uGbPYVlh2M hhez88x4gchSGJlT3NPGXgMggKYhcElKgtfrrFmhLIPsN6UC5DEEA9+QRHKqI2iM +8RRFU5BreUglYQ2DYheCl0nUKuiiYnvFdlFNQOi15txID/KgBpevDnxNXunH1eB +/t60Qfz7/viuyKvZ0ZwYsVWixBXhta7x2g7EMv3111ccIJrZUM3gcK4b+hrMTE= =moQI -----END PGP SIGNATURE----- Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/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>
This commit is contained in:
commit
d01de2389c
|
@ -22,6 +22,8 @@
|
|||
#error only <linux/bitops.h> can be included directly
|
||||
#endif
|
||||
|
||||
#include <asm-generic/bitops/hweight.h>
|
||||
|
||||
#include <asm-generic/bitops/atomic.h>
|
||||
|
||||
#endif /* __TOOLS_ASM_GENERIC_BITOPS_H */
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "../../../../include/asm-generic/bitops/arch_hweight.h"
|
|
@ -0,0 +1 @@
|
|||
#include "../../../../include/asm-generic/bitops/const_hweight.h"
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_
|
||||
#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_
|
||||
|
||||
#include <asm-generic/bitops/arch_hweight.h>
|
||||
#include <asm-generic/bitops/const_hweight.h>
|
||||
|
||||
#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ */
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef _TOOLS_LINUX_BITOPS_H_
|
||||
#define _TOOLS_LINUX_BITOPS_H_
|
||||
|
||||
#include <asm/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/hweight.h>
|
||||
|
||||
#ifndef __WORDSIZE
|
||||
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
|
||||
|
@ -19,6 +19,11 @@
|
|||
#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
|
||||
#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
|
||||
|
||||
extern unsigned int __sw_hweight8(unsigned int w);
|
||||
extern unsigned int __sw_hweight16(unsigned int w);
|
||||
extern unsigned int __sw_hweight32(unsigned int w);
|
||||
extern unsigned long __sw_hweight64(__u64 w);
|
||||
|
||||
/*
|
||||
* Include this here because some architectures need generic_ffs/fls in
|
||||
* scope
|
||||
|
|
|
@ -67,7 +67,7 @@ int debugfs_valid_mountpoint(const char *debugfs)
|
|||
|
||||
if (statfs(debugfs, &st_fs) < 0)
|
||||
return -ENOENT;
|
||||
else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
|
||||
else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -79,7 +79,7 @@ static int fs__valid_mount(const char *fs, long magic)
|
|||
|
||||
if (statfs(fs, &st_fs) < 0)
|
||||
return -ENOENT;
|
||||
else if (st_fs.f_type != magic)
|
||||
else if ((long)st_fs.f_type != magic)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -6,12 +6,15 @@ tools/lib/symbol/kallsyms.c
|
|||
tools/lib/symbol/kallsyms.h
|
||||
tools/lib/util/find_next_bit.c
|
||||
tools/include/asm/bug.h
|
||||
tools/include/asm-generic/bitops/arch_hweight.h
|
||||
tools/include/asm-generic/bitops/atomic.h
|
||||
tools/include/asm-generic/bitops/const_hweight.h
|
||||
tools/include/asm-generic/bitops/__ffs.h
|
||||
tools/include/asm-generic/bitops/__fls.h
|
||||
tools/include/asm-generic/bitops/find.h
|
||||
tools/include/asm-generic/bitops/fls64.h
|
||||
tools/include/asm-generic/bitops/fls.h
|
||||
tools/include/asm-generic/bitops/hweight.h
|
||||
tools/include/asm-generic/bitops.h
|
||||
tools/include/linux/bitops.h
|
||||
tools/include/linux/compiler.h
|
||||
|
@ -19,6 +22,8 @@ tools/include/linux/export.h
|
|||
tools/include/linux/hash.h
|
||||
tools/include/linux/log2.h
|
||||
tools/include/linux/types.h
|
||||
include/asm-generic/bitops/arch_hweight.h
|
||||
include/asm-generic/bitops/const_hweight.h
|
||||
include/asm-generic/bitops/fls64.h
|
||||
include/asm-generic/bitops/__fls.h
|
||||
include/asm-generic/bitops/fls.h
|
||||
|
@ -29,6 +34,7 @@ include/linux/list.h
|
|||
include/linux/hash.h
|
||||
include/linux/stringify.h
|
||||
lib/find_next_bit.c
|
||||
lib/hweight.c
|
||||
lib/rbtree.c
|
||||
include/linux/swab.h
|
||||
arch/*/include/asm/unistd*.h
|
||||
|
|
|
@ -232,12 +232,15 @@ LIB_H += ../include/linux/hash.h
|
|||
LIB_H += ../../include/linux/stringify.h
|
||||
LIB_H += util/include/linux/bitmap.h
|
||||
LIB_H += ../include/linux/bitops.h
|
||||
LIB_H += ../include/asm-generic/bitops/arch_hweight.h
|
||||
LIB_H += ../include/asm-generic/bitops/atomic.h
|
||||
LIB_H += ../include/asm-generic/bitops/const_hweight.h
|
||||
LIB_H += ../include/asm-generic/bitops/find.h
|
||||
LIB_H += ../include/asm-generic/bitops/fls64.h
|
||||
LIB_H += ../include/asm-generic/bitops/fls.h
|
||||
LIB_H += ../include/asm-generic/bitops/__ffs.h
|
||||
LIB_H += ../include/asm-generic/bitops/__fls.h
|
||||
LIB_H += ../include/asm-generic/bitops/hweight.h
|
||||
LIB_H += ../include/asm-generic/bitops.h
|
||||
LIB_H += ../include/linux/compiler.h
|
||||
LIB_H += ../include/linux/log2.h
|
||||
|
@ -255,7 +258,6 @@ LIB_H += util/include/linux/linkage.h
|
|||
LIB_H += util/include/asm/asm-offsets.h
|
||||
LIB_H += ../include/asm/bug.h
|
||||
LIB_H += util/include/asm/byteorder.h
|
||||
LIB_H += util/include/asm/hweight.h
|
||||
LIB_H += util/include/asm/swab.h
|
||||
LIB_H += util/include/asm/system.h
|
||||
LIB_H += util/include/asm/uaccess.h
|
||||
|
@ -462,10 +464,12 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
|
|||
# Benchmark modules
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
|
||||
ifeq ($(RAW_ARCH),x86_64)
|
||||
ifeq ($(ARCH), x86)
|
||||
ifeq ($(IS_64_BIT), 1)
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
|
||||
endif
|
||||
endif
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
|
||||
BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
|
||||
|
@ -743,6 +747,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
|
|||
$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ static Dwarf_Frame *get_eh_frame(Dwfl_Module *mod, Dwarf_Addr pc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
result = dwarf_cfi_addrframe(cfi, pc, &frame);
|
||||
result = dwarf_cfi_addrframe(cfi, pc-bias, &frame);
|
||||
if (result) {
|
||||
pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
|
||||
return NULL;
|
||||
|
@ -128,7 +128,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
result = dwarf_cfi_addrframe(cfi, pc, &frame);
|
||||
result = dwarf_cfi_addrframe(cfi, pc-bias, &frame);
|
||||
if (result) {
|
||||
pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
|
||||
return NULL;
|
||||
|
@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
|
|||
* yet used)
|
||||
* -1 in case of errors
|
||||
*/
|
||||
static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
|
||||
static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc)
|
||||
{
|
||||
int rc = -1;
|
||||
Dwfl *dwfl;
|
||||
|
@ -155,6 +155,7 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
|
|||
Dwarf_Addr start = pc;
|
||||
Dwarf_Addr end = pc;
|
||||
bool signalp;
|
||||
const char *exec_file = dso->long_name;
|
||||
|
||||
dwfl = dso->dwfl;
|
||||
|
||||
|
@ -165,8 +166,10 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) {
|
||||
pr_debug("dwfl_report_offline() failed %s\n",
|
||||
mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1,
|
||||
map_start, false);
|
||||
if (!mod) {
|
||||
pr_debug("dwfl_report_elf() failed %s\n",
|
||||
dwarf_errmsg(-1));
|
||||
/*
|
||||
* 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)
|
|||
return skip_slot;
|
||||
}
|
||||
|
||||
rc = check_return_addr(dso, ip);
|
||||
rc = check_return_addr(dso, al.map->start, ip);
|
||||
|
||||
pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n",
|
||||
dso->long_name, chain->nr, ip, rc);
|
||||
pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n",
|
||||
dso->long_name, al.sym->name, ip, rc);
|
||||
|
||||
if (rc == 0) {
|
||||
/*
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include <sys/utsname.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
static volatile int done;
|
||||
|
|
|
@ -20,7 +20,7 @@ NO_PERF_REGS := 1
|
|||
|
||||
# Additional ARCH settings for x86
|
||||
ifeq ($(ARCH),x86)
|
||||
ifeq (${IS_X86_64}, 1)
|
||||
ifeq (${IS_64_BIT}, 1)
|
||||
CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
|
||||
ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
|
||||
LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
uname_M := $(shell uname -m 2>/dev/null || echo not)
|
||||
|
||||
ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
|
||||
RAW_ARCH := $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
|
||||
-e s/arm.*/arm/ -e s/sa110/arm/ \
|
||||
-e s/s390x/s390/ -e s/parisc64/parisc/ \
|
||||
-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/ \
|
|||
-e s/tile.*/tile/ )
|
||||
|
||||
# Additional ARCH settings for x86
|
||||
ifeq ($(ARCH),i386)
|
||||
override ARCH := x86
|
||||
ifeq ($(RAW_ARCH),i386)
|
||||
ARCH ?= x86
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
override ARCH := x86
|
||||
IS_X86_64 := 0
|
||||
ifeq (, $(findstring m32,$(CFLAGS)))
|
||||
IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1)
|
||||
RAW_ARCH := x86_64
|
||||
ifeq ($(RAW_ARCH),x86_64)
|
||||
ARCH ?= x86
|
||||
|
||||
ifneq (, $(findstring m32,$(CFLAGS)))
|
||||
RAW_ARCH := x86_32
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (${IS_X86_64}, 1)
|
||||
ARCH ?= $(RAW_ARCH)
|
||||
|
||||
LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
|
||||
ifeq ($(LP64), 1)
|
||||
IS_64_BIT := 1
|
||||
else ifeq ($(ARCH),x86)
|
||||
IS_64_BIT := 0
|
||||
else
|
||||
IS_64_BIT := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
|
||||
IS_64_BIT := 0
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <sys/syscall.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#if defined(__i386__)
|
||||
#define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include "thread.h"
|
||||
#include "callchain.h"
|
||||
|
||||
/* For bsearch. We try to unwind functions in shared object. */
|
||||
#include <stdlib.h>
|
||||
|
||||
static int mmap_handler(struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
|
@ -28,7 +31,7 @@ static int init_live_machine(struct machine *machine)
|
|||
mmap_handler, machine, true);
|
||||
}
|
||||
|
||||
#define MAX_STACK 6
|
||||
#define MAX_STACK 8
|
||||
|
||||
static int unwind_entry(struct unwind_entry *entry, void *arg)
|
||||
{
|
||||
|
@ -37,6 +40,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
|
|||
static const char *funcs[MAX_STACK] = {
|
||||
"test__arch_unwind_sample",
|
||||
"unwind_thread",
|
||||
"compare",
|
||||
"bsearch",
|
||||
"krava_3",
|
||||
"krava_2",
|
||||
"krava_1",
|
||||
|
@ -88,10 +93,37 @@ static int unwind_thread(struct thread *thread)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int global_unwind_retval = -INT_MAX;
|
||||
|
||||
__attribute__ ((noinline))
|
||||
static int compare(void *p1, void *p2)
|
||||
{
|
||||
/* Any possible value should be 'thread' */
|
||||
struct thread *thread = *(struct thread **)p1;
|
||||
|
||||
if (global_unwind_retval == -INT_MAX)
|
||||
global_unwind_retval = unwind_thread(thread);
|
||||
|
||||
return p1 - p2;
|
||||
}
|
||||
|
||||
__attribute__ ((noinline))
|
||||
static int krava_3(struct thread *thread)
|
||||
{
|
||||
return unwind_thread(thread);
|
||||
struct thread *array[2] = {thread, thread};
|
||||
void *fp = &bsearch;
|
||||
/*
|
||||
* make _bsearch a volatile function pointer to
|
||||
* prevent potential optimization, which may expand
|
||||
* bsearch and call compare directly from this function,
|
||||
* instead of libc shared object.
|
||||
*/
|
||||
void *(*volatile _bsearch)(void *, void *, size_t,
|
||||
size_t, int (*)(void *, void *));
|
||||
|
||||
_bsearch = fp;
|
||||
_bsearch(array, &thread, 2, sizeof(struct thread **), compare);
|
||||
return global_unwind_retval;
|
||||
}
|
||||
|
||||
__attribute__ ((noinline))
|
||||
|
|
|
@ -116,11 +116,6 @@ struct annotation {
|
|||
struct annotated_source *src;
|
||||
};
|
||||
|
||||
struct sannotation {
|
||||
struct annotation annotation;
|
||||
struct symbol symbol;
|
||||
};
|
||||
|
||||
static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
|
||||
{
|
||||
return (((void *)¬es->src->histograms) +
|
||||
|
@ -129,8 +124,7 @@ static inline struct sym_hist *annotation__histogram(struct annotation *notes, i
|
|||
|
||||
static inline struct annotation *symbol__annotation(struct symbol *sym)
|
||||
{
|
||||
struct sannotation *a = container_of(sym, struct sannotation, symbol);
|
||||
return &a->annotation;
|
||||
return (void *)sym - symbol_conf.priv_size;
|
||||
}
|
||||
|
||||
int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx);
|
||||
|
|
|
@ -71,7 +71,9 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
|
|||
extern char *perf_pathdup(const char *fmt, ...)
|
||||
__attribute__((format (printf, 1, 2)));
|
||||
|
||||
#ifndef __UCLIBC__
|
||||
/* Matches the libc/libbsd function attribute so we declare this unconditionally: */
|
||||
extern size_t strlcpy(char *dest, const char *src, size_t size);
|
||||
#endif
|
||||
|
||||
#endif /* __PERF_CACHE_H */
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
#include <linux/bitops.h>
|
||||
|
||||
/**
|
||||
* hweightN - returns the hamming weight of a N-bit word
|
||||
* @x: the word to weigh
|
||||
*
|
||||
* The Hamming Weight of a number is the total number of bits set in it.
|
||||
*/
|
||||
|
||||
unsigned int hweight32(unsigned int w)
|
||||
{
|
||||
unsigned int res = w - ((w >> 1) & 0x55555555);
|
||||
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
||||
res = (res + (res >> 4)) & 0x0F0F0F0F;
|
||||
res = res + (res >> 8);
|
||||
return (res + (res >> 16)) & 0x000000FF;
|
||||
}
|
||||
|
||||
unsigned long hweight64(__u64 w)
|
||||
{
|
||||
#if BITS_PER_LONG == 32
|
||||
return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
|
||||
#elif BITS_PER_LONG == 64
|
||||
__u64 res = w - ((w >> 1) & 0x5555555555555555ul);
|
||||
res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
|
||||
res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
|
||||
res = res + (res >> 8);
|
||||
res = res + (res >> 16);
|
||||
return (res + (res >> 32)) & 0x00000000000000FFul;
|
||||
#endif
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef PERF_HWEIGHT_H
|
||||
#define PERF_HWEIGHT_H
|
||||
|
||||
#include <linux/types.h>
|
||||
unsigned int hweight32(unsigned int w);
|
||||
unsigned long hweight64(__u64 w);
|
||||
|
||||
#endif /* PERF_HWEIGHT_H */
|
|
@ -389,7 +389,6 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
|
|||
if (th != NULL) {
|
||||
rb_link_node(&th->rb_node, parent, p);
|
||||
rb_insert_color(&th->rb_node, &machine->threads);
|
||||
machine->last_match = th;
|
||||
|
||||
/*
|
||||
* We have to initialize map_groups separately
|
||||
|
@ -400,9 +399,12 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
|
|||
* leader and that would screwed the rb tree.
|
||||
*/
|
||||
if (thread__init_map_groups(th, machine)) {
|
||||
rb_erase(&th->rb_node, &machine->threads);
|
||||
thread__delete(th);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
machine->last_match = th;
|
||||
}
|
||||
|
||||
return th;
|
||||
|
|
|
@ -2052,9 +2052,11 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
|
|||
pr_debug("Writing event: %s\n", buf);
|
||||
if (!probe_event_dry_run) {
|
||||
ret = write(fd, buf, strlen(buf));
|
||||
if (ret <= 0)
|
||||
if (ret <= 0) {
|
||||
ret = -errno;
|
||||
pr_warning("Failed to write event: %s\n",
|
||||
strerror_r(errno, sbuf, sizeof(sbuf)));
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return ret;
|
||||
|
|
|
@ -10,7 +10,7 @@ util/ctype.c
|
|||
util/evlist.c
|
||||
util/evsel.c
|
||||
util/cpumap.c
|
||||
util/hweight.c
|
||||
../../lib/hweight.c
|
||||
util/thread_map.c
|
||||
util/util.c
|
||||
util/xyarray.c
|
||||
|
|
|
@ -185,6 +185,28 @@ static u64 elf_section_offset(int fd, const char *name)
|
|||
return offset;
|
||||
}
|
||||
|
||||
#ifndef NO_LIBUNWIND_DEBUG_FRAME
|
||||
static int elf_is_exec(int fd, const char *name)
|
||||
{
|
||||
Elf *elf;
|
||||
GElf_Ehdr ehdr;
|
||||
int retval = 0;
|
||||
|
||||
elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
|
||||
if (elf == NULL)
|
||||
return 0;
|
||||
if (gelf_getehdr(elf, &ehdr) == NULL)
|
||||
goto out;
|
||||
|
||||
retval = (ehdr.e_type == ET_EXEC);
|
||||
|
||||
out:
|
||||
elf_end(elf);
|
||||
pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct table_entry {
|
||||
u32 start_ip_offset;
|
||||
u32 fde_offset;
|
||||
|
@ -322,8 +344,12 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
|
|||
#ifndef NO_LIBUNWIND_DEBUG_FRAME
|
||||
/* Check the .debug_frame section for unwinding info */
|
||||
if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
|
||||
int fd = dso__data_fd(map->dso, ui->machine);
|
||||
int is_exec = elf_is_exec(fd, map->dso->name);
|
||||
unw_word_t base = is_exec ? 0 : map->start;
|
||||
|
||||
memset(&di, 0, sizeof(di));
|
||||
if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name,
|
||||
if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name,
|
||||
map->start, map->end))
|
||||
return dwarf_search_unwind_table(as, ip, &di, pi,
|
||||
need_unwind_info, arg);
|
||||
|
|
Loading…
Reference in New Issue