mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
perf/core improvements and fixes:
Fixes: - Do not show a bogus target address in 'perf annotate' for targetless powerpc jump instructions such as 'bctr' (Ravi Bangoria) - tools/build fixes related to race conditions with the fixdep utility (Jiri Olsa) - Fix building objtool with clang (Peter Foley) Infrastructure: - Support linking perf with clang and LLVM libraries, initially statically, but this limitation will be lifted and shared libraries, when available, will be preferred to the static build, that should, as with other features, be enabled explicitly (Wang Nan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJYRdL0AAoJENZQFvNTUqpAuLwQAK0BFAUhjiaz6IEqnKZYs3KL BSOUFQ4oOIQcz7PglQQovfpPKBfDiLdkMXQ31ftKwqsQhHTXDCj8hajvJlmf6YKf p4YioJlHU7/jqMM4T5puDjfJdri+ko9s2egoEieOUVs8yBNqIcitaQvYXXO6yDJ/ ddvPNqFiEp9Obdh+Skm+H3dEYzFPBHcCE7VBep54jo0aQB+UwFDnYGWgPxP8Wtio 3Ik+K18OJWK5eulZzlOOHqIgmO3elqRqwFsOfQ6BEGpGz/pAScTJavQUn2+yns2V CZjibLnrHh53fOk0cxwfAP15h45unE3/oPs7U1+l90vWLj0GwTIRewaCBVeem9eK wtCNq24Lk0Cdu6I1ca6tMq05isaBnDDeB9E9sj09sr8YM0NGYPsfEAgZEx3BmGFs RhrwHbmNlmhMIfUsbtd1iZkrmt7tFJrQi9eSzTgSwuagDJyJpwPT72Xdey25s0tB Rjv74dMBAZ/NcJcpEtKIXKVCEkr3JReNMoE1/aMl0tjLO7FJj33x70t4ICP5HmqK FSYUV4c/jZNDISH2vFhOJTdCmmdKZsRJG0ft8bp6HFjhuTWQx1BHU3l42lJbMAIx HE0UqUbWyx4i4GUdBqMTs2dXKOD7YZpXOHxjWVTMNvOnmQCcnnQIa4gkePt10GR4 OKpRcVtiQo4GcrMFx4YV =LkkJ -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo-20161205' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: Fixes: - Do not show a bogus target address in 'perf annotate' for targetless powerpc jump instructions such as 'bctr' (Ravi Bangoria) - Fix tools/build race conditions with the fixdep utility (Jiri Olsa) - Fix building objtool with clang (Peter Foley) Infrastructure changes: - Support linking perf with clang and LLVM libraries, initially statically, but this limitation will be lifted and shared libraries, when available, will be preferred to the static build, that should, as with other features, be enabled explicitly (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
34c4a42791
@ -65,22 +65,22 @@ dep-cmd = $(if $(wildcard $(fixdep)),
|
||||
printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \
|
||||
printf '\# using basic dep data\n\n' >> $(dot-target).cmd; \
|
||||
cat $(depfile) >> $(dot-target).cmd; \
|
||||
printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
|
||||
printf '\n%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
|
||||
|
||||
###
|
||||
# if_changed_dep - execute command if any prerequisite is newer than
|
||||
# target, or command line has changed and update
|
||||
# dependencies in the cmd file
|
||||
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \
|
||||
@set -e; \
|
||||
$(echo-cmd) $(cmd_$(1)) && $(dep-cmd))
|
||||
@set -e; \
|
||||
$(echo-cmd) $(cmd_$(1)) && $(dep-cmd))
|
||||
|
||||
# if_changed - execute command if any prerequisite is newer than
|
||||
# target, or command line has changed
|
||||
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
|
||||
@set -e; \
|
||||
$(echo-cmd) $(cmd_$(1)); \
|
||||
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
|
||||
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
|
||||
@set -e; \
|
||||
$(echo-cmd) $(cmd_$(1)); \
|
||||
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
|
||||
|
||||
###
|
||||
# C flags to be used in rule definitions, includes:
|
||||
@ -89,12 +89,12 @@ if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
|
||||
# - per target C flags
|
||||
# - per object C flags
|
||||
# - BUILD_STR macro to allow '-D"$(variable)"' constructs
|
||||
c_flags_1 = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
|
||||
c_flags_1 = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
|
||||
c_flags_2 = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(c_flags_1))
|
||||
c_flags = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2))
|
||||
cxx_flags = -Wp,-MD,$(depfile),-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj))
|
||||
cxx_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj))
|
||||
|
||||
###
|
||||
## HOSTCC C flags
|
||||
|
||||
host_c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj))
|
||||
host_c_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj))
|
||||
|
@ -27,58 +27,58 @@ endef
|
||||
# the rule that uses them - an example for that is the 'bionic'
|
||||
# feature check. ]
|
||||
#
|
||||
FEATURE_TESTS_BASIC := \
|
||||
backtrace \
|
||||
dwarf \
|
||||
dwarf_getlocations \
|
||||
fortify-source \
|
||||
sync-compare-and-swap \
|
||||
glibc \
|
||||
gtk2 \
|
||||
gtk2-infobar \
|
||||
libaudit \
|
||||
libbfd \
|
||||
libelf \
|
||||
libelf-getphdrnum \
|
||||
libelf-gelf_getnote \
|
||||
libelf-getshdrstrndx \
|
||||
libelf-mmap \
|
||||
libnuma \
|
||||
numa_num_possible_cpus \
|
||||
libperl \
|
||||
libpython \
|
||||
libpython-version \
|
||||
libslang \
|
||||
libcrypto \
|
||||
libunwind \
|
||||
libunwind-x86 \
|
||||
libunwind-x86_64 \
|
||||
libunwind-arm \
|
||||
libunwind-aarch64 \
|
||||
pthread-attr-setaffinity-np \
|
||||
stackprotector-all \
|
||||
timerfd \
|
||||
libdw-dwarf-unwind \
|
||||
zlib \
|
||||
lzma \
|
||||
get_cpuid \
|
||||
bpf \
|
||||
sdt
|
||||
FEATURE_TESTS_BASIC := \
|
||||
backtrace \
|
||||
dwarf \
|
||||
dwarf_getlocations \
|
||||
fortify-source \
|
||||
sync-compare-and-swap \
|
||||
glibc \
|
||||
gtk2 \
|
||||
gtk2-infobar \
|
||||
libaudit \
|
||||
libbfd \
|
||||
libelf \
|
||||
libelf-getphdrnum \
|
||||
libelf-gelf_getnote \
|
||||
libelf-getshdrstrndx \
|
||||
libelf-mmap \
|
||||
libnuma \
|
||||
numa_num_possible_cpus \
|
||||
libperl \
|
||||
libpython \
|
||||
libpython-version \
|
||||
libslang \
|
||||
libcrypto \
|
||||
libunwind \
|
||||
libunwind-x86 \
|
||||
libunwind-x86_64 \
|
||||
libunwind-arm \
|
||||
libunwind-aarch64 \
|
||||
pthread-attr-setaffinity-np \
|
||||
stackprotector-all \
|
||||
timerfd \
|
||||
libdw-dwarf-unwind \
|
||||
zlib \
|
||||
lzma \
|
||||
get_cpuid \
|
||||
bpf \
|
||||
sdt
|
||||
|
||||
# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
|
||||
# of all feature tests
|
||||
FEATURE_TESTS_EXTRA := \
|
||||
bionic \
|
||||
compile-32 \
|
||||
compile-x32 \
|
||||
cplus-demangle \
|
||||
hello \
|
||||
libbabeltrace \
|
||||
liberty \
|
||||
liberty-z \
|
||||
libunwind-debug-frame \
|
||||
libunwind-debug-frame-arm \
|
||||
libunwind-debug-frame-aarch64
|
||||
FEATURE_TESTS_EXTRA := \
|
||||
bionic \
|
||||
compile-32 \
|
||||
compile-x32 \
|
||||
cplus-demangle \
|
||||
hello \
|
||||
libbabeltrace \
|
||||
liberty \
|
||||
liberty-z \
|
||||
libunwind-debug-frame \
|
||||
libunwind-debug-frame-arm \
|
||||
libunwind-debug-frame-aarch64
|
||||
|
||||
FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
|
||||
|
||||
@ -86,26 +86,26 @@ ifeq ($(FEATURE_TESTS),all)
|
||||
FEATURE_TESTS := $(FEATURE_TESTS_BASIC) $(FEATURE_TESTS_EXTRA)
|
||||
endif
|
||||
|
||||
FEATURE_DISPLAY ?= \
|
||||
dwarf \
|
||||
dwarf_getlocations \
|
||||
glibc \
|
||||
gtk2 \
|
||||
libaudit \
|
||||
libbfd \
|
||||
libelf \
|
||||
libnuma \
|
||||
numa_num_possible_cpus \
|
||||
libperl \
|
||||
libpython \
|
||||
libslang \
|
||||
libcrypto \
|
||||
libunwind \
|
||||
libdw-dwarf-unwind \
|
||||
zlib \
|
||||
lzma \
|
||||
get_cpuid \
|
||||
bpf
|
||||
FEATURE_DISPLAY ?= \
|
||||
dwarf \
|
||||
dwarf_getlocations \
|
||||
glibc \
|
||||
gtk2 \
|
||||
libaudit \
|
||||
libbfd \
|
||||
libelf \
|
||||
libnuma \
|
||||
numa_num_possible_cpus \
|
||||
libperl \
|
||||
libpython \
|
||||
libslang \
|
||||
libcrypto \
|
||||
libunwind \
|
||||
libdw-dwarf-unwind \
|
||||
zlib \
|
||||
lzma \
|
||||
get_cpuid \
|
||||
bpf
|
||||
|
||||
# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
|
||||
# If in the future we need per-feature checks/flags for features not
|
||||
|
@ -1,60 +1,61 @@
|
||||
FILES= \
|
||||
test-all.bin \
|
||||
test-backtrace.bin \
|
||||
test-bionic.bin \
|
||||
test-dwarf.bin \
|
||||
test-dwarf_getlocations.bin \
|
||||
test-fortify-source.bin \
|
||||
test-sync-compare-and-swap.bin \
|
||||
test-glibc.bin \
|
||||
test-gtk2.bin \
|
||||
test-gtk2-infobar.bin \
|
||||
test-hello.bin \
|
||||
test-libaudit.bin \
|
||||
test-libbfd.bin \
|
||||
test-liberty.bin \
|
||||
test-liberty-z.bin \
|
||||
test-cplus-demangle.bin \
|
||||
test-libelf.bin \
|
||||
test-libelf-getphdrnum.bin \
|
||||
test-libelf-gelf_getnote.bin \
|
||||
test-libelf-getshdrstrndx.bin \
|
||||
test-libelf-mmap.bin \
|
||||
test-libnuma.bin \
|
||||
test-numa_num_possible_cpus.bin \
|
||||
test-libperl.bin \
|
||||
test-libpython.bin \
|
||||
test-libpython-version.bin \
|
||||
test-libslang.bin \
|
||||
test-libcrypto.bin \
|
||||
test-libunwind.bin \
|
||||
test-libunwind-debug-frame.bin \
|
||||
test-libunwind-x86.bin \
|
||||
test-libunwind-x86_64.bin \
|
||||
test-libunwind-arm.bin \
|
||||
test-libunwind-aarch64.bin \
|
||||
test-libunwind-debug-frame-arm.bin \
|
||||
test-libunwind-debug-frame-aarch64.bin \
|
||||
test-pthread-attr-setaffinity-np.bin \
|
||||
test-stackprotector-all.bin \
|
||||
test-timerfd.bin \
|
||||
test-libdw-dwarf-unwind.bin \
|
||||
test-libbabeltrace.bin \
|
||||
test-compile-32.bin \
|
||||
test-compile-x32.bin \
|
||||
test-zlib.bin \
|
||||
test-lzma.bin \
|
||||
test-bpf.bin \
|
||||
test-get_cpuid.bin \
|
||||
test-sdt.bin \
|
||||
test-cxx.bin \
|
||||
test-jvmti.bin
|
||||
FILES= \
|
||||
test-all.bin \
|
||||
test-backtrace.bin \
|
||||
test-bionic.bin \
|
||||
test-dwarf.bin \
|
||||
test-dwarf_getlocations.bin \
|
||||
test-fortify-source.bin \
|
||||
test-sync-compare-and-swap.bin \
|
||||
test-glibc.bin \
|
||||
test-gtk2.bin \
|
||||
test-gtk2-infobar.bin \
|
||||
test-hello.bin \
|
||||
test-libaudit.bin \
|
||||
test-libbfd.bin \
|
||||
test-liberty.bin \
|
||||
test-liberty-z.bin \
|
||||
test-cplus-demangle.bin \
|
||||
test-libelf.bin \
|
||||
test-libelf-getphdrnum.bin \
|
||||
test-libelf-gelf_getnote.bin \
|
||||
test-libelf-getshdrstrndx.bin \
|
||||
test-libelf-mmap.bin \
|
||||
test-libnuma.bin \
|
||||
test-numa_num_possible_cpus.bin \
|
||||
test-libperl.bin \
|
||||
test-libpython.bin \
|
||||
test-libpython-version.bin \
|
||||
test-libslang.bin \
|
||||
test-libcrypto.bin \
|
||||
test-libunwind.bin \
|
||||
test-libunwind-debug-frame.bin \
|
||||
test-libunwind-x86.bin \
|
||||
test-libunwind-x86_64.bin \
|
||||
test-libunwind-arm.bin \
|
||||
test-libunwind-aarch64.bin \
|
||||
test-libunwind-debug-frame-arm.bin \
|
||||
test-libunwind-debug-frame-aarch64.bin \
|
||||
test-pthread-attr-setaffinity-np.bin \
|
||||
test-stackprotector-all.bin \
|
||||
test-timerfd.bin \
|
||||
test-libdw-dwarf-unwind.bin \
|
||||
test-libbabeltrace.bin \
|
||||
test-compile-32.bin \
|
||||
test-compile-x32.bin \
|
||||
test-zlib.bin \
|
||||
test-lzma.bin \
|
||||
test-bpf.bin \
|
||||
test-get_cpuid.bin \
|
||||
test-sdt.bin \
|
||||
test-cxx.bin \
|
||||
test-jvmti.bin
|
||||
|
||||
FILES := $(addprefix $(OUTPUT),$(FILES))
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc -MD
|
||||
CXX := $(CROSS_COMPILE)g++ -MD
|
||||
PKG_CONFIG := $(CROSS_COMPILE)pkg-config
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
|
||||
all: $(FILES)
|
||||
|
||||
@ -229,6 +230,23 @@ $(OUTPUT)test-cxx.bin:
|
||||
$(OUTPUT)test-jvmti.bin:
|
||||
$(BUILD)
|
||||
|
||||
$(OUTPUT)test-llvm.bin:
|
||||
$(BUILDXX) -std=gnu++11 \
|
||||
-I$(shell $(LLVM_CONFIG) --includedir) \
|
||||
-L$(shell $(LLVM_CONFIG) --libdir) \
|
||||
$(shell $(LLVM_CONFIG) --libs Core BPF) \
|
||||
$(shell $(LLVM_CONFIG) --system-libs)
|
||||
|
||||
$(OUTPUT)test-clang.bin:
|
||||
$(BUILDXX) -std=gnu++11 \
|
||||
-I$(shell $(LLVM_CONFIG) --includedir) \
|
||||
-L$(shell $(LLVM_CONFIG) --libdir) \
|
||||
-Wl,--start-group -lclangBasic -lclangDriver \
|
||||
-lclangFrontend -lclangEdit -lclangLex \
|
||||
-lclangAST -Wl,--end-group \
|
||||
$(shell $(LLVM_CONFIG) --libs Core option) \
|
||||
$(shell $(LLVM_CONFIG) --system-libs)
|
||||
|
||||
-include $(OUTPUT)*.d
|
||||
|
||||
###############################
|
||||
|
21
tools/build/feature/test-clang.cpp
Normal file
21
tools/build/feature/test-clang.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "clang/Basic/VirtualFileSystem.h"
|
||||
#include "clang/Driver/Driver.h"
|
||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::driver;
|
||||
|
||||
int main()
|
||||
{
|
||||
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
|
||||
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
|
||||
|
||||
DiagnosticsEngine Diags(DiagID, &*DiagOpts);
|
||||
Driver TheDriver("test", "bpf-pc-linux", Diags);
|
||||
|
||||
llvm::llvm_shutdown();
|
||||
return 0;
|
||||
}
|
8
tools/build/feature/test-llvm.cpp
Normal file
8
tools/build/feature/test-llvm.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
int main()
|
||||
{
|
||||
llvm::errs() << "Hello World!\n";
|
||||
llvm::llvm_shutdown();
|
||||
return 0;
|
||||
}
|
@ -49,7 +49,7 @@ static void parse_dep_file(void *map, size_t len)
|
||||
char *end = m + len;
|
||||
char *p;
|
||||
char s[PATH_MAX];
|
||||
int is_target;
|
||||
int is_target, has_target = 0;
|
||||
int saw_any_target = 0;
|
||||
int is_first_dep = 0;
|
||||
|
||||
@ -67,7 +67,8 @@ static void parse_dep_file(void *map, size_t len)
|
||||
if (is_target) {
|
||||
/* The /next/ file is the first dependency */
|
||||
is_first_dep = 1;
|
||||
} else {
|
||||
has_target = 1;
|
||||
} else if (has_target) {
|
||||
/* Save this token/filename */
|
||||
memcpy(s, m, p-m);
|
||||
s[p - m] = 0;
|
||||
|
@ -136,6 +136,7 @@ endif
|
||||
# Treat warnings as errors unless directed not to
|
||||
ifneq ($(WERROR),0)
|
||||
CFLAGS += -Werror
|
||||
CXXFLAGS += -Werror
|
||||
endif
|
||||
|
||||
ifndef DEBUG
|
||||
@ -182,6 +183,13 @@ CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -std=gnu99
|
||||
|
||||
CXXFLAGS += -std=gnu++11 -fno-exceptions -fno-rtti
|
||||
CXXFLAGS += -Wall
|
||||
CXXFLAGS += -fno-omit-frame-pointer
|
||||
CXXFLAGS += -ggdb3
|
||||
CXXFLAGS += -funwind-tables
|
||||
CXXFLAGS += -Wno-strict-aliasing
|
||||
|
||||
# Enforce a non-executable stack, as we may regress (again) in the future by
|
||||
# adding assembler files missing the .GNU-stack linker note.
|
||||
LDFLAGS += -Wl,-z,noexecstack
|
||||
@ -204,24 +212,27 @@ ifeq ($(DEBUG),0)
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS += -I$(src-perf)/util/include
|
||||
CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
|
||||
CFLAGS += -I$(srctree)/tools/include/uapi
|
||||
CFLAGS += -I$(srctree)/tools/include/
|
||||
CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
|
||||
CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
|
||||
CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/
|
||||
INC_FLAGS += -I$(src-perf)/util/include
|
||||
INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include
|
||||
INC_FLAGS += -I$(srctree)/tools/include/uapi
|
||||
INC_FLAGS += -I$(srctree)/tools/include/
|
||||
INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
|
||||
INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
|
||||
INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/
|
||||
|
||||
# $(obj-perf) for generated common-cmds.h
|
||||
# $(obj-perf)/util for generated bison/flex headers
|
||||
ifneq ($(OUTPUT),)
|
||||
CFLAGS += -I$(obj-perf)/util
|
||||
CFLAGS += -I$(obj-perf)
|
||||
INC_FLAGS += -I$(obj-perf)/util
|
||||
INC_FLAGS += -I$(obj-perf)
|
||||
endif
|
||||
|
||||
CFLAGS += -I$(src-perf)/util
|
||||
CFLAGS += -I$(src-perf)
|
||||
CFLAGS += -I$(srctree)/tools/lib/
|
||||
INC_FLAGS += -I$(src-perf)/util
|
||||
INC_FLAGS += -I$(src-perf)
|
||||
INC_FLAGS += -I$(srctree)/tools/lib/
|
||||
|
||||
CFLAGS += $(INC_FLAGS)
|
||||
CXXFLAGS += $(INC_FLAGS)
|
||||
|
||||
CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
|
||||
|
||||
@ -783,6 +794,33 @@ ifndef NO_JVMTI
|
||||
endif
|
||||
endif
|
||||
|
||||
USE_CXX = 0
|
||||
USE_CLANGLLVM = 0
|
||||
ifdef LIBCLANGLLVM
|
||||
$(call feature_check,cxx)
|
||||
ifneq ($(feature-cxx), 1)
|
||||
msg := $(warning No g++ found, disable clang and llvm support. Please install g++)
|
||||
else
|
||||
$(call feature_check,llvm)
|
||||
ifneq ($(feature-llvm), 1)
|
||||
msg := $(warning No libLLVM found, disable clang and llvm support. Please install llvm-dev)
|
||||
else
|
||||
$(call feature_check,clang)
|
||||
ifneq ($(feature-clang), 1)
|
||||
msg := $(warning No libclang found, disable clang and llvm support. Please install libclang-dev)
|
||||
else
|
||||
CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT
|
||||
CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) --includedir)
|
||||
$(call detected,CONFIG_CXX)
|
||||
$(call detected,CONFIG_CLANGLLVM)
|
||||
USE_CXX = 1
|
||||
USE_LLVM = 1
|
||||
USE_CLANG = 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Among the variables below, these:
|
||||
# perfexecdir
|
||||
# template_dir
|
||||
|
@ -88,6 +88,10 @@ include ../scripts/utilities.mak
|
||||
# and bypass the feature detection
|
||||
#
|
||||
# Define NO_JVMTI if you do not want jvmti agent built
|
||||
#
|
||||
# Define LIBCLANGLLVM if you DO want builtin clang and llvm support.
|
||||
# When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if
|
||||
# llvm-config is not in $PATH.
|
||||
|
||||
# As per kernel Makefile, avoid funny character set dependencies
|
||||
unexport LC_ALL
|
||||
@ -143,6 +147,7 @@ endef
|
||||
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
|
||||
$(call allow-override,AR,$(CROSS_COMPILE)ar)
|
||||
$(call allow-override,LD,$(CROSS_COMPILE)ld)
|
||||
$(call allow-override,CXX,$(CROSS_COMPILE)g++)
|
||||
|
||||
LD += $(EXTRA_LDFLAGS)
|
||||
|
||||
@ -151,6 +156,7 @@ HOSTLD ?= ld
|
||||
HOSTAR ?= ar
|
||||
|
||||
PKG_CONFIG = $(CROSS_COMPILE)pkg-config
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
|
||||
RM = rm -f
|
||||
LN = ln -f
|
||||
@ -171,7 +177,7 @@ SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
|
||||
# non-config cases
|
||||
config := 1
|
||||
|
||||
NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc
|
||||
NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc install-man install-html install-info install-pdf doc man html info pdf
|
||||
|
||||
ifdef MAKECMDGOALS
|
||||
ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
|
||||
@ -262,17 +268,6 @@ python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT
|
||||
PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
|
||||
PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
|
||||
|
||||
$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
|
||||
$(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
|
||||
CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
|
||||
$(PYTHON_WORD) util/setup.py \
|
||||
--quiet build_ext; \
|
||||
mkdir -p $(OUTPUT)python && \
|
||||
cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
|
||||
#
|
||||
# No Perl scripts right now:
|
||||
#
|
||||
|
||||
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
|
||||
|
||||
PROGRAMS += $(OUTPUT)perf
|
||||
@ -325,11 +320,6 @@ endif
|
||||
ifndef NO_GTK2
|
||||
ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
|
||||
GTK_IN := $(OUTPUT)gtk-in.o
|
||||
|
||||
install-gtk: $(OUTPUT)libperf-gtk.so
|
||||
$(call QUIET_INSTALL, 'GTK UI') \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
|
||||
$(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
|
||||
endif
|
||||
|
||||
ifdef ASCIIDOC8
|
||||
@ -338,6 +328,21 @@ endif
|
||||
|
||||
LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
|
||||
|
||||
ifeq ($(USE_CLANG), 1)
|
||||
CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
|
||||
LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a))
|
||||
LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
|
||||
endif
|
||||
|
||||
ifeq ($(USE_LLVM), 1)
|
||||
LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs)
|
||||
LIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CXX), 1)
|
||||
LIBS += -lstdc++
|
||||
endif
|
||||
|
||||
export INSTALL SHELL_PATH
|
||||
|
||||
### Build rules
|
||||
@ -346,6 +351,14 @@ SHELL = $(SHELL_PATH)
|
||||
|
||||
all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
|
||||
|
||||
$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
|
||||
$(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
|
||||
CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
|
||||
$(PYTHON_WORD) util/setup.py \
|
||||
--quiet build_ext; \
|
||||
mkdir -p $(OUTPUT)python && \
|
||||
cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
|
||||
|
||||
please_set_SHELL_PATH_to_a_more_modern_shell:
|
||||
$(Q)$$(:)
|
||||
|
||||
@ -356,7 +369,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf
|
||||
|
||||
PERF_IN := $(OUTPUT)perf-in.o
|
||||
|
||||
export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
|
||||
export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK
|
||||
export HOSTCC HOSTLD HOSTAR
|
||||
include $(srctree)/tools/build/Makefile.include
|
||||
|
||||
@ -691,7 +704,14 @@ check: $(OUTPUT)common-cmds.h
|
||||
|
||||
### Installation rules
|
||||
|
||||
ifndef NO_GTK2
|
||||
install-gtk: $(OUTPUT)libperf-gtk.so
|
||||
$(call QUIET_INSTALL, 'GTK UI') \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
|
||||
$(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
|
||||
else
|
||||
install-gtk:
|
||||
endif
|
||||
|
||||
install-tools: all install-gtk
|
||||
$(call QUIET_INSTALL, binaries) \
|
||||
|
@ -43,6 +43,7 @@ perf-y += sdt.o
|
||||
perf-y += is_printable_array.o
|
||||
perf-y += bitmap.o
|
||||
perf-y += perf-hooks.o
|
||||
perf-y += clang.o
|
||||
|
||||
$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
|
||||
$(call rule_mkdir)
|
||||
|
@ -233,6 +233,15 @@ static struct test generic_tests[] = {
|
||||
.desc = "perf hooks",
|
||||
.func = test__perf_hooks,
|
||||
},
|
||||
{
|
||||
.desc = "builtin clang support",
|
||||
.func = test__clang,
|
||||
.subtest = {
|
||||
.skip_if_fail = true,
|
||||
.get_nr = test__clang_subtest_get_nr,
|
||||
.get_desc = test__clang_subtest_get_desc,
|
||||
}
|
||||
},
|
||||
{
|
||||
.func = NULL,
|
||||
},
|
||||
|
46
tools/perf/tests/clang.c
Normal file
46
tools/perf/tests/clang.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "tests.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
#include "c++/clang-c.h"
|
||||
|
||||
static struct {
|
||||
int (*func)(void);
|
||||
const char *desc;
|
||||
} clang_testcase_table[] = {
|
||||
#ifdef HAVE_LIBCLANGLLVM_SUPPORT
|
||||
{
|
||||
.func = test__clang_to_IR,
|
||||
.desc = "builtin clang compile C source to IR",
|
||||
},
|
||||
{
|
||||
.func = test__clang_to_obj,
|
||||
.desc = "builtin clang compile C source to ELF object",
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
int test__clang_subtest_get_nr(void)
|
||||
{
|
||||
return (int)ARRAY_SIZE(clang_testcase_table);
|
||||
}
|
||||
|
||||
const char *test__clang_subtest_get_desc(int i)
|
||||
{
|
||||
if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
|
||||
return NULL;
|
||||
return clang_testcase_table[i].desc;
|
||||
}
|
||||
|
||||
#ifndef HAVE_LIBCLANGLLVM_SUPPORT
|
||||
int test__clang(int i __maybe_unused)
|
||||
{
|
||||
return TEST_SKIP;
|
||||
}
|
||||
#else
|
||||
int test__clang(int i)
|
||||
{
|
||||
if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
|
||||
return TEST_FAIL;
|
||||
return clang_testcase_table[i].func();
|
||||
}
|
||||
#endif
|
@ -1,6 +1,10 @@
|
||||
#ifndef PERF_TEST_LLVM_H
|
||||
#define PERF_TEST_LLVM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
#include <stdbool.h> /* for bool */
|
||||
|
||||
@ -20,4 +24,7 @@ enum test_llvm__testcase {
|
||||
int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
|
||||
enum test_llvm__testcase index, bool force,
|
||||
bool *should_load_fail);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -83,6 +83,7 @@ make_no_libbpf := NO_LIBBPF=1
|
||||
make_no_libcrypto := NO_LIBCRYPTO=1
|
||||
make_with_babeltrace:= LIBBABELTRACE=1
|
||||
make_no_sdt := NO_SDT=1
|
||||
make_with_clangllvm := LIBCLANGLLVM=1
|
||||
make_tags := tags
|
||||
make_cscope := cscope
|
||||
make_help := help
|
||||
@ -139,6 +140,7 @@ run += make_no_libbionic
|
||||
run += make_no_auxtrace
|
||||
run += make_no_libbpf
|
||||
run += make_with_babeltrace
|
||||
run += make_with_clangllvm
|
||||
run += make_help
|
||||
run += make_doc
|
||||
run += make_perf_o
|
||||
@ -278,7 +280,7 @@ endif
|
||||
|
||||
MAKEFLAGS := --no-print-directory
|
||||
|
||||
clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null)
|
||||
clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null && $(MAKE) -s $(O_OPT) -C ../build clean >/dev/null)
|
||||
|
||||
$(run):
|
||||
$(call clean)
|
||||
|
@ -15,13 +15,13 @@ static void sigsegv_handler(int sig __maybe_unused)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static int hook_flags;
|
||||
|
||||
static void the_hook(void)
|
||||
static void the_hook(void *_hook_flags)
|
||||
{
|
||||
int *hook_flags = _hook_flags;
|
||||
int *p = NULL;
|
||||
|
||||
hook_flags = 1234;
|
||||
*hook_flags = 1234;
|
||||
|
||||
/* Generate a segfault, test perf_hooks__recover */
|
||||
*p = 0;
|
||||
@ -29,13 +29,17 @@ static void the_hook(void)
|
||||
|
||||
int test__perf_hooks(int subtest __maybe_unused)
|
||||
{
|
||||
int hook_flags = 0;
|
||||
|
||||
signal(SIGSEGV, sigsegv_handler);
|
||||
perf_hooks__set_hook("test", the_hook);
|
||||
perf_hooks__set_hook("test", the_hook, &hook_flags);
|
||||
perf_hooks__invoke_test();
|
||||
|
||||
/* hook is triggered? */
|
||||
if (hook_flags != 1234)
|
||||
if (hook_flags != 1234) {
|
||||
pr_debug("Setting failed: %d (%p)\n", hook_flags, &hook_flags);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
/* the buggy hook is removed? */
|
||||
if (perf_hooks__get_hook("test"))
|
||||
|
@ -92,6 +92,9 @@ int test__sdt_event(int subtest);
|
||||
int test__is_printable_array(int subtest);
|
||||
int test__bitmap_print(int subtest);
|
||||
int test__perf_hooks(int subtest);
|
||||
int test__clang(int subtest);
|
||||
const char *test__clang_subtest_get_desc(int subtest);
|
||||
int test__clang_subtest_get_nr(void);
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
#ifdef HAVE_DWARF_UNWIND_SUPPORT
|
||||
|
@ -126,6 +126,8 @@ endif
|
||||
|
||||
libperf-y += perf-hooks.o
|
||||
|
||||
libperf-$(CONFIG_CXX) += c++/
|
||||
|
||||
CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
|
||||
# avoid compiler warnings in 32-bit mode
|
||||
CFLAGS_genelf_debug.o += -Wno-packed
|
||||
|
@ -237,6 +237,9 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
|
||||
static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops)
|
||||
{
|
||||
if (!ops->target.addr)
|
||||
return ins__raw_scnprintf(ins, bf, size, ops);
|
||||
|
||||
return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,11 @@
|
||||
#include "debug.h"
|
||||
#include "bpf-loader.h"
|
||||
#include "bpf-prologue.h"
|
||||
#include "llvm-utils.h"
|
||||
#include "probe-event.h"
|
||||
#include "probe-finder.h" // for MAX_PROBES
|
||||
#include "parse-events.h"
|
||||
#include "llvm-utils.h"
|
||||
#include "c++/clang-c.h"
|
||||
|
||||
#define DEFINE_PRINT_FN(name, level) \
|
||||
static int libbpf_##name(const char *fmt, ...) \
|
||||
@ -86,10 +86,21 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
|
||||
void *obj_buf;
|
||||
size_t obj_buf_sz;
|
||||
|
||||
err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
|
||||
if (err)
|
||||
return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
|
||||
perf_clang__init();
|
||||
err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
|
||||
perf_clang__cleanup();
|
||||
if (err) {
|
||||
pr_warning("bpf: builtin compilation failed: %d, try external compiler\n", err);
|
||||
err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
|
||||
if (err)
|
||||
return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
|
||||
} else
|
||||
pr_debug("bpf: successfull builtin compilation\n");
|
||||
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
|
||||
|
||||
if (!IS_ERR(obj) && llvm_param.dump_obj)
|
||||
llvm__dump_obj(filename, obj_buf, obj_buf_sz);
|
||||
|
||||
free(obj_buf);
|
||||
} else
|
||||
obj = bpf_object__open(filename);
|
||||
|
2
tools/perf/util/c++/Build
Normal file
2
tools/perf/util/c++/Build
Normal file
@ -0,0 +1,2 @@
|
||||
libperf-$(CONFIG_CLANGLLVM) += clang.o
|
||||
libperf-$(CONFIG_CLANGLLVM) += clang-test.o
|
43
tools/perf/util/c++/clang-c.h
Normal file
43
tools/perf/util/c++/clang-c.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef PERF_UTIL_CLANG_C_H
|
||||
#define PERF_UTIL_CLANG_C_H
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
#include <util-cxx.h> /* for __maybe_unused */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBCLANGLLVM_SUPPORT
|
||||
extern void perf_clang__init(void);
|
||||
extern void perf_clang__cleanup(void);
|
||||
|
||||
extern int test__clang_to_IR(void);
|
||||
extern int test__clang_to_obj(void);
|
||||
|
||||
extern int perf_clang__compile_bpf(const char *filename,
|
||||
void **p_obj_buf,
|
||||
size_t *p_obj_buf_sz);
|
||||
#else
|
||||
|
||||
|
||||
static inline void perf_clang__init(void) { }
|
||||
static inline void perf_clang__cleanup(void) { }
|
||||
|
||||
static inline int test__clang_to_IR(void) { return -1; }
|
||||
static inline int test__clang_to_obj(void) { return -1;}
|
||||
|
||||
static inline int
|
||||
perf_clang__compile_bpf(const char *filename __maybe_unused,
|
||||
void **p_obj_buf __maybe_unused,
|
||||
size_t *p_obj_buf_sz __maybe_unused)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
62
tools/perf/util/c++/clang-test.cpp
Normal file
62
tools/perf/util/c++/clang-test.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "clang.h"
|
||||
#include "clang-c.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
|
||||
#include <util-cxx.h>
|
||||
#include <tests/llvm.h>
|
||||
#include <string>
|
||||
|
||||
class perf_clang_scope {
|
||||
public:
|
||||
explicit perf_clang_scope() {perf_clang__init();}
|
||||
~perf_clang_scope() {perf_clang__cleanup();}
|
||||
};
|
||||
|
||||
static std::unique_ptr<llvm::Module>
|
||||
__test__clang_to_IR(void)
|
||||
{
|
||||
unsigned int kernel_version;
|
||||
|
||||
if (fetch_kernel_version(&kernel_version, NULL, 0))
|
||||
return std::unique_ptr<llvm::Module>(nullptr);
|
||||
|
||||
std::string cflag_kver("-DLINUX_VERSION_CODE=" +
|
||||
std::to_string(kernel_version));
|
||||
|
||||
std::unique_ptr<llvm::Module> M =
|
||||
perf::getModuleFromSource({cflag_kver.c_str()},
|
||||
"perf-test.c",
|
||||
test_llvm__bpf_base_prog);
|
||||
return M;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
int test__clang_to_IR(void)
|
||||
{
|
||||
perf_clang_scope _scope;
|
||||
|
||||
auto M = __test__clang_to_IR();
|
||||
if (!M)
|
||||
return -1;
|
||||
for (llvm::Function& F : *M)
|
||||
if (F.getName() == "bpf_func__SyS_epoll_wait")
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test__clang_to_obj(void)
|
||||
{
|
||||
perf_clang_scope _scope;
|
||||
|
||||
auto M = __test__clang_to_IR();
|
||||
if (!M)
|
||||
return -1;
|
||||
|
||||
auto Buffer = perf::getBPFObjectFromModule(&*M);
|
||||
if (!Buffer)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
195
tools/perf/util/c++/clang.cpp
Normal file
195
tools/perf/util/c++/clang.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* llvm C frontend for perf. Support dynamically compile C file
|
||||
*
|
||||
* Inspired by clang example code:
|
||||
* http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp
|
||||
*
|
||||
* Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
|
||||
* Copyright (C) 2016 Huawei Inc.
|
||||
*/
|
||||
|
||||
#include "clang/CodeGen/CodeGenAction.h"
|
||||
#include "clang/Frontend/CompilerInvocation.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <memory>
|
||||
|
||||
#include "clang.h"
|
||||
#include "clang-c.h"
|
||||
|
||||
namespace perf {
|
||||
|
||||
static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
|
||||
|
||||
using namespace clang;
|
||||
|
||||
static CompilerInvocation *
|
||||
createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
|
||||
DiagnosticsEngine& Diags)
|
||||
{
|
||||
llvm::opt::ArgStringList CCArgs {
|
||||
"-cc1",
|
||||
"-triple", "bpf-pc-linux",
|
||||
"-fsyntax-only",
|
||||
"-ferror-limit", "19",
|
||||
"-fmessage-length", "127",
|
||||
"-O2",
|
||||
"-nostdsysteminc",
|
||||
"-nobuiltininc",
|
||||
"-vectorize-loops",
|
||||
"-vectorize-slp",
|
||||
"-Wno-unused-value",
|
||||
"-Wno-pointer-sign",
|
||||
"-x", "c"};
|
||||
|
||||
CCArgs.append(CFlags.begin(), CFlags.end());
|
||||
CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
|
||||
|
||||
FrontendOptions& Opts = CI->getFrontendOpts();
|
||||
Opts.Inputs.clear();
|
||||
Opts.Inputs.emplace_back(Path, IK_C);
|
||||
return CI;
|
||||
}
|
||||
|
||||
static std::unique_ptr<llvm::Module>
|
||||
getModuleFromSource(llvm::opt::ArgStringList CFlags,
|
||||
StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
|
||||
{
|
||||
CompilerInstance Clang;
|
||||
Clang.createDiagnostics();
|
||||
|
||||
Clang.setVirtualFileSystem(&*VFS);
|
||||
|
||||
IntrusiveRefCntPtr<CompilerInvocation> CI =
|
||||
createCompilerInvocation(std::move(CFlags), Path,
|
||||
Clang.getDiagnostics());
|
||||
Clang.setInvocation(&*CI);
|
||||
|
||||
std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
|
||||
if (!Clang.ExecuteAction(*Act))
|
||||
return std::unique_ptr<llvm::Module>(nullptr);
|
||||
|
||||
return Act->takeModule();
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::Module>
|
||||
getModuleFromSource(llvm::opt::ArgStringList CFlags,
|
||||
StringRef Name, StringRef Content)
|
||||
{
|
||||
using namespace vfs;
|
||||
|
||||
llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS(
|
||||
new OverlayFileSystem(getRealFileSystem()));
|
||||
llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS(
|
||||
new InMemoryFileSystem(true));
|
||||
|
||||
/*
|
||||
* pushOverlay helps setting working dir for MemFS. Must call
|
||||
* before addFile.
|
||||
*/
|
||||
OverlayFS->pushOverlay(MemFS);
|
||||
MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
|
||||
|
||||
return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::Module>
|
||||
getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
|
||||
{
|
||||
IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
|
||||
return getModuleFromSource(std::move(CFlags), Path, VFS);
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::SmallVectorImpl<char>>
|
||||
getBPFObjectFromModule(llvm::Module *Module)
|
||||
{
|
||||
using namespace llvm;
|
||||
|
||||
std::string TargetTriple("bpf-pc-linux");
|
||||
std::string Error;
|
||||
const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error);
|
||||
if (!Target) {
|
||||
llvm::errs() << Error;
|
||||
return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);
|
||||
}
|
||||
|
||||
llvm::TargetOptions Opt;
|
||||
TargetMachine *TargetMachine =
|
||||
Target->createTargetMachine(TargetTriple,
|
||||
"generic", "",
|
||||
Opt, Reloc::Static);
|
||||
|
||||
Module->setDataLayout(TargetMachine->createDataLayout());
|
||||
Module->setTargetTriple(TargetTriple);
|
||||
|
||||
std::unique_ptr<SmallVectorImpl<char>> Buffer(new SmallVector<char, 0>());
|
||||
raw_svector_ostream ostream(*Buffer);
|
||||
|
||||
legacy::PassManager PM;
|
||||
if (TargetMachine->addPassesToEmitFile(PM, ostream,
|
||||
TargetMachine::CGFT_ObjectFile)) {
|
||||
llvm::errs() << "TargetMachine can't emit a file of this type\n";
|
||||
return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
|
||||
}
|
||||
PM.run(*Module);
|
||||
|
||||
return std::move(Buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void perf_clang__init(void)
|
||||
{
|
||||
perf::LLVMCtx.reset(new llvm::LLVMContext());
|
||||
LLVMInitializeBPFTargetInfo();
|
||||
LLVMInitializeBPFTarget();
|
||||
LLVMInitializeBPFTargetMC();
|
||||
LLVMInitializeBPFAsmPrinter();
|
||||
}
|
||||
|
||||
void perf_clang__cleanup(void)
|
||||
{
|
||||
perf::LLVMCtx.reset(nullptr);
|
||||
llvm::llvm_shutdown();
|
||||
}
|
||||
|
||||
int perf_clang__compile_bpf(const char *filename,
|
||||
void **p_obj_buf,
|
||||
size_t *p_obj_buf_sz)
|
||||
{
|
||||
using namespace perf;
|
||||
|
||||
if (!p_obj_buf || !p_obj_buf_sz)
|
||||
return -EINVAL;
|
||||
|
||||
llvm::opt::ArgStringList CFlags;
|
||||
auto M = getModuleFromSource(std::move(CFlags), filename);
|
||||
if (!M)
|
||||
return -EINVAL;
|
||||
auto O = getBPFObjectFromModule(&*M);
|
||||
if (!O)
|
||||
return -EINVAL;
|
||||
|
||||
size_t size = O->size_in_bytes();
|
||||
void *buffer;
|
||||
|
||||
buffer = malloc(size);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
memcpy(buffer, O->data(), size);
|
||||
*p_obj_buf = buffer;
|
||||
*p_obj_buf_sz = size;
|
||||
return 0;
|
||||
}
|
||||
}
|
26
tools/perf/util/c++/clang.h
Normal file
26
tools/perf/util/c++/clang.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef PERF_UTIL_CLANG_H
|
||||
#define PERF_UTIL_CLANG_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include <memory>
|
||||
|
||||
namespace perf {
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
std::unique_ptr<Module>
|
||||
getModuleFromSource(opt::ArgStringList CFlags,
|
||||
StringRef Name, StringRef Content);
|
||||
|
||||
std::unique_ptr<Module>
|
||||
getModuleFromSource(opt::ArgStringList CFlags,
|
||||
StringRef Path);
|
||||
|
||||
std::unique_ptr<llvm::SmallVectorImpl<char>>
|
||||
getBPFObjectFromModule(llvm::Module *Module);
|
||||
|
||||
}
|
||||
#endif
|
@ -7,6 +7,7 @@
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/err.h>
|
||||
#include "debug.h"
|
||||
#include "llvm-utils.h"
|
||||
#include "config.h"
|
||||
@ -282,9 +283,10 @@ static const char *kinc_fetch_script =
|
||||
"rm -rf $TMPDIR\n"
|
||||
"exit $RET\n";
|
||||
|
||||
static inline void
|
||||
get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
|
||||
void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
|
||||
{
|
||||
static char *saved_kbuild_dir;
|
||||
static char *saved_kbuild_include_opts;
|
||||
int err;
|
||||
|
||||
if (!kbuild_dir || !kbuild_include_opts)
|
||||
@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
|
||||
*kbuild_dir = NULL;
|
||||
*kbuild_include_opts = NULL;
|
||||
|
||||
if (saved_kbuild_dir && saved_kbuild_include_opts &&
|
||||
!IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
|
||||
*kbuild_dir = strdup(saved_kbuild_dir);
|
||||
*kbuild_include_opts = strdup(saved_kbuild_include_opts);
|
||||
|
||||
if (*kbuild_dir && *kbuild_include_opts)
|
||||
return;
|
||||
|
||||
zfree(kbuild_dir);
|
||||
zfree(kbuild_include_opts);
|
||||
/*
|
||||
* Don't fall through: it may breaks saved_kbuild_dir and
|
||||
* saved_kbuild_include_opts if detect them again when
|
||||
* memory is low.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
|
||||
pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
|
||||
pr_debug("Skip kbuild options detection.\n");
|
||||
return;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
err = detect_kbuild_dir(kbuild_dir);
|
||||
@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
|
||||
"Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
|
||||
" \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
|
||||
" \tdetection.\n\n");
|
||||
return;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
|
||||
@ -325,14 +345,43 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
|
||||
|
||||
free(*kbuild_dir);
|
||||
*kbuild_dir = NULL;
|
||||
return;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
pr_debug("include option is set to %s\n", *kbuild_include_opts);
|
||||
|
||||
saved_kbuild_dir = strdup(*kbuild_dir);
|
||||
saved_kbuild_include_opts = strdup(*kbuild_include_opts);
|
||||
|
||||
if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
|
||||
zfree(&saved_kbuild_dir);
|
||||
zfree(&saved_kbuild_include_opts);
|
||||
}
|
||||
return;
|
||||
errout:
|
||||
saved_kbuild_dir = ERR_PTR(-EINVAL);
|
||||
saved_kbuild_include_opts = ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_obj(const char *path, void *obj_buf, size_t size)
|
||||
int llvm__get_nr_cpus(void)
|
||||
{
|
||||
static int nr_cpus_avail = 0;
|
||||
char serr[STRERR_BUFSIZE];
|
||||
|
||||
if (nr_cpus_avail > 0)
|
||||
return nr_cpus_avail;
|
||||
|
||||
nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
|
||||
if (nr_cpus_avail <= 0) {
|
||||
pr_err(
|
||||
"WARNING:\tunable to get available CPUs in this system: %s\n"
|
||||
" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
|
||||
nr_cpus_avail = 128;
|
||||
}
|
||||
return nr_cpus_avail;
|
||||
}
|
||||
|
||||
void llvm__dump_obj(const char *path, void *obj_buf, size_t size)
|
||||
{
|
||||
char *obj_path = strdup(path);
|
||||
FILE *fp;
|
||||
@ -406,15 +455,9 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
|
||||
* This is an optional work. Even it fail we can continue our
|
||||
* work. Needn't to check error return.
|
||||
*/
|
||||
get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
|
||||
llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
|
||||
|
||||
nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
|
||||
if (nr_cpus_avail <= 0) {
|
||||
pr_err(
|
||||
"WARNING:\tunable to get available CPUs in this system: %s\n"
|
||||
" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
|
||||
nr_cpus_avail = 128;
|
||||
}
|
||||
nr_cpus_avail = llvm__get_nr_cpus();
|
||||
snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
|
||||
nr_cpus_avail);
|
||||
|
||||
@ -453,9 +496,6 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
|
||||
free(kbuild_dir);
|
||||
free(kbuild_include_opts);
|
||||
|
||||
if (llvm_param.dump_obj)
|
||||
dump_obj(path, obj_buf, obj_buf_sz);
|
||||
|
||||
if (!p_obj_buf)
|
||||
free(obj_buf);
|
||||
else
|
||||
|
@ -50,4 +50,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, size_t *p_obj_buf_sz);
|
||||
|
||||
/* This function is for test__llvm() use only */
|
||||
int llvm__search_clang(void);
|
||||
|
||||
/* Following functions are reused by builtin clang support */
|
||||
void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts);
|
||||
int llvm__get_nr_cpus(void);
|
||||
|
||||
void llvm__dump_obj(const char *path, void *obj_buf, size_t size);
|
||||
#endif
|
||||
|
@ -27,7 +27,7 @@ void perf_hooks__invoke(const struct perf_hook_desc *desc)
|
||||
*(current_perf_hook->p_hook_func) = NULL;
|
||||
} else {
|
||||
current_perf_hook = desc;
|
||||
(**desc->p_hook_func)();
|
||||
(**desc->p_hook_func)(desc->hook_ctx);
|
||||
}
|
||||
current_perf_hook = NULL;
|
||||
}
|
||||
@ -41,7 +41,9 @@ void perf_hooks__recover(void)
|
||||
#define PERF_HOOK(name) \
|
||||
perf_hook_func_t __perf_hook_func_##name = NULL; \
|
||||
struct perf_hook_desc __perf_hook_desc_##name = \
|
||||
{.hook_name = #name, .p_hook_func = &__perf_hook_func_##name};
|
||||
{.hook_name = #name, \
|
||||
.p_hook_func = &__perf_hook_func_##name, \
|
||||
.hook_ctx = NULL};
|
||||
#include "perf-hooks-list.h"
|
||||
#undef PERF_HOOK
|
||||
|
||||
@ -54,7 +56,8 @@ static struct perf_hook_desc *perf_hooks[] = {
|
||||
#undef PERF_HOOK
|
||||
|
||||
int perf_hooks__set_hook(const char *hook_name,
|
||||
perf_hook_func_t hook_func)
|
||||
perf_hook_func_t hook_func,
|
||||
void *hook_ctx)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@ -65,6 +68,7 @@ int perf_hooks__set_hook(const char *hook_name,
|
||||
if (*(perf_hooks[i]->p_hook_func))
|
||||
pr_warning("Overwrite existing hook: %s\n", hook_name);
|
||||
*(perf_hooks[i]->p_hook_func) = hook_func;
|
||||
perf_hooks[i]->hook_ctx = hook_ctx;
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
|
@ -5,10 +5,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*perf_hook_func_t)(void);
|
||||
typedef void (*perf_hook_func_t)(void *ctx);
|
||||
struct perf_hook_desc {
|
||||
const char * const hook_name;
|
||||
perf_hook_func_t * const p_hook_func;
|
||||
void *hook_ctx;
|
||||
};
|
||||
|
||||
extern void perf_hooks__invoke(const struct perf_hook_desc *);
|
||||
@ -26,7 +27,8 @@ static inline void perf_hooks__invoke_##name(void) \
|
||||
|
||||
extern int
|
||||
perf_hooks__set_hook(const char *hook_name,
|
||||
perf_hook_func_t hook_func);
|
||||
perf_hook_func_t hook_func,
|
||||
void *hook_ctx);
|
||||
|
||||
extern perf_hook_func_t
|
||||
perf_hooks__get_hook(const char *hook_name);
|
||||
|
26
tools/perf/util/util-cxx.h
Normal file
26
tools/perf/util/util-cxx.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Support C++ source use utilities defined in util.h
|
||||
*/
|
||||
|
||||
#ifndef PERF_UTIL_UTIL_CXX_H
|
||||
#define PERF_UTIL_UTIL_CXX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now 'new' is the only C++ keyword found in util.h:
|
||||
* in tools/include/linux/rbtree.h
|
||||
*
|
||||
* Other keywords, like class and delete, should be
|
||||
* redefined if necessary.
|
||||
*/
|
||||
#define new _new
|
||||
#include "util.h"
|
||||
#undef new
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user