Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf bpf: Remove support for embedding clang for compiling BPF events (-e foo.c)

This never was in the default build for perf, is difficult to maintain
as it uses clang/llvm internals so ditch it, keeping, for now, the
external compilation of .c BPF into .o bytecode and its subsequent
loading, that is also going to be removed, do it separately to help
bisection and to properly document what is being removed and why.

Committer notes:

Extracted from a larger patch and removed some leftovers, namely
deleting these now unused feature tests:

tools/build/feature/test-clang.cpp
tools/build/feature/test-cxx.cpp
tools/build/feature/test-llvm-version.cpp
tools/build/feature/test-llvm.cpp

Testing the use of BPF events after applying this patch:

To use the external clang/llvm toolchain to compile a .c event and then
use libbpf to load it, to get the syscalls:sys_enter_open* tracepoints
and read the filename pointer, putting it into the ring buffer right
after the usual tracepoint payload for 'perf trace' to then print it:

[root@quaco ~]# perf trace -e /home/acme/git/perf-tools-next/tools/perf/examples/bpf/augmented_raw_syscalls.c,open* --max-events=10
0.000 systemd-oomd/959 openat(dfd: CWD, filename: "/proc/meminfo", flags: RDONLY|CLOEXEC) = 12
0.083 abrt-dump-jour/1453 openat(dfd: CWD, filename: "/var/log/journal/d6a97235307247e09f13f326fb607e3c/system.journal", flags: RDONLY|CLOEXEC|NONBLOCK) = 4
0.063 abrt-dump-jour/1454 openat(dfd: CWD, filename: "/var/log/journal/d6a97235307247e09f13f326fb607e3c/system.journal", flags: RDONLY|CLOEXEC|NONBLOCK) = 4
0.082 abrt-dump-jour/1455 openat(dfd: CWD, filename: "/var/log/journal/d6a97235307247e09f13f326fb607e3c/system.journal", flags: RDONLY|CLOEXEC|NONBLOCK) = 4
250.124 systemd-oomd/959 openat(dfd: CWD, filename: "/proc/meminfo", flags: RDONLY|CLOEXEC) = 12
250.521 systemd-oomd/959 openat(dfd: CWD, filename: "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/memory.pressure", flags: RDONLY|CLOEXEC) = 12
251.047 systemd-oomd/959 openat(dfd: CWD, filename: "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/memory.current", flags: RDONLY|CLOEXEC) = 12
251.162 systemd-oomd/959 openat(dfd: CWD, filename: "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/memory.min", flags: RDONLY|CLOEXEC) = 12
251.242 systemd-oomd/959 openat(dfd: CWD, filename: "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/memory.low", flags: RDONLY|CLOEXEC) = 12
251.353 systemd-oomd/959 openat(dfd: CWD, filename: "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/memory.swap.current", flags: RDONLY|CLOEXEC) = 12
[root@quaco ~]#

Same thing, but with a prebuilt .o BPF bytecode:

[root@quaco ~]# perf trace -e /home/acme/git/perf-tools-next/tools/perf/examples/bpf/augmented_raw_syscalls.o,open* --max-events=10
0.000 systemd-oomd/959 openat(dfd: CWD, filename: "/proc/meminfo", flags: RDONLY|CLOEXEC) = 12
0.083 abrt-dump-jour/1453 openat(dfd: CWD, filename: "/var/log/journal/d6a97235307247e09f13f326fb607e3c/system.journal", flags: RDONLY|CLOEXEC|NONBLOCK) = 4
0.083 abrt-dump-jour/1455 openat(dfd: CWD, filename: "/var/log/journal/d6a97235307247e09f13f326fb607e3c/system.journal", flags: RDONLY|CLOEXEC|NONBLOCK) = 4
0.062 abrt-dump-jour/1454 openat(dfd: CWD, filename: "/var/log/journal/d6a97235307247e09f13f326fb607e3c/system.journal", flags: RDONLY|CLOEXEC|NONBLOCK) = 4
249.985 systemd-oomd/959 openat(dfd: CWD, filename: "/proc/meminfo", flags: RDONLY|CLOEXEC) = 12
466.763 thermald/1234 openat(dfd: CWD, filename: "/sys/class/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:2/energy_uj") = 13
467.145 thermald/1234 openat(dfd: CWD, filename: "/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj") = 13
467.311 thermald/1234 openat(dfd: CWD, filename: "/sys/class/thermal/thermal_zone2/temp") = 13
500.040 cgroupify/24006 openat(dfd: 4, filename: ".", flags: RDONLY|CLOEXEC|DIRECTORY|NONBLOCK) = 5
500.295 cgroupify/24006 openat(dfd: 4, filename: "24616/cgroup.procs") = 5
[root@quaco ~]#

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Carsten Haitzler <carsten.haitzler@arm.com>
Cc: Eduard Zingerman <eddyz87@gmail.com>
Cc: Fangrui Song <maskray@google.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Tom Rix <trix@redhat.com>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Wang ShaoBo <bobo.shaobowang@huawei.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: YueHaibing <yuehaibing@huawei.com>
Link: https://lore.kernel.org/lkml/ZNZWsAXg2px1sm2h@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
56b11a21 6f769c34

+4 -533
-28
tools/build/feature/test-clang.cpp
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include "clang/Basic/Version.h" 3 - #if CLANG_VERSION_MAJOR < 8 4 - #include "clang/Basic/VirtualFileSystem.h" 5 - #endif 6 - #include "clang/Driver/Driver.h" 7 - #include "clang/Frontend/TextDiagnosticPrinter.h" 8 - #include "llvm/ADT/IntrusiveRefCntPtr.h" 9 - #include "llvm/Support/ManagedStatic.h" 10 - #if CLANG_VERSION_MAJOR >= 8 11 - #include "llvm/Support/VirtualFileSystem.h" 12 - #endif 13 - #include "llvm/Support/raw_ostream.h" 14 - 15 - using namespace clang; 16 - using namespace clang::driver; 17 - 18 - int main() 19 - { 20 - IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 21 - IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 22 - 23 - DiagnosticsEngine Diags(DiagID, &*DiagOpts); 24 - Driver TheDriver("test", "bpf-pc-linux", Diags); 25 - 26 - llvm::llvm_shutdown(); 27 - return 0; 28 - }
-16
tools/build/feature/test-cxx.cpp
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <iostream> 3 - #include <memory> 4 - 5 - static void print_str(std::string s) 6 - { 7 - std::cout << s << std::endl; 8 - } 9 - 10 - int main() 11 - { 12 - std::string s("Hello World!"); 13 - print_str(std::move(s)); 14 - std::cout << "|" << s << "|" << std::endl; 15 - return 0; 16 - }
-12
tools/build/feature/test-llvm-version.cpp
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <cstdio> 3 - #include "llvm/Config/llvm-config.h" 4 - 5 - #define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) + LLVM_VERSION_PATCH) 6 - #define pass int main() {printf("%x\n", NUM_VERSION); return 0;} 7 - 8 - #if NUM_VERSION >= 0x030900 9 - pass 10 - #else 11 - # error This LLVM is not tested yet. 12 - #endif
-14
tools/build/feature/test-llvm.cpp
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include "llvm/Support/ManagedStatic.h" 3 - #include "llvm/Support/raw_ostream.h" 4 - #define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) + LLVM_VERSION_PATCH) 5 - 6 - #if NUM_VERSION < 0x030900 7 - # error "LLVM version too low" 8 - #endif 9 - int main() 10 - { 11 - llvm::errs() << "Hello World!\n"; 12 - llvm::llvm_shutdown(); 13 - return 0; 14 - }
-31
tools/perf/Makefile.config
··· 1127 1127 endif 1128 1128 endif 1129 1129 1130 - USE_CXX = 0 1131 - USE_CLANGLLVM = 0 1132 - ifdef LIBCLANGLLVM 1133 - $(call feature_check,cxx) 1134 - ifneq ($(feature-cxx), 1) 1135 - msg := $(warning No g++ found, disable clang and llvm support. Please install g++) 1136 - else 1137 - $(call feature_check,llvm) 1138 - $(call feature_check,llvm-version) 1139 - ifneq ($(feature-llvm), 1) 1140 - msg := $(warning No suitable libLLVM found, disabling builtin clang and LLVM support. Please install llvm-dev(el) (>= 3.9.0)) 1141 - else 1142 - $(call feature_check,clang) 1143 - ifneq ($(feature-clang), 1) 1144 - msg := $(warning No suitable libclang found, disabling builtin clang and LLVM support. Please install libclang-dev(el) (>= 3.9.0)) 1145 - else 1146 - CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT 1147 - CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) --includedir) 1148 - $(call detected,CONFIG_CXX) 1149 - $(call detected,CONFIG_CLANGLLVM) 1150 - USE_CXX = 1 1151 - USE_LLVM = 1 1152 - USE_CLANG = 1 1153 - ifneq ($(feature-llvm-version),1) 1154 - msg := $(warning This version of LLVM is not tested. May cause build errors) 1155 - endif 1156 - endif 1157 - endif 1158 - endif 1159 - endif 1160 - 1161 1130 ifndef NO_LIBPFM4 1162 1131 $(call feature_check,libpfm4) 1163 1132 ifeq ($(feature-libpfm4), 1)
-17
tools/perf/Makefile.perf
··· 99 99 # Define NO_JVMTI_CMLR (debug only) if you do not want to process CMLR 100 100 # data for java source lines. 101 101 # 102 - # Define LIBCLANGLLVM if you DO want builtin clang and llvm support. 103 - # When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if 104 - # llvm-config is not in $PATH. 105 - # 106 102 # Define CORESIGHT if you DO WANT support for CoreSight trace decoding. 107 103 # 108 104 # Define NO_AIO if you do not want support of Posix AIO based trace ··· 420 424 421 425 EXTLIBS := $(call filter-out,$(EXCLUDE_EXTLIBS),$(EXTLIBS)) 422 426 LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group 423 - 424 - ifeq ($(USE_CLANG), 1) 425 - LIBS += -L$(shell $(LLVM_CONFIG) --libdir) -lclang-cpp 426 - endif 427 - 428 - ifeq ($(USE_LLVM), 1) 429 - LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs) 430 - LIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM) 431 - endif 432 - 433 - ifeq ($(USE_CXX), 1) 434 - LIBS += -lstdc++ 435 - endif 436 427 437 428 export INSTALL SHELL_PATH 438 429
-1
tools/perf/tests/Build
··· 51 51 perf-y += is_printable_array.o 52 52 perf-y += bitmap.o 53 53 perf-y += perf-hooks.o 54 - perf-y += clang.o 55 54 perf-y += unit_number__scnprintf.o 56 55 perf-y += mem2node.o 57 56 perf-y += maps.o
-1
tools/perf/tests/builtin-test.c
··· 108 108 &suite__is_printable_array, 109 109 &suite__bitmap_print, 110 110 &suite__perf_hooks, 111 - &suite__clang, 112 111 &suite__unit_number__scnprint, 113 112 &suite__mem2node, 114 113 &suite__time_utils,
-32
tools/perf/tests/clang.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include "tests.h" 3 - #include "c++/clang-c.h" 4 - #include <linux/kernel.h> 5 - 6 - #ifndef HAVE_LIBCLANGLLVM_SUPPORT 7 - static int test__clang_to_IR(struct test_suite *test __maybe_unused, 8 - int subtest __maybe_unused) 9 - { 10 - return TEST_SKIP; 11 - } 12 - 13 - static int test__clang_to_obj(struct test_suite *test __maybe_unused, 14 - int subtest __maybe_unused) 15 - { 16 - return TEST_SKIP; 17 - } 18 - #endif 19 - 20 - static struct test_case clang_tests[] = { 21 - TEST_CASE_REASON("builtin clang compile C source to IR", clang_to_IR, 22 - "not compiled in"), 23 - TEST_CASE_REASON("builtin clang compile C source to ELF object", 24 - clang_to_obj, 25 - "not compiled in"), 26 - { .name = NULL, } 27 - }; 28 - 29 - struct test_suite suite__clang = { 30 - .desc = "builtin clang support", 31 - .test_cases = clang_tests, 32 - };
-1
tools/perf/tests/make
··· 95 95 make_with_coresight := CORESIGHT=1 96 96 make_no_sdt := NO_SDT=1 97 97 make_no_syscall_tbl := NO_SYSCALL_TABLE=1 98 - make_with_clangllvm := LIBCLANGLLVM=1 99 98 make_no_libpfm4 := NO_LIBPFM4=1 100 99 make_with_gtk2 := GTK2=1 101 100 make_refcnt_check := EXTRA_CFLAGS="-DREFCNT_CHECKING=1"
-2
tools/perf/util/Build
··· 232 232 perf-$(CONFIG_LIBBPF) += bpf-event.o 233 233 perf-$(CONFIG_LIBBPF) += bpf-utils.o 234 234 235 - perf-$(CONFIG_CXX) += c++/ 236 - 237 235 perf-$(CONFIG_LIBPFM4) += pfm.o 238 236 239 237 CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
+4 -11
tools/perf/util/bpf-loader.c
··· 26 26 #include "strfilter.h" 27 27 #include "util.h" 28 28 #include "llvm-utils.h" 29 - #include "c++/clang-c.h" 30 29 #include "util/hashmap.h" 31 30 #include "asm/bug.h" 32 31 ··· 219 220 void *obj_buf; 220 221 size_t obj_buf_sz; 221 222 222 - perf_clang__init(); 223 - err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz); 224 - perf_clang__cleanup(); 225 - if (err) { 226 - pr_debug("bpf: builtin compilation failed: %d, try external compiler\n", err); 227 - err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); 228 - if (err) 229 - return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE); 230 - } else 231 - pr_debug("bpf: successful builtin compilation\n"); 223 + err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); 224 + if (err) 225 + return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE); 226 + 232 227 obj = bpf_object__open_mem(obj_buf, obj_buf_sz, &opts); 233 228 234 229 if (!IS_ERR_OR_NULL(obj) && llvm_param.dump_obj)
-5
tools/perf/util/c++/Build
··· 1 - perf-$(CONFIG_CLANGLLVM) += clang.o 2 - perf-$(CONFIG_CLANGLLVM) += clang-test.o 3 - 4 - CXXFLAGS_clang.o += -Wno-unused-parameter 5 - CXXFLAGS_clang-test.o += -Wno-unused-parameter
-43
tools/perf/util/c++/clang-c.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef PERF_UTIL_CLANG_C_H 3 - #define PERF_UTIL_CLANG_C_H 4 - 5 - #include <stddef.h> /* for size_t */ 6 - 7 - #ifdef __cplusplus 8 - extern "C" { 9 - #endif 10 - 11 - #ifdef HAVE_LIBCLANGLLVM_SUPPORT 12 - extern void perf_clang__init(void); 13 - extern void perf_clang__cleanup(void); 14 - 15 - struct test_suite; 16 - extern int test__clang_to_IR(struct test_suite *test, int subtest); 17 - extern int test__clang_to_obj(struct test_suite *test, int subtest); 18 - 19 - extern int perf_clang__compile_bpf(const char *filename, 20 - void **p_obj_buf, 21 - size_t *p_obj_buf_sz); 22 - #else 23 - 24 - #include <errno.h> 25 - #include <linux/compiler.h> /* for __maybe_unused */ 26 - 27 - static inline void perf_clang__init(void) { } 28 - static inline void perf_clang__cleanup(void) { } 29 - 30 - static inline int 31 - perf_clang__compile_bpf(const char *filename __maybe_unused, 32 - void **p_obj_buf __maybe_unused, 33 - size_t *p_obj_buf_sz __maybe_unused) 34 - { 35 - return -ENOTSUP; 36 - } 37 - 38 - #endif 39 - 40 - #ifdef __cplusplus 41 - } 42 - #endif 43 - #endif
-67
tools/perf/util/c++/clang-test.cpp
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include "clang.h" 3 - #include "clang-c.h" 4 - extern "C" { 5 - #include "../util.h" 6 - } 7 - #include "llvm/IR/Function.h" 8 - #include "llvm/IR/LLVMContext.h" 9 - 10 - #include <tests/llvm.h> 11 - #include <string> 12 - 13 - class perf_clang_scope { 14 - public: 15 - explicit perf_clang_scope() {perf_clang__init();} 16 - ~perf_clang_scope() {perf_clang__cleanup();} 17 - }; 18 - 19 - static std::unique_ptr<llvm::Module> 20 - __test__clang_to_IR(void) 21 - { 22 - unsigned int kernel_version; 23 - 24 - if (fetch_kernel_version(&kernel_version, NULL, 0)) 25 - return std::unique_ptr<llvm::Module>(nullptr); 26 - 27 - std::string cflag_kver("-DLINUX_VERSION_CODE=" + 28 - std::to_string(kernel_version)); 29 - 30 - std::unique_ptr<llvm::Module> M = 31 - perf::getModuleFromSource({cflag_kver.c_str()}, 32 - "perf-test.c", 33 - test_llvm__bpf_base_prog); 34 - return M; 35 - } 36 - 37 - extern "C" { 38 - int test__clang_to_IR(struct test_suite *test __maybe_unused, 39 - int subtest __maybe_unused) 40 - { 41 - perf_clang_scope _scope; 42 - 43 - auto M = __test__clang_to_IR(); 44 - if (!M) 45 - return -1; 46 - for (llvm::Function& F : *M) 47 - if (F.getName() == "bpf_func__SyS_epoll_pwait") 48 - return 0; 49 - return -1; 50 - } 51 - 52 - int test__clang_to_obj(struct test_suite *test __maybe_unused, 53 - int subtest __maybe_unused) 54 - { 55 - perf_clang_scope _scope; 56 - 57 - auto M = __test__clang_to_IR(); 58 - if (!M) 59 - return -1; 60 - 61 - auto Buffer = perf::getBPFObjectFromModule(&*M); 62 - if (!Buffer) 63 - return -1; 64 - return 0; 65 - } 66 - 67 - }
-225
tools/perf/util/c++/clang.cpp
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * llvm C frontend for perf. Support dynamically compile C file 4 - * 5 - * Inspired by clang example code: 6 - * http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp 7 - * 8 - * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com> 9 - * Copyright (C) 2016 Huawei Inc. 10 - */ 11 - 12 - #include "clang/Basic/Version.h" 13 - #include "clang/CodeGen/CodeGenAction.h" 14 - #include "clang/Frontend/CompilerInvocation.h" 15 - #include "clang/Frontend/CompilerInstance.h" 16 - #include "clang/Frontend/TextDiagnosticPrinter.h" 17 - #include "clang/Tooling/Tooling.h" 18 - #include "llvm/IR/LegacyPassManager.h" 19 - #include "llvm/IR/Module.h" 20 - #include "llvm/Option/Option.h" 21 - #include "llvm/Support/FileSystem.h" 22 - #include "llvm/Support/ManagedStatic.h" 23 - #if CLANG_VERSION_MAJOR >= 14 24 - #include "llvm/MC/TargetRegistry.h" 25 - #else 26 - #include "llvm/Support/TargetRegistry.h" 27 - #endif 28 - #include "llvm/Support/TargetSelect.h" 29 - #include "llvm/Target/TargetMachine.h" 30 - #include "llvm/Target/TargetOptions.h" 31 - #include <memory> 32 - 33 - #include "clang.h" 34 - #include "clang-c.h" 35 - 36 - namespace perf { 37 - 38 - static std::unique_ptr<llvm::LLVMContext> LLVMCtx; 39 - 40 - using namespace clang; 41 - 42 - static CompilerInvocation * 43 - createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path, 44 - DiagnosticsEngine& Diags) 45 - { 46 - llvm::opt::ArgStringList CCArgs { 47 - "-cc1", 48 - "-triple", "bpf-pc-linux", 49 - "-fsyntax-only", 50 - "-O2", 51 - "-nostdsysteminc", 52 - "-nobuiltininc", 53 - "-vectorize-loops", 54 - "-vectorize-slp", 55 - "-Wno-unused-value", 56 - "-Wno-pointer-sign", 57 - "-x", "c"}; 58 - 59 - CCArgs.append(CFlags.begin(), CFlags.end()); 60 - CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs 61 - #if CLANG_VERSION_MAJOR >= 11 62 - ,/*BinaryName=*/nullptr 63 - #endif 64 - ); 65 - 66 - FrontendOptions& Opts = CI->getFrontendOpts(); 67 - Opts.Inputs.clear(); 68 - Opts.Inputs.emplace_back(Path, 69 - FrontendOptions::getInputKindForExtension("c")); 70 - return CI; 71 - } 72 - 73 - static std::unique_ptr<llvm::Module> 74 - getModuleFromSource(llvm::opt::ArgStringList CFlags, 75 - StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS) 76 - { 77 - CompilerInstance Clang; 78 - Clang.createDiagnostics(); 79 - 80 - #if CLANG_VERSION_MAJOR < 9 81 - Clang.setVirtualFileSystem(&*VFS); 82 - #else 83 - Clang.createFileManager(&*VFS); 84 - #endif 85 - 86 - #if CLANG_VERSION_MAJOR < 4 87 - IntrusiveRefCntPtr<CompilerInvocation> CI = 88 - createCompilerInvocation(std::move(CFlags), Path, 89 - Clang.getDiagnostics()); 90 - Clang.setInvocation(&*CI); 91 - #else 92 - std::shared_ptr<CompilerInvocation> CI( 93 - createCompilerInvocation(std::move(CFlags), Path, 94 - Clang.getDiagnostics())); 95 - Clang.setInvocation(CI); 96 - #endif 97 - 98 - std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx)); 99 - if (!Clang.ExecuteAction(*Act)) 100 - return std::unique_ptr<llvm::Module>(nullptr); 101 - 102 - return Act->takeModule(); 103 - } 104 - 105 - std::unique_ptr<llvm::Module> 106 - getModuleFromSource(llvm::opt::ArgStringList CFlags, 107 - StringRef Name, StringRef Content) 108 - { 109 - using namespace vfs; 110 - 111 - llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS( 112 - new OverlayFileSystem(getRealFileSystem())); 113 - llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS( 114 - new InMemoryFileSystem(true)); 115 - 116 - /* 117 - * pushOverlay helps setting working dir for MemFS. Must call 118 - * before addFile. 119 - */ 120 - OverlayFS->pushOverlay(MemFS); 121 - MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content)); 122 - 123 - return getModuleFromSource(std::move(CFlags), Name, OverlayFS); 124 - } 125 - 126 - std::unique_ptr<llvm::Module> 127 - getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path) 128 - { 129 - IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem()); 130 - return getModuleFromSource(std::move(CFlags), Path, VFS); 131 - } 132 - 133 - std::unique_ptr<llvm::SmallVectorImpl<char>> 134 - getBPFObjectFromModule(llvm::Module *Module) 135 - { 136 - using namespace llvm; 137 - 138 - std::string TargetTriple("bpf-pc-linux"); 139 - std::string Error; 140 - const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error); 141 - if (!Target) { 142 - llvm::errs() << Error; 143 - return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr); 144 - } 145 - 146 - llvm::TargetOptions Opt; 147 - TargetMachine *TargetMachine = 148 - Target->createTargetMachine(TargetTriple, 149 - "generic", "", 150 - Opt, Reloc::Static); 151 - 152 - Module->setDataLayout(TargetMachine->createDataLayout()); 153 - Module->setTargetTriple(TargetTriple); 154 - 155 - std::unique_ptr<SmallVectorImpl<char>> Buffer(new SmallVector<char, 0>()); 156 - raw_svector_ostream ostream(*Buffer); 157 - 158 - legacy::PassManager PM; 159 - bool NotAdded; 160 - NotAdded = TargetMachine->addPassesToEmitFile(PM, ostream 161 - #if CLANG_VERSION_MAJOR >= 7 162 - , /*DwoOut=*/nullptr 163 - #endif 164 - #if CLANG_VERSION_MAJOR < 10 165 - , TargetMachine::CGFT_ObjectFile 166 - #else 167 - , llvm::CGFT_ObjectFile 168 - #endif 169 - ); 170 - if (NotAdded) { 171 - llvm::errs() << "TargetMachine can't emit a file of this type\n"; 172 - return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr); 173 - } 174 - PM.run(*Module); 175 - 176 - return Buffer; 177 - } 178 - 179 - } 180 - 181 - extern "C" { 182 - void perf_clang__init(void) 183 - { 184 - perf::LLVMCtx.reset(new llvm::LLVMContext()); 185 - LLVMInitializeBPFTargetInfo(); 186 - LLVMInitializeBPFTarget(); 187 - LLVMInitializeBPFTargetMC(); 188 - LLVMInitializeBPFAsmPrinter(); 189 - } 190 - 191 - void perf_clang__cleanup(void) 192 - { 193 - perf::LLVMCtx.reset(nullptr); 194 - llvm::llvm_shutdown(); 195 - } 196 - 197 - int perf_clang__compile_bpf(const char *filename, 198 - void **p_obj_buf, 199 - size_t *p_obj_buf_sz) 200 - { 201 - using namespace perf; 202 - 203 - if (!p_obj_buf || !p_obj_buf_sz) 204 - return -EINVAL; 205 - 206 - llvm::opt::ArgStringList CFlags; 207 - auto M = getModuleFromSource(std::move(CFlags), filename); 208 - if (!M) 209 - return -EINVAL; 210 - auto O = getBPFObjectFromModule(&*M); 211 - if (!O) 212 - return -EINVAL; 213 - 214 - size_t size = O->size_in_bytes(); 215 - void *buffer; 216 - 217 - buffer = malloc(size); 218 - if (!buffer) 219 - return -ENOMEM; 220 - memcpy(buffer, O->data(), size); 221 - *p_obj_buf = buffer; 222 - *p_obj_buf_sz = size; 223 - return 0; 224 - } 225 - }
-27
tools/perf/util/c++/clang.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef PERF_UTIL_CLANG_H 3 - #define PERF_UTIL_CLANG_H 4 - 5 - #include "llvm/ADT/StringRef.h" 6 - #include "llvm/IR/LLVMContext.h" 7 - #include "llvm/IR/Module.h" 8 - #include "llvm/Option/Option.h" 9 - #include <memory> 10 - 11 - namespace perf { 12 - 13 - using namespace llvm; 14 - 15 - std::unique_ptr<Module> 16 - getModuleFromSource(opt::ArgStringList CFlags, 17 - StringRef Name, StringRef Content); 18 - 19 - std::unique_ptr<Module> 20 - getModuleFromSource(opt::ArgStringList CFlags, 21 - StringRef Path); 22 - 23 - std::unique_ptr<llvm::SmallVectorImpl<char>> 24 - getBPFObjectFromModule(llvm::Module *Module); 25 - 26 - } 27 - #endif