From 2055f3557696ce931f7afff079c1751f9d79b68b Mon Sep 17 00:00:00 2001 From: Alessandro Gario Date: Sat, 30 Apr 2022 21:41:30 +0200 Subject: [PATCH 1/2] cmake: Initial commit --- .github/workflows/main.yml | 170 ++++++++++++++++++ .github/workflows/posix.yml | 212 +++++++++++++++++++++++ .github/workflows/windows.yml | 79 +++++++++ .gitmodules | 3 + CMakeLists.txt | 25 +++ cmake/options.cmake | 20 +++ cmake/packaging.cmake | 61 +++++++ cmake/platform.cmake | 17 ++ cmake/settings.cmake | 94 ++++++++++ cmake/version.cmake | 9 + vm/CMakeLists.txt | 123 +++++++++++++ vm/compat/CMakeLists.txt | 42 +++++ vm/compat/libraries/CMakeLists.txt | 9 + vm/compat/libraries/win-c/CMakeLists.txt | 24 +++ vm/compat/libraries/win-c/src | 1 + vm/compat/macos/endian.h | 29 ++++ vm/compat/windows/endian.h | 29 ++++ vm/compat/windows/sys/mman.c | 37 ++++ vm/compat/windows/sys/mman.h | 24 +++ vm/compat/windows/unistd.c | 39 +++++ vm/compat/windows/unistd.h | 16 ++ vm/inc/ubpf.h | 5 + vm/test.c | 19 +- vm/ubpf_config.h.inc | 11 ++ vm/ubpf_loader.c | 8 + vm/ubpf_vm.c | 1 + 26 files changed, 1103 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/posix.yml create mode 100644 .github/workflows/windows.yml create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 cmake/options.cmake create mode 100644 cmake/packaging.cmake create mode 100644 cmake/platform.cmake create mode 100644 cmake/settings.cmake create mode 100644 cmake/version.cmake create mode 100644 vm/CMakeLists.txt create mode 100644 vm/compat/CMakeLists.txt create mode 100644 vm/compat/libraries/CMakeLists.txt create mode 100644 vm/compat/libraries/win-c/CMakeLists.txt create mode 160000 vm/compat/libraries/win-c/src create mode 100644 vm/compat/macos/endian.h create mode 100644 vm/compat/windows/endian.h create mode 100644 vm/compat/windows/sys/mman.c create mode 100644 vm/compat/windows/sys/mman.h create mode 100644 vm/compat/windows/unistd.c create mode 100644 vm/compat/windows/unistd.h create mode 100644 vm/ubpf_config.h.inc diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..c3e325df --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,170 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +name: Main + +on: + schedule: + - cron: '00 21 * * *' + + push: + branches: + - '*' + + pull_request: + branches: + - '*' + +concurrency: + group: main-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + +jobs: + windows_release: + uses: ./.github/workflows/windows.yml + with: + platform: windows-latest + build_type: RelWithDebInfo + upload_packages: true + + windows_debug: + uses: ./.github/workflows/windows.yml + with: + platform: windows-latest + build_type: Debug + upload_packages: true + + macos_release: + uses: ./.github/workflows/posix.yml + with: + platform: macos-11 + build_type: RelWithDebInfo + enable_sanitizers: false + enable_coverage: false + scan_build: false + upload_packages: true + + macos_release_coverage: + uses: ./.github/workflows/posix.yml + with: + platform: macos-11 + build_type: RelWithDebInfo + enable_sanitizers: false + enable_coverage: true + scan_build: false + upload_packages: false + + macos_release_sanitizers: + uses: ./.github/workflows/posix.yml + with: + platform: macos-11 + build_type: RelWithDebInfo + enable_sanitizers: true + enable_coverage: false + scan_build: false + upload_packages: false + + macos_debug: + uses: ./.github/workflows/posix.yml + with: + platform: macos-11 + build_type: Debug + enable_sanitizers: false + enable_coverage: false + scan_build: false + upload_packages: false + + macos_debug_coverage: + uses: ./.github/workflows/posix.yml + with: + platform: macos-11 + build_type: Debug + enable_sanitizers: false + enable_coverage: true + scan_build: false + upload_packages: false + + macos_debug_sanitizers: + uses: ./.github/workflows/posix.yml + with: + platform: macos-11 + build_type: Debug + enable_sanitizers: true + enable_coverage: false + scan_build: false + upload_packages: false + + linux_release: + uses: ./.github/workflows/posix.yml + with: + platform: ubuntu-20.04 + build_type: RelWithDebInfo + enable_sanitizers: false + enable_coverage: false + scan_build: false + upload_packages: true + + linux_release_scan_build: + uses: ./.github/workflows/posix.yml + with: + platform: ubuntu-20.04 + build_type: RelWithDebInfo + enable_sanitizers: false + enable_coverage: false + scan_build: true + upload_packages: false + + linux_release_coverage: + uses: ./.github/workflows/posix.yml + with: + platform: ubuntu-20.04 + build_type: RelWithDebInfo + enable_sanitizers: false + enable_coverage: true + scan_build: false + upload_packages: false + + linux_release_sanitizers: + uses: ./.github/workflows/posix.yml + with: + platform: ubuntu-20.04 + build_type: RelWithDebInfo + enable_sanitizers: true + enable_coverage: false + scan_build: false + upload_packages: false + + linux_debug: + uses: ./.github/workflows/posix.yml + with: + platform: ubuntu-20.04 + build_type: Debug + enable_sanitizers: false + enable_coverage: false + scan_build: false + upload_packages: false + + linux_debug_coverage: + uses: ./.github/workflows/posix.yml + with: + platform: ubuntu-20.04 + build_type: Debug + enable_sanitizers: false + enable_coverage: true + scan_build: false + upload_packages: false + + linux_debug_sanitizers: + uses: ./.github/workflows/posix.yml + with: + platform: ubuntu-20.04 + build_type: Debug + enable_sanitizers: true + enable_coverage: false + scan_build: false + upload_packages: false diff --git a/.github/workflows/posix.yml b/.github/workflows/posix.yml new file mode 100644 index 00000000..0ec19685 --- /dev/null +++ b/.github/workflows/posix.yml @@ -0,0 +1,212 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +name: Posix + +on: + workflow_call: + inputs: + platform: + required: true + type: string + + build_type: + required: true + type: string + + enable_sanitizers: + required: true + type: boolean + + enable_coverage: + required: true + type: boolean + + scan_build: + required: true + type: boolean + + upload_packages: + required: true + type: boolean + +jobs: + build: + runs-on: ${{ inputs.platform }} + + steps: + - uses: actions/checkout@v3 + + - name: Generate the cache key + id: cache_key + run: echo ::set-output name=VALUE::platform-${{ inputs.platform }}_type-${{ inputs.build_type }}_sanitizers-${{ inputs.enable_sanitizers }}_coverage-${{ inputs.enable_coverage }}_scan_build-${{ inputs.scan_build }} + + - name: Update the cache (ccache) + uses: actions/cache@v1.0.3 + with: + path: ccache + key: ${{ steps.cache_key.outputs.VALUE }}_ccache + + - name: Create the build folders + run: | + mkdir -p \ + ccache + + - name: Install system dependencies (Linux) + if: inputs.platform == 'ubuntu-20.04' + run: | + sudo apt-get install -y \ + ccache \ + ninja-build \ + cmake + + if [[ "${{ inputs.scan_build }}" == "true" ]] ; then + sudo apt-get install -y \ + clang-tools + fi + + - name: Install system dependencies (macOS) + if: inputs.platform == 'macos-11' + run: | + brew install \ + cmake \ + ninja \ + ccache + + - name: Configure the project + run: | + export CCACHE_DIR="$(pwd)/ccache" + + if [[ "${{ inputs.scan_build }}" == "true" ]] ; then + mkdir scan_build_report + command_prefix="scan-build -o scan_build_report" + fi + + ${command_prefix} cmake \ + -G Ninja \ + -S . \ + -B build \ + -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \ + -DUBPF_ENABLE_COVERAGE=${{ inputs.enable_sanitizers }} \ + -DUBPF_ENABLE_SANITIZERS=${{ inputs.enable_coverage }} \ + -DUBPF_ENABLE_TESTS=true \ + -DUBPF_ENABLE_INSTALL=true + + - name: Build the project + run: | + export CCACHE_DIR="$(pwd)/ccache" + + if [[ "${{ inputs.scan_build }}" == "true" ]] ; then + command_prefix="scan-build -o scan_build_report" + fi + + ${command_prefix} cmake \ + --build build \ + -- -v + + - name: Upload scan-build report + if: inputs.scan_build == true + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: scan-build_report + path: ${{github.workspace}}/scan_build_report + retention-days: 5 + + - name: Run the tests + run: | + cmake \ + --build build \ + --target test \ + -- -v + + - name: Run the install target + run: | + mkdir install + export DESTDIR=$(pwd)/install + + cmake \ + --build build \ + --target install + + - name: Generate the DEB package + if: inputs.platform == 'ubuntu-20.04' + run: | + cmake \ + -S . \ + -B build \ + -DUBPF_ENABLE_PACKAGE=true \ + -DCPACK_GENERATOR=DEB + + cmake \ + --build build \ + --target package + + - name: Generate the RPM package + if: inputs.platform == 'ubuntu-20.04' + run: | + cmake \ + -S . \ + -B build \ + -DUBPF_ENABLE_PACKAGE=true \ + -DCPACK_GENERATOR=RPM + + cmake \ + --build build \ + --target package + + - name: Generate the TGZ package + run: | + cmake \ + -S . \ + -B build \ + -DUBPF_ENABLE_PACKAGE=true \ + -DCPACK_GENERATOR=TGZ + + cmake \ + --build build \ + --target package + + - name: Locate the packages + id: package_locations + if: inputs.upload_packages == true + run: | + echo ::set-output name=REL_DEB_PACKAGE_PATH::$(ls build/*.deb) + echo ::set-output name=REL_RPM_PACKAGE_PATH::$(ls build/*.rpm) + echo ::set-output name=REL_TGZ_PACKAGE_PATH::$(ls build/*.tar.gz) + + - name: Upload the DEB package + if: inputs.upload_packages == true && inputs.platform == 'ubuntu-20.04' + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: linux_deb_package + path: ${{ steps.package_locations.outputs.REL_DEB_PACKAGE_PATH }} + retention-days: 5 + + - name: Upload the RPM package + if: inputs.upload_packages == true && inputs.platform == 'ubuntu-20.04' + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: linux_rpm_package + path: ${{ steps.package_locations.outputs.REL_RPM_PACKAGE_PATH }} + retention-days: 5 + + - name: Upload the Linux TGZ package + if: inputs.upload_packages == true && inputs.platform == 'ubuntu-20.04' + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: linux_tgz_package + path: ${{ steps.package_locations.outputs.REL_TGZ_PACKAGE_PATH }} + retention-days: 5 + + - name: Upload the macOS TGZ package + if: inputs.upload_packages == true && inputs.platform == 'macos-11' + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: macos_tgz_package + path: ${{ steps.package_locations.outputs.REL_TGZ_PACKAGE_PATH }} + retention-days: 5 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 00000000..94956a46 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,79 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +name: Windows + +on: + workflow_call: + inputs: + platform: + required: true + type: string + + build_type: + required: true + type: string + + upload_packages: + required: true + type: boolean + +jobs: + build: + runs-on: ${{ inputs.platform }} + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Configure the project + run: | + cmake ` + -S . ` + -B build ` + -DUBPF_ENABLE_TESTS=true ` + -DUBPF_ENABLE_INSTALL=true + + - name: Build the project + run: | + cmake ` + --build build ` + --config ${{ inputs.build_type }} + + - name: Run the tests + working-directory: build + run: | + ctest -C ${{ inputs.build_type }} -V + + - name: Generate the TGZ package + run: | + cmake ` + -S . ` + -B build ` + -DUBPF_ENABLE_PACKAGE=true ` + -DCPACK_GENERATOR=TGZ + + cmake ` + --build build ` + --target package + + - name: Locate the packages + id: package_locations + if: inputs.upload_packages == true + shell: bash + run: | + echo ::set-output name=REL_TGZ_PACKAGE_PATH::$(ls build/*.tar.gz) + + - name: Upload the Windows TGZ package + if: inputs.upload_packages == true + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: windows_tgz_package + path: ${{ steps.package_locations.outputs.REL_TGZ_PACKAGE_PATH }} + retention-days: 5 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..5f1c9068 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vm/compat/libraries/win-c/src"] + path = vm/compat/libraries/win-c/src + url = https://github.com/takamin/win-c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..55424e56 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +project("ubpf") +cmake_minimum_required(VERSION 3.16) + +include("cmake/platform.cmake") +include("cmake/settings.cmake") +include("cmake/options.cmake") +include("cmake/version.cmake") + +if(UBPF_ENABLE_TESTS) + include("CTest") +endif() + +add_subdirectory("vm") + +if(UBPF_ENABLE_PACKAGE) + include("cmake/packaging.cmake") +endif() diff --git a/cmake/options.cmake b/cmake/options.cmake new file mode 100644 index 00000000..6b32c6ad --- /dev/null +++ b/cmake/options.cmake @@ -0,0 +1,20 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +if(PLATFORM_LINUX OR PLATFORM_MACOS) + option(UBPF_ENABLE_COVERAGE "Set to true to enable coverage flags") + option(UBPF_ENABLE_SANITIZERS "Set to true to enable the address and undefined sanitizers") +endif() + +option(UBPF_ENABLE_INSTALL "Set to true to enable the install targets") +option(UBPF_ENABLE_TESTS "Set to true to enable tests") +option(UBPF_ENABLE_PACKAGE "Set to true to enable packaging") + +# Note that the compile_commands.json file is only exporter when +# using the Ninja or Makefile generator +set(CMAKE_EXPORT_COMPILE_COMMANDS true CACHE BOOL "Set to true to generate the compile_commands.json file (forced on)" FORCE) diff --git a/cmake/packaging.cmake b/cmake/packaging.cmake new file mode 100644 index 00000000..656562a7 --- /dev/null +++ b/cmake/packaging.cmake @@ -0,0 +1,61 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +if(NOT CPACK_GENERATOR) + message(FATAL_ERROR "ubpf - No generator selected") +endif() + +set(CPACK_PACKAGE_VERSION "${UBPF_VERSION}") +set(CPACK_PACKAGE_DESCRIPTION "Userspace eBPF VM") +set(CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}") +set(CPACK_PACKAGE_VENDOR "IO Visor Project") +set(CPACK_PACKAGE_CONTACT "contact-us@iovisor.org") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://www.iovisor.org") +set(CPACK_PACKAGE_RELOCATABLE ON) +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE-APACHE") +set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") + +if(CPACK_GENERATOR STREQUAL "DEB") + set(CPACK_STRIP_FILES ON) + set(CPACK_DEBIAN_UBPF_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") + set(CPACK_DEBIAN_PACKAGE_RELEASE "${CPACK_PACKAGE_VERSION}") + set(CPACK_DEBIAN_UBPF_FILE_NAME "DEB-DEFAULT") + set(CPACK_DEBIAN_PACKAGE_PRIORITY "extra") + set(CPACK_DEBIAN_PACKAGE_SECTION "default") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>=2.31), zlib1g") + set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CPACK_PACKAGE_HOMEPAGE_URL}") + + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CPACK_DEB_COMPONENT_INSTALL ON) + set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON) + endif() + +elseif(CPACK_GENERATOR STREQUAL "RPM") + set(CPACK_STRIP_FILES ON) + set(CPACK_RPM_PACKAGE_RELEASE "${CPACK_PACKAGE_VERSION}") + set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") + set(CPACK_RPM_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}") + set(CPACK_RPM_PACKAGE_GROUP "default") + set(CPACK_RPM_PACKAGE_LICENSE "Apache 2.0") + set(CPACK_RPM_PACKAGE_REQUIRES "glibc >= 2.31, zlib") + + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CPACK_RPM_DEBUGINFO_PACKAGE ON) + set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/usr/src/debug/ubpf") + set(CPACK_RPM_DEBUGINFO_FILE_NAME "RPM-DEFAULT") + endif() + +elseif(CPACK_GENERATOR STREQUAL "TGZ") + set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0) + + if(NOT PLATFORM_WINDOWS) + set(CPACK_SET_DESTDIR ON) + endif() +endif() + +include("CPack") diff --git a/cmake/platform.cmake b/cmake/platform.cmake new file mode 100644 index 00000000..035cd666 --- /dev/null +++ b/cmake/platform.cmake @@ -0,0 +1,17 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(PLATFORM_WINDOWS true) + +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(PLATFORM_MACOS true) + +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(PLATFORM_LINUX true) +endif() diff --git a/cmake/settings.cmake b/cmake/settings.cmake new file mode 100644 index 00000000..3406c94f --- /dev/null +++ b/cmake/settings.cmake @@ -0,0 +1,94 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +add_library("ubpf_settings" INTERFACE) + +# Only configure our settings target if we are being built directly. +# If we are being used as a submodule, give a chance to the parent +# project to use the settings they want. +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + if(PLATFORM_LINUX OR PLATFORM_MACOS) + target_compile_options("ubpf_settings" INTERFACE + -Wall + -Werror + -Iinc + -O2 + -Wunused-parameter + -fPIC + ) + + if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR + CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + + target_compile_options("ubpf_settings" INTERFACE + -g + ) + endif() + + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_definitions("ubpf_settings" INTERFACE + DEBUG + ) + endif() + + if(UBPF_ENABLE_COVERAGE) + target_compile_options("ubpf_settings" INTERFACE + -fprofile-arcs + -ftest-coverage + ) + + target_link_options("ubpf_settings" INTERFACE + -fprofile-arcs + ) + endif() + + if(UBPF_ENABLE_SANITIZERS) + set(sanitizer_flags + -fno-omit-frame-pointer + -fsanitize=undefined,address + ) + + target_compile_options("ubpf_settings" INTERFACE + ${sanitizer_flags} + ) + + target_link_options("ubpf_settings" INTERFACE + ${sanitizer_flags} + ) + endif() + + elseif(PLATFORM_WINDOWS) + set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION "8.1") + + target_compile_options("ubpf_settings" INTERFACE + /W4 + ) + + target_compile_definitions("ubpf_settings" INTERFACE + UNICODE + _UNICODE + + $<$:DEBUG> + $<$:NDEBUG> + $<$:NDEBUG> + ) + + else() + message(WARNING "ubpf - Unsupported platform") + endif() +endif() + +if(UBPF_ENABLE_INSTALL) + install( + TARGETS + "ubpf_settings" + + EXPORT + "ubpf" + ) +endif() diff --git a/cmake/version.cmake b/cmake/version.cmake new file mode 100644 index 00000000..a9361bbf --- /dev/null +++ b/cmake/version.cmake @@ -0,0 +1,9 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +set(UBPF_VERSION "1.0.0") diff --git a/vm/CMakeLists.txt b/vm/CMakeLists.txt new file mode 100644 index 00000000..eff6094f --- /dev/null +++ b/vm/CMakeLists.txt @@ -0,0 +1,123 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +include("CheckLibraryExists") +include("GNUInstallDirs") + +find_path(UBPF_ELF_H_PATH "elf.h" NO_CACHE) +if(UBPF_ELF_H_PATH) + set(UBPF_HAS_ELF_H true) + +else() + message(WARNING "ubpf - elf.h was not found, disabling ELF support") +endif() + +configure_file( + ubpf_config.h.inc + "${CMAKE_CURRENT_BINARY_DIR}/ubpf_config.h" +) + +set(public_header_list + inc/ubpf.h + "${CMAKE_CURRENT_BINARY_DIR}/ubpf_config.h" +) + +add_library("ubpf" + ${public_header_list} + + ebpf.h + ubpf_int.h + ubpf_jit_arm64.c + ubpf_jit.c + ubpf_jit_x86_64.c + ubpf_jit_x86_64.h + ubpf_loader.c + ubpf_vm.c +) + +target_link_libraries("ubpf" + PRIVATE + "ubpf_settings" +) + +target_include_directories("ubpf" PUBLIC + $ + $ + $ +) + +set_target_properties("ubpf" PROPERTIES + PUBLIC_HEADER + "${public_header_list}" +) + +if(PLATFORM_LINUX) + check_library_exists("m" "pow" "" "libm_found") + + if(libm_found) + target_link_libraries("ubpf" + PUBLIC + "m" + ) + endif() +endif() + +if(UBPF_ENABLE_TESTS) + add_executable("ubpf_test" + test.c + ) + + target_link_libraries("ubpf_test" + PRIVATE + "ubpf_settings" + "ubpf" + ) +endif() + +add_subdirectory("compat") + +if(TARGET "ubpf_compat") + target_link_libraries("ubpf" PRIVATE + $ + ) + + target_link_libraries("ubpf_test" PRIVATE + $ + ) +endif() + + +if(UBPF_ENABLE_INSTALL) + install( + TARGETS + "ubpf" + + EXPORT + "ubpf" + + LIBRARY DESTINATION + "${CMAKE_INSTALL_LIBDIR}" + + PUBLIC_HEADER DESTINATION + "${CMAKE_INSTALL_INCLUDEDIR}" + ) + + install( + EXPORT + "ubpf" + + DESTINATION + "${CMAKE_INSTALL_LIBDIR}/cmake/ubpf" + + NAMESPACE + "ubpf::" + + FILE + "ubpfConfig.cmake" + ) +endif() diff --git a/vm/compat/CMakeLists.txt b/vm/compat/CMakeLists.txt new file mode 100644 index 00000000..89dc0956 --- /dev/null +++ b/vm/compat/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +if(PLATFORM_WINDOWS) + add_subdirectory("libraries") + + add_library("ubpf_compat" INTERFACE) + target_sources("ubpf_compat" INTERFACE + windows/sys/mman.h + windows/sys/mman.c + + windows/endian.h + + windows/unistd.h + windows/unistd.c + ) + + target_include_directories("ubpf_compat" INTERFACE + windows + ) + + target_link_libraries("ubpf_compat" INTERFACE + "external::win-c" + "Ws2_32.lib" + ) + +elseif(PLATFORM_MACOS) + add_library("ubpf_compat" INTERFACE) + + target_sources("ubpf_compat" INTERFACE + macos/endian.h + ) + + target_include_directories("ubpf_compat" INTERFACE + macos + ) +endif() diff --git a/vm/compat/libraries/CMakeLists.txt b/vm/compat/libraries/CMakeLists.txt new file mode 100644 index 00000000..1d090e3b --- /dev/null +++ b/vm/compat/libraries/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +add_subdirectory("win-c") diff --git a/vm/compat/libraries/win-c/CMakeLists.txt b/vm/compat/libraries/win-c/CMakeLists.txt new file mode 100644 index 00000000..8fda0885 --- /dev/null +++ b/vm/compat/libraries/win-c/CMakeLists.txt @@ -0,0 +1,24 @@ +# +# Copyright (c) 2022-present, IO Visor Project +# All rights reserved. +# +# This source code is licensed in accordance with the terms specified in +# the LICENSE file found in the root directory of this source tree. +# + +set(library_root "${CMAKE_CURRENT_SOURCE_DIR}/src") + +add_library("win-c" EXCLUDE_FROM_ALL + ${library_root}/include/getopt.h + ${library_root}/source/getopt.c +) + +target_include_directories("win-c" PUBLIC + ${library_root}/include +) + +target_link_libraries("win-c" PRIVATE + "ubpf_settings" +) + +add_library("external::win-c" ALIAS "win-c") diff --git a/vm/compat/libraries/win-c/src b/vm/compat/libraries/win-c/src new file mode 160000 index 00000000..29a86ef6 --- /dev/null +++ b/vm/compat/libraries/win-c/src @@ -0,0 +1 @@ +Subproject commit 29a86ef6ce6b0ef22742ba0ba7ef7d71c96da578 diff --git a/vm/compat/macos/endian.h b/vm/compat/macos/endian.h new file mode 100644 index 00000000..1485f323 --- /dev/null +++ b/vm/compat/macos/endian.h @@ -0,0 +1,29 @@ +/* + Copyright (c) 2022-present, IO Visor Project + All rights reserved. + + This source code is licensed in accordance with the terms specified in + the LICENSE file found in the root directory of this source tree. +*/ + +#pragma once + +#include + +#define htole16(value) \ + OSSwapHostToLittleInt16(value) + +#define htole32(value) \ + OSSwapHostToLittleInt32(value) + +#define htole64(value) \ + OSSwapHostToLittleInt64(value) + +#define htobe16(value) \ + OSSwapHostToBigInt16(value) + +#define htobe32(value) \ + OSSwapHostToBigInt32(value) + +#define htobe64(value) \ + OSSwapHostToBigInt64(value) diff --git a/vm/compat/windows/endian.h b/vm/compat/windows/endian.h new file mode 100644 index 00000000..7cbc3b77 --- /dev/null +++ b/vm/compat/windows/endian.h @@ -0,0 +1,29 @@ +/* + Copyright (c) 2022-present, IO Visor Project + All rights reserved. + + This source code is licensed in accordance with the terms specified in + the LICENSE file found in the root directory of this source tree. +*/ + +#pragma once + +#include + +#define htole16(value) \ + (value) + +#define htole32(value) \ + (value) + +#define htole64(value) \ + (value) + +#define htobe16(value) \ + htons(value) + +#define htobe32(value) \ + htonl(value) + +#define htobe64(value) \ + htonll(value) diff --git a/vm/compat/windows/sys/mman.c b/vm/compat/windows/sys/mman.c new file mode 100644 index 00000000..8c6af238 --- /dev/null +++ b/vm/compat/windows/sys/mman.c @@ -0,0 +1,37 @@ +/* + Copyright (c) 2022-present, IO Visor Project + All rights reserved. + + This source code is licensed in accordance with the terms specified in + the LICENSE file found in the root directory of this source tree. +*/ + +#include "mman.h" + +#include + +void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { + (void) addr; + (void) length; + (void) prot; + (void) flags; + (void) fd; + (void) offset; + + return NULL; +} + +int munmap(void *addr, size_t length) { + (void) addr; + (void) length; + + return 0; +} + +int mprotect(void *addr, size_t len, int prot) { + (void) addr; + (void) len; + (void) prot; + + return 0; +} diff --git a/vm/compat/windows/sys/mman.h b/vm/compat/windows/sys/mman.h new file mode 100644 index 00000000..7176b27a --- /dev/null +++ b/vm/compat/windows/sys/mman.h @@ -0,0 +1,24 @@ +/* + Copyright (c) 2022-present, IO Visor Project + All rights reserved. + + This source code is licensed in accordance with the terms specified in + the LICENSE file found in the root directory of this source tree. +*/ + +#pragma once + +#include + +#define PROT_READ 0 +#define PROT_WRITE 0 +#define MAP_PRIVATE 0 +#define MAP_ANONYMOUS 0 +#define MAP_FAILED NULL +#define PROT_EXEC 0 + +typedef int64_t off_t; + +void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); +int munmap(void *addr, size_t length); +int mprotect(void *addr, size_t len, int prot); diff --git a/vm/compat/windows/unistd.c b/vm/compat/windows/unistd.c new file mode 100644 index 00000000..20c98130 --- /dev/null +++ b/vm/compat/windows/unistd.c @@ -0,0 +1,39 @@ +/* + Copyright (c) 2022-present, IO Visor Project + All rights reserved. + + This source code is licensed in accordance with the terms specified in + the LICENSE file found in the root directory of this source tree. +*/ + +#include "unistd.h" + +#define _CRT_RAND_S +#include + +#include + +int rand_r(unsigned int *seedp) { + (void) seedp; + + unsigned int value = 0; + rand_s(&value); + + return (int) value; +} + +int vasprintf(char **strp, const char *fmt, va_list ap) { + int buffer_size = vsnprintf(NULL, 0, fmt, ap); + if (buffer_size < 0) { + return -1; + } + + buffer_size++; + + *strp = (char *) malloc(buffer_size); + if (*strp == NULL) { + return -1; + } + + return vsprintf_s(*strp, buffer_size, fmt, ap); +} diff --git a/vm/compat/windows/unistd.h b/vm/compat/windows/unistd.h new file mode 100644 index 00000000..cb1c58f4 --- /dev/null +++ b/vm/compat/windows/unistd.h @@ -0,0 +1,16 @@ +/* + Copyright (c) 2022-present, IO Visor Project + All rights reserved. + + This source code is licensed in accordance with the terms specified in + the LICENSE file found in the root directory of this source tree. +*/ + +#pragma once + +#include + +#define STDIN_FILENO 0 + +int rand_r(unsigned int *seedp); +int vasprintf(char **strp, const char *fmt, va_list ap); diff --git a/vm/inc/ubpf.h b/vm/inc/ubpf.h index ca8c8265..a368a8d2 100644 --- a/vm/inc/ubpf.h +++ b/vm/inc/ubpf.h @@ -17,6 +17,8 @@ #ifndef UBPF_H #define UBPF_H +#include + #include #include #include @@ -108,7 +110,10 @@ void ubpf_unload_code(struct ubpf_vm *vm); * Returns 0 on success, -1 on error. In case of error a pointer to the error * message will be stored in 'errmsg' and should be freed by the caller. */ + +#if defined(UBPF_HAS_ELF_H) int ubpf_load_elf(struct ubpf_vm *vm, const void *elf, size_t elf_len, char **errmsg); +#endif int ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len, uint64_t* bpf_return_value); diff --git a/vm/test.c b/vm/test.c index 6b476aa4..d8c55ac2 100644 --- a/vm/test.c +++ b/vm/test.c @@ -15,6 +15,8 @@ * limitations under the License. */ +#include + #define _GNU_SOURCE #include #include @@ -24,10 +26,13 @@ #include #include #include -#include #include #include "ubpf.h" +#if defined(UBPF_HAS_ELF_H) +#include +#endif + void ubpf_set_register_offset(int x); static void *readfile(const char *path, size_t maxlen, size_t *len); static void register_functions(struct ubpf_vm *vm); @@ -53,7 +58,7 @@ int main(int argc, char **argv) { .name = "register-offset", .val = 'r', .has_arg=1 }, { .name = "unload", .val = 'U' }, /* for unit test only */ { .name = "reload", .val = 'R' }, /* for unit test only */ - { } + { 0 } }; const char *mem_filename = NULL; @@ -126,16 +131,22 @@ int main(int argc, char **argv) * The ELF magic corresponds to an RSH instruction with an offset, * which is invalid. */ +#if defined(UBPF_HAS_ELF_H) bool elf = code_len >= SELFMAG && !memcmp(code, ELFMAG, SELFMAG); +#endif char *errmsg; int rv; load: +#if defined(UBPF_HAS_ELF_H) if (elf) { rv = ubpf_load_elf(vm, code, code_len, &errmsg); } else { +#endif rv = ubpf_load(vm, code, code_len, &errmsg); +#if defined(UBPF_HAS_ELF_H) } +#endif if (unload) { ubpf_unload_code(vm); unload = false; @@ -193,7 +204,7 @@ static void *readfile(const char *path, size_t maxlen, size_t *len) return NULL; } - void *data = calloc(maxlen, 1); + char *data = calloc(maxlen, 1); size_t offset = 0; size_t rv; while ((rv = fread(data+offset, 1, maxlen-offset, file)) > 0) { @@ -219,7 +230,7 @@ static void *readfile(const char *path, size_t maxlen, size_t *len) if (len) { *len = offset; } - return data; + return (void *) data; } #ifndef __GLIBC__ diff --git a/vm/ubpf_config.h.inc b/vm/ubpf_config.h.inc new file mode 100644 index 00000000..728e524f --- /dev/null +++ b/vm/ubpf_config.h.inc @@ -0,0 +1,11 @@ +/* + Copyright (c) 2022-present, IO Visor Project + All rights reserved. + + This source code is licensed in accordance with the terms specified in + the LICENSE file found in the root directory of this source tree. +*/ + +#pragma once + +#cmakedefine UBPF_HAS_ELF_H diff --git a/vm/ubpf_loader.c b/vm/ubpf_loader.c index f7fb40e3..35faade3 100644 --- a/vm/ubpf_loader.c +++ b/vm/ubpf_loader.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #define _GNU_SOURCE #include #include @@ -22,7 +24,10 @@ #include #include #include "ubpf_int.h" + +#if defined(UBPF_HAS_ELF_H) #include +#endif #define MAX_SECTIONS 32 @@ -30,6 +35,8 @@ #define EM_BPF 247 #endif +#if defined(UBPF_HAS_ELF_H) + struct bounds { const void *base; uint64_t size; @@ -225,3 +232,4 @@ ubpf_load_elf(struct ubpf_vm *vm, const void *elf, size_t elf_size, char **errms free(text_copy); return -1; } +#endif diff --git a/vm/ubpf_vm.c b/vm/ubpf_vm.c index 440528a7..8029ece7 100644 --- a/vm/ubpf_vm.c +++ b/vm/ubpf_vm.c @@ -24,6 +24,7 @@ #include #include #include "ubpf_int.h" +#include #define MAX_EXT_FUNCS 64 From 5f97959fc25d87aa4d94420be12c07657d7c9af7 Mon Sep 17 00:00:00 2001 From: Alessandro Gario Date: Thu, 16 Jun 2022 18:40:49 +0200 Subject: [PATCH 2/2] make: Add missing ubpf_config.h generator --- vm/Makefile | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/vm/Makefile b/vm/Makefile index 788810c3..616bc9ed 100644 --- a/vm/Makefile +++ b/vm/Makefile @@ -35,7 +35,11 @@ endif all: libubpf.a libubpf.so test -ubpf_jit_x86_64.o: ubpf_jit_x86_64.c ubpf_jit_x86_64.h +ubpf_jit_x86_64.o: ubpf_config.h ubpf_jit_x86_64.c ubpf_jit_x86_64.h + +ubpf_vm.o: ubpf_config.h + +test.o: ubpf_config.h libubpf.a: ubpf_vm.o ubpf_jit_arm64.o ubpf_jit_x86_64.o ubpf_loader.o ubpf_jit.o ar rc $@ $^ @@ -43,14 +47,19 @@ libubpf.a: ubpf_vm.o ubpf_jit_arm64.o ubpf_jit_x86_64.o ubpf_loader.o ubpf_jit.o libubpf.so: ubpf_vm.o ubpf_jit_x86_64.o ubpf_loader.o $(CC) -shared -o $@ $^ $(LDLIBS) +.PHONY: ubpf_config.h +ubpf_config.h: + echo '#define UBPF_HAS_ELF_H 1' > "inc/ubpf_config.h" + test: test.o libubpf.a -install: +install: all $(INSTALL) -d $(DESTDIR)$(PREFIX)/lib $(INSTALL) -m 644 libubpf.a $(DESTDIR)$(PREFIX)/lib $(INSTALL) -m 644 libubpf.so $(DESTDIR)$(PREFIX)/lib $(INSTALL) -d $(DESTDIR)$(PREFIX)/include $(INSTALL) -m 644 inc/ubpf.h $(DESTDIR)$(PREFIX)/include + $(INSTALL) -m 644 inc/ubpf_config.h $(DESTDIR)$(PREFIX)/include clean: - rm -f test libubpf.a libubpf.so *.o + rm -f test libubpf.a libubpf.so *.o inc/ubpf_config.h