Commit 59b2858f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
 "Mostly tooling fixes, but also two PMU driver fixes"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf tools powerpc: Use dwfl_report_elf() instead of offline.
  perf tools: Fix segfault for symbol annotation on TUI
  perf test: Fix dwarf unwind using libunwind.
  perf tools: Avoid build splat for syscall numbers with uclibc
  perf tools: Elide strlcpy warning with uclibc
  perf tools: Fix statfs.f_type data type mismatch build error with uclibc
  tools: Remove bitops/hweight usage of bits in tools/perf
  perf machine: Fix __machine__findnew_thread() error path
  perf tools: Fix building error in x86_64 when dwarf unwind is on
  perf probe: Propagate error code when write(2) failed
  perf/x86/intel: Fix bug for "cycles:p" and "cycles:pp" on SLM
  perf/rapl: Fix sysfs_show() initialization for RAPL PMU
parents fc7f0dd3 d01de238
...@@ -568,8 +568,8 @@ struct event_constraint intel_atom_pebs_event_constraints[] = { ...@@ -568,8 +568,8 @@ struct event_constraint intel_atom_pebs_event_constraints[] = {
}; };
struct event_constraint intel_slm_pebs_event_constraints[] = { struct event_constraint intel_slm_pebs_event_constraints[] = {
/* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x1),
/* Allow all events as PEBS with no flags */ /* Allow all events as PEBS with no flags */
INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
EVENT_CONSTRAINT_END EVENT_CONSTRAINT_END
......
...@@ -103,6 +103,13 @@ static struct kobj_attribute format_attr_##_var = \ ...@@ -103,6 +103,13 @@ static struct kobj_attribute format_attr_##_var = \
#define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */ #define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */
#define RAPL_EVENT_ATTR_STR(_name, v, str) \
static struct perf_pmu_events_attr event_attr_##v = { \
.attr = __ATTR(_name, 0444, rapl_sysfs_show, NULL), \
.id = 0, \
.event_str = str, \
};
struct rapl_pmu { struct rapl_pmu {
spinlock_t lock; spinlock_t lock;
int hw_unit; /* 1/2^hw_unit Joule */ int hw_unit; /* 1/2^hw_unit Joule */
...@@ -379,23 +386,36 @@ static struct attribute_group rapl_pmu_attr_group = { ...@@ -379,23 +386,36 @@ static struct attribute_group rapl_pmu_attr_group = {
.attrs = rapl_pmu_attrs, .attrs = rapl_pmu_attrs,
}; };
EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01"); static ssize_t rapl_sysfs_show(struct device *dev,
EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02"); struct device_attribute *attr,
EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03"); char *page)
EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04"); {
struct perf_pmu_events_attr *pmu_attr = \
container_of(attr, struct perf_pmu_events_attr, attr);
if (pmu_attr->event_str)
return sprintf(page, "%s", pmu_attr->event_str);
return 0;
}
RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02");
RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03");
RAPL_EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04");
EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules"); RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules"); RAPL_EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules");
EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules"); RAPL_EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules");
EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules"); RAPL_EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules");
/* /*
* we compute in 0.23 nJ increments regardless of MSR * we compute in 0.23 nJ increments regardless of MSR
*/ */
EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10"); RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10"); RAPL_EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10");
EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10"); RAPL_EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10");
EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10"); RAPL_EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10");
static struct attribute *rapl_events_srv_attr[] = { static struct attribute *rapl_events_srv_attr[] = {
EVENT_PTR(rapl_cores), EVENT_PTR(rapl_cores),
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#error only <linux/bitops.h> can be included directly #error only <linux/bitops.h> can be included directly
#endif #endif
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/atomic.h> #include <asm-generic/bitops/atomic.h>
#endif /* __TOOLS_ASM_GENERIC_BITOPS_H */ #endif /* __TOOLS_ASM_GENERIC_BITOPS_H */
#include "../../../../include/asm-generic/bitops/arch_hweight.h"
#include "../../../../include/asm-generic/bitops/const_hweight.h"
#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_ */
#ifndef _TOOLS_LINUX_BITOPS_H_ #ifndef _TOOLS_LINUX_BITOPS_H_
#define _TOOLS_LINUX_BITOPS_H_ #define _TOOLS_LINUX_BITOPS_H_
#include <asm/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <asm/hweight.h>
#ifndef __WORDSIZE #ifndef __WORDSIZE
#define __WORDSIZE (__SIZEOF_LONG__ * 8) #define __WORDSIZE (__SIZEOF_LONG__ * 8)
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) #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) #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 * Include this here because some architectures need generic_ffs/fls in
* scope * scope
......
...@@ -67,7 +67,7 @@ int debugfs_valid_mountpoint(const char *debugfs) ...@@ -67,7 +67,7 @@ int debugfs_valid_mountpoint(const char *debugfs)
if (statfs(debugfs, &st_fs) < 0) if (statfs(debugfs, &st_fs) < 0)
return -ENOENT; return -ENOENT;
else if (st_fs.f_type != (long) DEBUGFS_MAGIC) else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC)
return -ENOENT; return -ENOENT;
return 0; return 0;
......
...@@ -79,7 +79,7 @@ static int fs__valid_mount(const char *fs, long magic) ...@@ -79,7 +79,7 @@ static int fs__valid_mount(const char *fs, long magic)
if (statfs(fs, &st_fs) < 0) if (statfs(fs, &st_fs) < 0)
return -ENOENT; return -ENOENT;
else if (st_fs.f_type != magic) else if ((long)st_fs.f_type != magic)
return -ENOENT; return -ENOENT;
return 0; return 0;
......
...@@ -6,12 +6,15 @@ tools/lib/symbol/kallsyms.c ...@@ -6,12 +6,15 @@ tools/lib/symbol/kallsyms.c
tools/lib/symbol/kallsyms.h tools/lib/symbol/kallsyms.h
tools/lib/util/find_next_bit.c tools/lib/util/find_next_bit.c
tools/include/asm/bug.h 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/atomic.h
tools/include/asm-generic/bitops/const_hweight.h
tools/include/asm-generic/bitops/__ffs.h tools/include/asm-generic/bitops/__ffs.h
tools/include/asm-generic/bitops/__fls.h tools/include/asm-generic/bitops/__fls.h
tools/include/asm-generic/bitops/find.h tools/include/asm-generic/bitops/find.h
tools/include/asm-generic/bitops/fls64.h tools/include/asm-generic/bitops/fls64.h
tools/include/asm-generic/bitops/fls.h tools/include/asm-generic/bitops/fls.h
tools/include/asm-generic/bitops/hweight.h
tools/include/asm-generic/bitops.h tools/include/asm-generic/bitops.h
tools/include/linux/bitops.h tools/include/linux/bitops.h
tools/include/linux/compiler.h tools/include/linux/compiler.h
...@@ -19,6 +22,8 @@ tools/include/linux/export.h ...@@ -19,6 +22,8 @@ tools/include/linux/export.h
tools/include/linux/hash.h tools/include/linux/hash.h
tools/include/linux/log2.h tools/include/linux/log2.h
tools/include/linux/types.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/fls64.h
include/asm-generic/bitops/__fls.h include/asm-generic/bitops/__fls.h
include/asm-generic/bitops/fls.h include/asm-generic/bitops/fls.h
...@@ -29,6 +34,7 @@ include/linux/list.h ...@@ -29,6 +34,7 @@ include/linux/list.h
include/linux/hash.h include/linux/hash.h
include/linux/stringify.h include/linux/stringify.h
lib/find_next_bit.c lib/find_next_bit.c
lib/hweight.c
lib/rbtree.c lib/rbtree.c
include/linux/swab.h include/linux/swab.h
arch/*/include/asm/unistd*.h arch/*/include/asm/unistd*.h
......
...@@ -232,12 +232,15 @@ LIB_H += ../include/linux/hash.h ...@@ -232,12 +232,15 @@ LIB_H += ../include/linux/hash.h
LIB_H += ../../include/linux/stringify.h LIB_H += ../../include/linux/stringify.h
LIB_H += util/include/linux/bitmap.h LIB_H += util/include/linux/bitmap.h
LIB_H += ../include/linux/bitops.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/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/find.h
LIB_H += ../include/asm-generic/bitops/fls64.h LIB_H += ../include/asm-generic/bitops/fls64.h
LIB_H += ../include/asm-generic/bitops/fls.h LIB_H += ../include/asm-generic/bitops/fls.h
LIB_H += ../include/asm-generic/bitops/__ffs.h LIB_H += ../include/asm-generic/bitops/__ffs.h
LIB_H += ../include/asm-generic/bitops/__fls.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/asm-generic/bitops.h
LIB_H += ../include/linux/compiler.h LIB_H += ../include/linux/compiler.h
LIB_H += ../include/linux/log2.h LIB_H += ../include/linux/log2.h
...@@ -255,7 +258,6 @@ LIB_H += util/include/linux/linkage.h ...@@ -255,7 +258,6 @@ LIB_H += util/include/linux/linkage.h
LIB_H += util/include/asm/asm-offsets.h LIB_H += util/include/asm/asm-offsets.h
LIB_H += ../include/asm/bug.h LIB_H += ../include/asm/bug.h
LIB_H += util/include/asm/byteorder.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/swab.h
LIB_H += util/include/asm/system.h LIB_H += util/include/asm/system.h
LIB_H += util/include/asm/uaccess.h LIB_H += util/include/asm/uaccess.h
...@@ -462,10 +464,12 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o ...@@ -462,10 +464,12 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
# Benchmark modules # Benchmark modules
BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.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-memcpy-x86-64-asm.o
BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
endif endif
endif
BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
...@@ -743,6 +747,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS ...@@ -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 $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< $(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 $(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)"' $< $(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) ...@@ -103,7 +103,7 @@ static Dwarf_Frame *get_eh_frame(Dwfl_Module *mod, Dwarf_Addr pc)
return NULL; return NULL;
} }
result = dwarf_cfi_addrframe(cfi, pc, &frame); result = dwarf_cfi_addrframe(cfi, pc-bias, &frame);
if (result) { if (result) {
pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
return NULL; return NULL;
...@@ -128,7 +128,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc) ...@@ -128,7 +128,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
return NULL; return NULL;
} }
result = dwarf_cfi_addrframe(cfi, pc, &frame); result = dwarf_cfi_addrframe(cfi, pc-bias, &frame);
if (result) { if (result) {
pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
return NULL; return NULL;
...@@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc) ...@@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
* yet used) * yet used)
* -1 in case of errors * -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; int rc = -1;
Dwfl *dwfl; Dwfl *dwfl;
...@@ -155,6 +155,7 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc) ...@@ -155,6 +155,7 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
Dwarf_Addr start = pc; Dwarf_Addr start = pc;
Dwarf_Addr end = pc; Dwarf_Addr end = pc;
bool signalp; bool signalp;
const char *exec_file = dso->long_name;
dwfl = dso->dwfl; dwfl = dso->dwfl;
...@@ -165,8 +166,10 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc) ...@@ -165,8 +166,10 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
return -1; return -1;
} }
if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) { mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1,
pr_debug("dwfl_report_offline() failed %s\n", map_start, false);
if (!mod) {
pr_debug("dwfl_report_elf() failed %s\n",
dwarf_errmsg(-1)); dwarf_errmsg(-1));
/* /*
* We normally cache the DWARF debug info and never * 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,10 +259,10 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
return skip_slot; 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", pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n",
dso->long_name, chain->nr, ip, rc); dso->long_name, al.sym->name, ip, rc);
if (rc == 0) { if (rc == 0) {
/* /*
......
...@@ -19,12 +19,12 @@ ...@@ -19,12 +19,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <linux/unistd.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/syscall.h>
#include <pthread.h> #include <pthread.h>
......
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
#include <sys/utsname.h> #include <sys/utsname.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <linux/unistd.h>
#include <linux/types.h> #include <linux/types.h>
static volatile int done; static volatile int done;
......
...@@ -20,7 +20,7 @@ NO_PERF_REGS := 1 ...@@ -20,7 +20,7 @@ NO_PERF_REGS := 1
# Additional ARCH settings for x86 # Additional ARCH settings for x86
ifeq ($(ARCH),x86) ifeq ($(ARCH),x86)
ifeq (${IS_X86_64}, 1) ifeq (${IS_64_BIT}, 1)
CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
......
uname_M := $(shell uname -m 2>/dev/null || echo not) 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/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ -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,23 +9,23 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/tile.*/tile/ ) -e s/tile.*/tile/ )
# Additional ARCH settings for x86 # Additional ARCH settings for x86
ifeq ($(ARCH),i386) ifeq ($(RAW_ARCH),i386)
override ARCH := x86 ARCH ?= x86
endif endif
ifeq ($(ARCH),x86_64) ifeq ($(RAW_ARCH),x86_64)
override ARCH := x86 ARCH ?= x86
IS_X86_64 := 0
ifeq (, $(findstring m32,$(CFLAGS))) ifneq (, $(findstring m32,$(CFLAGS)))
IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) RAW_ARCH := x86_32
RAW_ARCH := x86_64
endif endif
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 IS_64_BIT := 1
else ifeq ($(ARCH),x86)
IS_64_BIT := 0
else else
IS_64_BIT := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) IS_64_BIT := 0
endif endif
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <sys/syscall.h> #include <sys/syscall.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <asm/unistd.h>
#if defined(__i386__) #if defined(__i386__)
#define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") #define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
#include "thread.h" #include "thread.h"
#include "callchain.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, static int mmap_handler(struct perf_tool *tool __maybe_unused,
union perf_event *event, union perf_event *event,
struct perf_sample *sample __maybe_unused, struct perf_sample *sample __maybe_unused,
...@@ -28,7 +31,7 @@ static int init_live_machine(struct machine *machine) ...@@ -28,7 +31,7 @@ static int init_live_machine(struct machine *machine)
mmap_handler, machine, true); mmap_handler, machine, true);
} }
#define MAX_STACK 6 #define MAX_STACK 8
static int unwind_entry(struct unwind_entry *entry, void *arg) static int unwind_entry(struct unwind_entry *entry, void *arg)
{ {
...@@ -37,6 +40,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] = { static const char *funcs[MAX_STACK] = {
"test__arch_unwind_sample", "test__arch_unwind_sample",
"unwind_thread", "unwind_thread",
"compare",
"bsearch",
"krava_3", "krava_3",
"krava_2", "krava_2",
"krava_1", "krava_1",
...@@ -88,10 +93,37 @@ static int unwind_thread(struct thread *thread) ...@@ -88,10 +93,37 @@ static int unwind_thread(struct thread *thread)
return err; 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)) __attribute__ ((noinline))
static int krava_3(struct thread *thread) 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)) __attribute__ ((noinline))
......
...@@ -116,11 +116,6 @@ struct annotation { ...@@ -116,11 +116,6 @@ struct annotation {
struct annotated_source *src; struct annotated_source *src;
}; };
struct sannotation {
struct annotation annotation;
struct symbol symbol;
};
static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
{ {
return (((void *)&notes->src->histograms) + return (((void *)&notes->src->histograms) +
...@@ -129,8 +124,7 @@ static inline struct sym_hist *annotation__histogram(struct annotation *notes, i ...@@ -129,8 +124,7 @@ static inline struct sym_hist *annotation__histogram(struct annotation *notes, i
static inline struct annotation *symbol__annotation(struct symbol *sym) static inline struct annotation *symbol__annotation(struct symbol *sym)
{ {
struct sannotation *a = container_of(sym, struct sannotation, symbol); return (void *)sym - symbol_conf.priv_size;
return &a->annotation;
} }
int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); 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 ...@@ -71,7 +71,9 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
extern char *perf_pathdup(const char *fmt, ...) extern char *perf_pathdup(const char *fmt, ...)
__attribute__((format (printf, 1, 2))); __attribute__((format (printf, 1, 2)));
#ifndef __UCLIBC__
/* Matches the libc/libbsd function attribute so we declare this unconditionally: */ /* Matches the libc/libbsd function attribute so we declare this unconditionally: */
extern size_t strlcpy(char *dest, const char *src, size_t size); extern size_t strlcpy(char *dest, const char *src, size_t size);
#endif
#endif /* __PERF_CACHE_H */ #endif /* __PERF_CACHE_H */
#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
}
#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, ...@@ -389,7 +389,6 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
if (th != NULL) { if (th != NULL) {
rb_link_node(&th->rb_node, parent, p); rb_link_node(&th->rb_node, parent, p);
rb_insert_color(&th->rb_node, &machine->threads); rb_insert_color(&th->rb_node, &machine->threads);
machine->last_match = th;
/* /*
* We have to initialize map_groups separately * We have to initialize map_groups separately
...@@ -400,9 +399,12 @@ static struct thread *__machine__findnew_thread(struct machine *machine, ...@@ -400,9 +399,12 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
* leader and that would screwed the rb tree. * leader and that would screwed the rb tree.
*/ */
if (thread__init_map_groups(th, machine)) { if (thread__init_map_groups(th, machine)) {
rb_erase(&th->rb_node, &machine->threads);
thread__delete(th); thread__delete(th);
return NULL; return NULL;
} }
machine->last_match = th;
} }
return th; return th;
......
...@@ -2052,9 +2052,11 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev) ...@@ -2052,9 +2052,11 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
pr_debug("Writing event: %s\n", buf); pr_debug("Writing event: %s\n", buf);
if (!probe_event_dry_run) { if (!probe_event_dry_run) {
ret = write(fd, buf, strlen(buf)); ret = write(fd, buf, strlen(buf));
if (ret <= 0) if (ret <= 0) {
ret = -errno;
pr_warning("Failed to write event: %s\n", pr_warning("Failed to write event: %s\n",
strerror_r(errno, sbuf, sizeof(sbuf))); strerror_r(errno, sbuf, sizeof(sbuf)));
}
} }
free(buf); free(buf);
return ret; return ret;
......
...@@ -10,7 +10,7 @@ util/ctype.c ...@@ -10,7 +10,7 @@ util/ctype.c
util/evlist.c util/evlist.c
util/evsel.c util/evsel.c
util/cpumap.c util/cpumap.c
util/hweight.c ../../lib/hweight.c
util/thread_map.c util/thread_map.c
util/util.c util/util.c
util/xyarray.c util/xyarray.c
......
...@@ -185,6 +185,28 @@ static u64 elf_section_offset(int fd, const char *name) ...@@ -185,6 +185,28 @@ static u64 elf_section_offset(int fd, const char *name)
return offset; 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 { struct table_entry {
u32 start_ip_offset; u32 start_ip_offset;
u32 fde_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, ...@@ -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 #ifndef NO_LIBUNWIND_DEBUG_FRAME
/* Check the .debug_frame section for unwinding info */ /* Check the .debug_frame section for unwinding info */
if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { 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)); 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)) map->start, map->end))
return dwarf_search_unwind_table(as, ip, &di, pi, return dwarf_search_unwind_table(as, ip, &di, pi,
need_unwind_info, arg); need_unwind_info, arg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment