diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fdb921d..a9ebece5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,14 +31,18 @@ cmake_policy(SET CMP0048 NEW) # set the project name - version is MAJOR.MINOR.PATCH.RELEASE - releases start at 1 # if (DEFINED ENV{VERSION}) - project(ProcDumpForLinux VERSION $ENV{VERSION}) + project(ProcDumpForLinux VERSION $ENV{VERSION} LANGUAGES C CXX) else() - project(ProcDumpForLinux VERSION 0.0.0) + project(ProcDumpForLinux VERSION 0.0.0 LANGUAGES C CXX) endif() set(PROJECT_VERSION_TWEAK 0) file(READ "dist/changelog" CHANGE_LOG) +option(PROCDUMP_DISABLE_SYSTEM_LIBBPF "Don't attempt to use an installed libbpf" OFF) + +include(GNUInstallDirs) + # # enable Debug while pre-release; disable Debug in post-release # @@ -191,8 +195,17 @@ target_include_directories(procdump PUBLIC ${procdump_ebpf_SOURCE_DIR} ) -add_dependencies(procdump libbpf procdump_ebpf) -target_link_libraries(procdump ${libbpf_SOURCE_DIR}/src/libbpf.a elf z pthread) +add_dependencies(procdump procdump_ebpf) + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +find_package(Threads REQUIRED) +find_package(ZLIB REQUIRED) +find_package(Libelf REQUIRED) +target_link_libraries(procdump + Libelf::Libelf + ZLIB::ZLIB + Threads::Threads +) # # Copy integration test directory @@ -235,17 +248,37 @@ add_custom_target(rpm # Make ProcDump eBPF program # -# Fetch libbpf -include(ExternalProject) +# Attempt to use system-installed libbpf +if(NOT PROCDUMP_DISABLE_SYSTEM_LIBBPF) + find_package(Bpf COMPONENTS libbpf) + if(Bpf_FOUND) + set(libbpf_LINK Bpf::libbpf) + set(libbpf_INCLUDE "${Bpf_INCLUDE_DIRS}") + endif() +endif() + +if(NOT Bpf_FOUND) + # Fetch libbpf + include(ExternalProject) + + ExternalProject_Add(libbpf + GIT_REPOSITORY https://github.com/libbpf/libbpf.git + GIT_TAG v1.2.2 + PREFIX ./libbpf + CONFIGURE_COMMAND "" + BUILD_COMMAND + cd ../libbpf/src && + bash -c "CFLAGS=\"-g -O2 -Werror -Wall -fPIC\" make" + INSTALL_COMMAND + cd ../libbpf/src && bash -c "DESTDIR= make install" + ) + set(libbpf_LINK "${libbpf_BINARY_DIR}/usr/${CMAKE_INSTALL_LIBDIR}/libbpf.a") + set(libbpf_INCLUDE "${libbpf_BINARY_DIR}/usr/include") +endif() +# We always need to find the bpftool program +find_package(Bpf REQUIRED COMPONENTS bpftool) -ExternalProject_Add(libbpf - GIT_REPOSITORY https://github.com/libbpf/libbpf.git - GIT_TAG v1.2.2 - PREFIX ./libbpf - CONFIGURE_COMMAND "" - BUILD_COMMAND cd ../libbpf/src && bash -c "CFLAGS=\"-g -O2 -Werror -Wall -fPIC\" make" - INSTALL_COMMAND "" - ) +target_link_libraries(procdump ${libbpf_LINK}) # set binaries and options for clang and llc set(CLANG "clang") @@ -274,19 +307,33 @@ set(CLANG_INCLUDES -I "/usr/include/x86_64-linux-gnu" -I "${CMAKE_SOURCE_DIR}" -I "${CMAKE_BINARY_DIR}" - -I "${libbpf_SOURCE_DIR}/src" + -I "${libbpf_INCLUDE}" ) -add_custom_target(procdump_ebpf - DEPENDS procdump_ebpf.o - ) +add_custom_command(OUTPUT procdump_ebpf.o + COMMAND "${CLANG}" -nostdinc -isystem `gcc -print-file-name=include` ${CLANG_INCLUDES} ${CLANG_DEFINES} -O2 ${CLANG_OPTIONS} -target bpf -fno-stack-protector -c "${procdump_ebpf_SOURCE_DIR}/procdump_ebpf.c" -o "procdump_ebpf.o" + COMMENT "Building EBPF object procdump_ebpf.o" + DEPENDS ${procdump_ebpf_SOURCE_DIR}/procdump_ebpf.c + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} +) +add_custom_command(OUTPUT procdump.ebpf.o + COMMAND Bpf::bpftool gen object procdump.ebpf.o procdump_ebpf.o + COMMENT "Generating procdump.ebpf.o" + DEPENDS procdump_ebpf.o + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} +) -add_dependencies(procdump_ebpf libbpf) +add_custom_command(OUTPUT procdump_ebpf.skel.h + COMMAND Bpf::bpftool gen skeleton "procdump.ebpf.o" name "procdump_ebpf" > "procdump_ebpf.skel.h" + COMMENT "Writing EBPF header procdump_ebpf.skel.h" + DEPENDS procdump.ebpf.o + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} +) -add_custom_command(OUTPUT procdump_ebpf.o - COMMAND "${CLANG}" -nostdinc -isystem `gcc -print-file-name=include` ${CLANG_INCLUDES} ${CLANG_DEFINES} -O2 ${CLANG_OPTIONS} -target bpf -fno-stack-protector -c "${procdump_ebpf_SOURCE_DIR}/procdump_ebpf.c" -o "procdump_ebpf.o" && bpftool gen object procdump.ebpf.o procdump_ebpf.o && bpftool gen skeleton "procdump.ebpf.o" name "procdump_ebpf" > "procdump_ebpf.skel.h" - COMMENT "Building EBPF object procdump_ebpf.o" - DEPENDS ${procdump_ebpf_SOURCE_DIR}/procdump_ebpf.c - ) +add_custom_target(procdump_ebpf DEPENDS + procdump_ebpf.o + procdump.ebpf.o + procdump_ebpf.skel.h +) -set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES procdump.ebpf.o) \ No newline at end of file +add_dependencies(procdump_ebpf ${libbpf_LINK}) diff --git a/cmake/FindBpf.cmake b/cmake/FindBpf.cmake new file mode 100644 index 00000000..825c119d --- /dev/null +++ b/cmake/FindBpf.cmake @@ -0,0 +1,138 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindBpf +---------- + +Find libbpf headers and library, and bpftool executable. + +Imported Targets +^^^^^^^^^^^^^^^^ + +``Bpf::libbpf`` + The libbpf library, if found. +``Bpf::bpftool`` + The bpftool executable, if found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This will define some or all of the following variables +in your project (depending on components selected): + +``Bpf_FOUND`` + true if (the requested version of) libbpf and/or the bpftool + program are available. +``Bpf_VERSION`` + the version of libbpf. +``Bpf_LIBRARIES`` + the libraries to link against to use libbpf. +``Bpf_INCLUDE_DIRS`` + where to find the libbpf headers. +``Bpf_COMPILE_OPTIONS`` + this should be passed to target_compile_options(), if the + target is not used for linking +``Bpf_BPFTOOL_EXECUTABLE`` + the location of the bpftool binary. + +#]=======================================================================] + +if(NOT Bpf_FIND_COMPONENTS) + set(Bpf_FIND_COMPONENTS libbpf bpftool) +endif() +set(_required) + +if(libbpf IN_LIST Bpf_FIND_COMPONENTS) + # Use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig QUIET) + pkg_check_modules(PKG_Bpf QUIET libbpf) + + set(Bpf_COMPILE_OPTIONS ${PKG_Bpf_CFLAGS_OTHER}) + set(Bpf_VERSION ${PKG_Bpf_VERSION}) + + find_path(Bpf_INCLUDE_DIR + NAMES + bpf/libbpf.h + HINTS + ${PKG_Bpf_INCLUDE_DIRS} + ) + mark_as_advanced(Bpf_INCLUDE_DIR) + + find_library(Bpf_LIBRARY + NAMES + bpf + HINTS + ${PKG_Bpf_LIBRARY_DIRS} + ) + mark_as_advanced(Bpf_LIBRARY) + + if(Bpf_INCLUDE_DIR AND Bpf_LIBRARY) + set(Bpf_libbpf_FOUND TRUE) + endif() + + list(APPEND _required Bpf_LIBRARY Bpf_INCLUDE_DIR) + set(_version Bpf_VERSION) + + set(Bpf_LIBRARIES ${Bpf_LIBRARY}) + set(Bpf_INCLUDE_DIRS ${Bpf_INCLUDE_DIR}) +endif() + +if(bpftool IN_LIST Bpf_FIND_COMPONENTS) + find_program(Bpf_BPFTOOL_EXECUTABLE + NAMES + bpftool + ) + mark_as_advanced(Bpf_BPFTOOL_EXECUTABLE) + + if(Bpf_BPFTOOL_EXECUTABLE) + set(Bpf_bpftool_FOUND TRUE) + endif() + list(APPEND _required Bpf_BPFTOOL_EXECUTABLE) + set(Bpf_BPFTOOL_EXECUTABLE ${Bpf_BPFTOOL_EXECUTABLE}) +endif() + +include(FindPackageHandleStandardArgs) + +# From CMake 3.18, HANDLE_COMPONENTS makes REQUIRED_VARS optional +if(CMAKE_VERSION VERSION_LESS "3.18") + set(_required_vars + REQUIRED_VARS + ${_required} + ) +else() + set(_required_vars) +endif() + +if(DEFINED _version) + set(_version_var + VERSION_VAR ${_version} + ) +else() + set(_version_var) +endif() + +find_package_handle_standard_args(Bpf + FOUND_VAR + Bpf_FOUND + ${_version_var} + ${_required_vars} + HANDLE_COMPONENTS +) + +if(Bpf_FOUND AND Bpf_LIBRARY AND NOT TARGET Bpf::libbpf) + add_library(Bpf::libbpf UNKNOWN IMPORTED) + set_target_properties(Bpf::libbpf PROPERTIES + IMPORTED_LOCATION "${Bpf_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${Bpf_COMPILE_OPTIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${Bpf_INCLUDE_DIR}" + ) +endif() + +if(Bpf_FOUND AND Bpf_BPFTOOL_EXECUTABLE AND NOT TARGET Bpf::bpftool) + add_executable(Bpf::bpftool IMPORTED) + set_target_properties(Bpf::bpftool PROPERTIES + IMPORTED_LOCATION "${Bpf_BPFTOOL_EXECUTABLE}" + ) +endif() diff --git a/cmake/FindLibelf.cmake b/cmake/FindLibelf.cmake new file mode 100644 index 00000000..fe11e267 --- /dev/null +++ b/cmake/FindLibelf.cmake @@ -0,0 +1,82 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindLibelf +---------- + +Find libelf headers and library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +``Libelf::Libelf`` + The libelf library, if found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This will define the following variables in your project: + +``Libelf_FOUND`` + true if (the requested version of) Libelf is available. +``Libelf_VERSION`` + the version of Libelf. +``Libelf_LIBRARIES`` + the libraries to link against to use Libelf. +``Libelf_INCLUDE_DIRS`` + where to find the Libelf headers. +``Libelf_COMPILE_OPTIONS`` + this should be passed to target_compile_options(), if the + target is not used for linking + +#]=======================================================================] + + +# Use pkg-config to get the directories and then use these values +# in the FIND_PATH() and FIND_LIBRARY() calls +find_package(PkgConfig QUIET) +pkg_check_modules(PKG_Libelf QUIET libelf) + +set(Libelf_COMPILE_OPTIONS ${PKG_Libelf_CFLAGS_OTHER}) +set(Libelf_VERSION ${PKG_Libelf_VERSION}) + +find_path(Libelf_INCLUDE_DIR + NAMES + libelf.h + HINTS + ${PKG_Libelf_INCLUDE_DIRS} +) +find_library(Libelf_LIBRARY + NAMES + elf + HINTS + ${PKG_Libelf_LIBRARY_DIRS} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Libelf + FOUND_VAR + Libelf_FOUND + REQUIRED_VARS + Libelf_LIBRARY + Libelf_INCLUDE_DIR + VERSION_VAR + Libelf_VERSION +) + +if(Libelf_FOUND AND NOT TARGET Libelf::Libelf) + add_library(Libelf::Libelf UNKNOWN IMPORTED) + set_target_properties(Libelf::Libelf PROPERTIES + IMPORTED_LOCATION "${Libelf_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${Libelf_COMPILE_OPTIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${Libelf_INCLUDE_DIR}" + ) +endif() + +mark_as_advanced(Libelf_LIBRARY Libelf_INCLUDE_DIR) + +if(Libelf_FOUND) + set(Libelf_LIBRARIES ${Libelf_LIBRARY}) + set(Libelf_INCLUDE_DIRS ${Libelf_INCLUDE_DIR}) +endif() diff --git a/ebpf/procdump_ebpf.h b/ebpf/procdump_ebpf.h index 26ae33ad..63e3c53a 100644 --- a/ebpf/procdump_ebpf.h +++ b/ebpf/procdump_ebpf.h @@ -18,8 +18,8 @@ #define __PROCDUMP_EBPF_H__ #include "vmlinux.h" -#include -#include +#include +#include #define USER_STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK) #define ARGS_HASH_SIZE 10240 @@ -66,4 +66,4 @@ struct { __uint(max_entries, 10 * 1024 * 1024 /* 10 MB */); } ringBuffer SEC(".maps"); -#endif // __PROCDUMP_EBPF_H__ \ No newline at end of file +#endif // __PROCDUMP_EBPF_H__