diff --git a/SPECS/bcc.el6.spec b/SPECS/bcc.el6.spec index 9bf72554e557..f25e34ab30da 100644 --- a/SPECS/bcc.el6.spec +++ b/SPECS/bcc.el6.spec @@ -107,8 +107,6 @@ Python bindings for BPF Compiler Collection (BCC) %files -n libbcc /usr/lib64/* -/usr/share/bcc/include/* -/usr/share/bcc/lib/* /usr/include/bcc/* %files -n libbcc-examples diff --git a/SPECS/bcc.el6.spec.in b/SPECS/bcc.el6.spec.in index f684c7cf534c..4493f9ff980a 100644 --- a/SPECS/bcc.el6.spec.in +++ b/SPECS/bcc.el6.spec.in @@ -107,8 +107,6 @@ Python bindings for BPF Compiler Collection (BCC) %files -n libbcc /usr/lib64/* -/usr/share/bcc/include/* -/usr/share/bcc/lib/* /usr/include/bcc/* %files -n libbcc-examples diff --git a/SPECS/bcc.el7.spec b/SPECS/bcc.el7.spec index ba21a3298bee..6a99d624e515 100644 --- a/SPECS/bcc.el7.spec +++ b/SPECS/bcc.el7.spec @@ -76,8 +76,6 @@ Python bindings for BPF Compiler Collection (BCC) %files -n libbcc /usr/lib64/* -/usr/share/bcc/include/* -/usr/share/bcc/lib/* /usr/include/bcc/* %files -n libbcc-examples diff --git a/SPECS/bcc.el7.spec.in b/SPECS/bcc.el7.spec.in index a6531fe7d176..32cd9a487d4d 100644 --- a/SPECS/bcc.el7.spec.in +++ b/SPECS/bcc.el7.spec.in @@ -76,8 +76,6 @@ Python bindings for BPF Compiler Collection (BCC) %files -n libbcc /usr/lib64/* -/usr/share/bcc/include/* -/usr/share/bcc/lib/* /usr/include/bcc/* %files -n libbcc-examples diff --git a/SPECS/bcc.f22.spec b/SPECS/bcc.f22.spec index ba21a3298bee..6a99d624e515 100644 --- a/SPECS/bcc.f22.spec +++ b/SPECS/bcc.f22.spec @@ -76,8 +76,6 @@ Python bindings for BPF Compiler Collection (BCC) %files -n libbcc /usr/lib64/* -/usr/share/bcc/include/* -/usr/share/bcc/lib/* /usr/include/bcc/* %files -n libbcc-examples diff --git a/SPECS/bcc.f22.spec.in b/SPECS/bcc.f22.spec.in index a6531fe7d176..32cd9a487d4d 100644 --- a/SPECS/bcc.f22.spec.in +++ b/SPECS/bcc.f22.spec.in @@ -76,8 +76,6 @@ Python bindings for BPF Compiler Collection (BCC) %files -n libbcc /usr/lib64/* -/usr/share/bcc/include/* -/usr/share/bcc/lib/* /usr/include/bcc/* %files -n libbcc-examples diff --git a/SPECS/bcc.spec b/SPECS/bcc.spec index 8eb193b43af2..08e13feb4624 100644 --- a/SPECS/bcc.spec +++ b/SPECS/bcc.spec @@ -71,8 +71,6 @@ Command line tools for BPF Compiler Collection (BCC) %files -n libbcc /usr/lib64/* -/usr/share/bcc/include/* -/usr/share/bcc/lib/* /usr/include/bcc/* %files -n libbcc-examples diff --git a/debian/libbcc.install b/debian/libbcc.install index c60b682413fc..cd38d8df562f 100644 --- a/debian/libbcc.install +++ b/debian/libbcc.install @@ -1,4 +1,2 @@ usr/include/bcc/* usr/lib/x86_64-linux-gnu/libbcc* -usr/share/bcc/include/* -usr/share/bcc/lib/* diff --git a/src/cc/CMakeLists.txt b/src/cc/CMakeLists.txt index ca7dfdf99d76..197f32087102 100644 --- a/src/cc/CMakeLists.txt +++ b/src/cc/CMakeLists.txt @@ -32,10 +32,7 @@ if (CMAKE_COMPILER_IS_GNUCC) endif() endif() -# tell the shared library where it is being installed so it can find shared header files -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBCC_INSTALL_PREFIX='\"${CMAKE_INSTALL_PREFIX}\"'") - -add_library(bcc SHARED bpf_common.cc bpf_module.cc libbpf.c perf_reader.c shared_table.cc) +add_library(bcc SHARED bpf_common.cc bpf_module.cc libbpf.c perf_reader.c shared_table.cc exported_files.cc) set_target_properties(bcc PROPERTIES VERSION ${REVISION_LAST} SOVERSION 0) # BPF is still experimental otherwise it should be available @@ -52,9 +49,6 @@ target_link_libraries(bcc b_frontend clang_frontend ${clang_libs} ${llvm_libs} L install(TARGETS bcc LIBRARY COMPONENT libbcc DESTINATION ${CMAKE_INSTALL_LIBDIR}) -install(DIRECTORY export/ COMPONENT libbcc - DESTINATION share/bcc/include/bcc - FILES_MATCHING PATTERN "*.h") install(FILES bpf_common.h bpf_module.h ../libbpf.h COMPONENT libbcc DESTINATION include/bcc) install(DIRECTORY compat/linux/ COMPONENT libbcc @@ -62,8 +56,5 @@ install(DIRECTORY compat/linux/ COMPONENT libbcc FILES_MATCHING PATTERN "*.h") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libbcc.pc COMPONENT libbcc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -install(DIRECTORY clang COMPONENT libbcc - DESTINATION share/bcc/lib - FILES_MATCHING PATTERN "*.h") add_subdirectory(frontends) diff --git a/src/cc/bpf_module.cc b/src/cc/bpf_module.cc index 1d427820c1e5..cc5aae1a6578 100644 --- a/src/cc/bpf_module.cc +++ b/src/cc/bpf_module.cc @@ -48,6 +48,7 @@ #include "frontends/clang/loader.h" #include "frontends/clang/b_frontend_action.h" #include "bpf_module.h" +#include "exported_files.h" #include "kbuild_helper.h" #include "shared_table.h" #include "libbpf.h" @@ -331,9 +332,9 @@ int BPFModule::load_cfile(const string &file, bool in_memory, const char *cflags // Load in a pre-built list of functions into the initial Module object, then // build an ExecutionEngine. -int BPFModule::load_includes(const string &tmpfile) { +int BPFModule::load_includes(const string &text) { clang_loader_ = make_unique(&*ctx_, flags_); - if (clang_loader_->parse(&mod_, &tables_, tmpfile, false, nullptr, 0)) + if (clang_loader_->parse(&mod_, &tables_, text, true, nullptr, 0)) return -1; return 0; } @@ -683,7 +684,12 @@ int BPFModule::load_b(const string &filename, const string &proto_filename) { // Helpers are inlined in the following file (C). Load the definitions and // pass the partially compiled module to the B frontend to continue with. - if (int rc = load_includes(BCC_INSTALL_PREFIX "/share/bcc/include/bcc/helpers.h")) + auto helpers_h = ExportedFiles::headers().find("/virtual/include/bcc/helpers.h"); + if (helpers_h == ExportedFiles::headers().end()) { + fprintf(stderr, "Internal error: missing bcc/helpers.h"); + return -1; + } + if (int rc = load_includes(helpers_h->second)) return rc; b_loader_.reset(new BLoader(flags_)); diff --git a/src/cc/bpf_module.h b/src/cc/bpf_module.h index f9df6f47a4a2..86fbdcf42bb2 100644 --- a/src/cc/bpf_module.h +++ b/src/cc/bpf_module.h @@ -47,7 +47,7 @@ class BPFModule { llvm::Function * make_writer(llvm::Module *mod, llvm::Type *type); void dump_ir(llvm::Module &mod); int load_file_module(std::unique_ptr *mod, const std::string &file, bool in_memory); - int load_includes(const std::string &tmpfile); + int load_includes(const std::string &text); int load_cfile(const std::string &file, bool in_memory, const char *cflags[], int ncflags); int kbuild_flags(const char *uname_release, std::vector *cflags); int run_pass_manager(llvm::Module &mod); diff --git a/src/cc/clang/include/stdarg.h b/src/cc/clang/include/stdarg.h index a57e18364871..e0a43f5ae7b5 100644 --- a/src/cc/clang/include/stdarg.h +++ b/src/cc/clang/include/stdarg.h @@ -1,3 +1,4 @@ +R"********( /*===---- stdarg.h - Variable argument handling ----------------------------=== * * Copyright (c) 2008 Eli Friedman @@ -50,3 +51,4 @@ typedef __builtin_va_list va_list; typedef __builtin_va_list __gnuc_va_list; #endif /* __STDARG_H */ +)********" diff --git a/src/cc/export/helpers.h b/src/cc/export/helpers.h index a75f9f400723..9dfc060cdfc3 100644 --- a/src/cc/export/helpers.h +++ b/src/cc/export/helpers.h @@ -1,3 +1,4 @@ +R"********( /* * Copyright (c) 2015 PLUMgrid, Inc. * @@ -392,3 +393,4 @@ int bpf_num_cpus() asm("llvm.bpf.extra"); #define lock_xadd(ptr, val) ((void)__sync_fetch_and_add(ptr, val)) #endif +)********" diff --git a/src/cc/export/proto.h b/src/cc/export/proto.h index a7fe4606a40c..b2f50ede99f5 100644 --- a/src/cc/export/proto.h +++ b/src/cc/export/proto.h @@ -1,3 +1,4 @@ +R"********( /* * Copyright (c) 2015 PLUMgrid, Inc. * @@ -95,3 +96,4 @@ struct vxlan_t { unsigned int key:24; unsigned int rsv4:8; } BPF_PACKET_HEADER; +)********" diff --git a/src/cc/exported_files.cc b/src/cc/exported_files.cc new file mode 100644 index 000000000000..9dde0147cd93 --- /dev/null +++ b/src/cc/exported_files.cc @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 PLUMgrid, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "exported_files.h" + +using std::map; +using std::string; + +namespace ebpf { + +// c++11 feature for including raw string literals +// see http://www.stroustrup.com/C++11FAQ.html#raw-strings + +map ExportedFiles::headers_ = { + { + "/virtual/include/bcc/proto.h", + #include "export/proto.h" + }, + { + "/virtual/include/bcc/helpers.h", + #include "export/helpers.h" + }, + { + "/virtual/lib/clang/include/stdarg.h", + #include "clang/include/stdarg.h" + }, +}; + +} diff --git a/src/cc/exported_files.h b/src/cc/exported_files.h new file mode 100644 index 000000000000..80a06a76f944 --- /dev/null +++ b/src/cc/exported_files.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016 PLUMgrid, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace ebpf { + +class ExportedFiles { + static std::map headers_; + public: + static const std::map & headers() { return headers_; } +}; + +} diff --git a/src/cc/frontends/clang/kbuild_helper.cc b/src/cc/frontends/clang/kbuild_helper.cc index f60266ec2548..dc1675b1293b 100644 --- a/src/cc/frontends/clang/kbuild_helper.cc +++ b/src/cc/frontends/clang/kbuild_helper.cc @@ -57,7 +57,7 @@ int KBuildHelper::get_flags(const char *uname_machine, vector *cflags) { cflags->push_back("-nostdinc"); cflags->push_back("-isystem"); - cflags->push_back(BCC_INSTALL_PREFIX "/share/bcc/lib/clang/include"); + cflags->push_back("/virtual/lib/clang/include"); cflags->push_back("-I./arch/"+arch+"/include"); cflags->push_back("-Iarch/"+arch+"/include/generated/uapi"); cflags->push_back("-Iarch/"+arch+"/include/generated"); diff --git a/src/cc/frontends/clang/loader.cc b/src/cc/frontends/clang/loader.cc index 7b2de839448e..a138d93abf2d 100644 --- a/src/cc/frontends/clang/loader.cc +++ b/src/cc/frontends/clang/loader.cc @@ -47,6 +47,7 @@ #include "common.h" #include "exception.h" +#include "exported_files.h" #include "kbuild_helper.h" #include "b_frontend_action.h" #include "loader.h" @@ -58,9 +59,16 @@ using std::vector; namespace ebpf { +map> ClangLoader::remapped_files_; + ClangLoader::ClangLoader(llvm::LLVMContext *ctx, unsigned flags) : ctx_(ctx), flags_(flags) -{} +{ + if (remapped_files_.empty()) { + for (auto f : ExportedFiles::headers()) + remapped_files_[f.first] = llvm::MemoryBuffer::getMemBuffer(f.second); + } +} ClangLoader::~ClangLoader() {} @@ -68,6 +76,10 @@ int ClangLoader::parse(unique_ptr *mod, unique_ptr main_buf; struct utsname un; uname(&un); char kdir[256]; @@ -80,7 +92,8 @@ int ClangLoader::parse(unique_ptr *mod, unique_ptr *mod, unique_ptrc_str()); if (cflags) { @@ -156,11 +169,17 @@ int ClangLoader::parse(unique_ptr *mod, unique_ptr(ccargs.data()) + ccargs.size(), diags)) return -1; + // This option instructs clang whether or not to free the file buffers that we + // give to it. Since the embedded header files should be copied fewer times + // and reused if possible, set this flag to true. + invocation1->getPreprocessorOpts().RetainRemappedFileBuffers = true; + for (const auto &f : remapped_files_) + invocation1->getPreprocessorOpts().addRemappedFile(f.first, &*f.second); + if (in_memory) { - invocation1->getPreprocessorOpts().addRemappedFile("", - llvm::MemoryBuffer::getMemBuffer(file).release()); + invocation1->getPreprocessorOpts().addRemappedFile(main_path, &*main_buf); invocation1->getFrontendOpts().Inputs.clear(); - invocation1->getFrontendOpts().Inputs.push_back(FrontendInputFile("", IK_C)); + invocation1->getFrontendOpts().Inputs.push_back(FrontendInputFile(main_path, IK_C)); } invocation1->getFrontendOpts().DisableFree = false; @@ -174,6 +193,7 @@ int ClangLoader::parse(unique_ptr *mod, unique_ptr out_buf = llvm::MemoryBuffer::getMemBuffer(out_str); // this contains the open FDs *tables = bact.take_tables(); @@ -183,10 +203,12 @@ int ClangLoader::parse(unique_ptr *mod, unique_ptr(ccargs.data()) + ccargs.size(), diags)) return -1; CompilerInstance compiler2; - invocation2->getPreprocessorOpts().addRemappedFile("", - llvm::MemoryBuffer::getMemBuffer(out_str).release()); + invocation2->getPreprocessorOpts().RetainRemappedFileBuffers = true; + for (const auto &f : remapped_files_) + invocation2->getPreprocessorOpts().addRemappedFile(f.first, &*f.second); + invocation2->getPreprocessorOpts().addRemappedFile(main_path, &*out_buf); invocation2->getFrontendOpts().Inputs.clear(); - invocation2->getFrontendOpts().Inputs.push_back(FrontendInputFile("", IK_C)); + invocation2->getFrontendOpts().Inputs.push_back(FrontendInputFile(main_path, IK_C)); invocation2->getFrontendOpts().DisableFree = false; // suppress warnings in the 2nd pass, but bail out on errors (our fault) invocation2->getDiagnosticOpts().IgnoreWarnings = true; diff --git a/src/cc/frontends/clang/loader.h b/src/cc/frontends/clang/loader.h index 22c64e1ba811..67b996987d98 100644 --- a/src/cc/frontends/clang/loader.h +++ b/src/cc/frontends/clang/loader.h @@ -23,6 +23,7 @@ namespace llvm { class Module; class LLVMContext; +class MemoryBuffer; } namespace ebpf { @@ -41,6 +42,7 @@ class ClangLoader { int parse(std::unique_ptr *mod, std::unique_ptr> *tables, const std::string &file, bool in_memory, const char *cflags[], int ncflags); private: + static std::map> remapped_files_; llvm::LLVMContext *ctx_; unsigned flags_; };