diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 33349ce4d..928da375a 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -56,12 +56,10 @@ jobs: - name: Build working-directory: ./build - # TODO: Remove the disable option for fork safe once funchook problem is solved run: | if [ "$(uname)" == "Darwin" ]; then . .env fi - cmake -DOPTION_FORK_SAFE=OFF .. bash ../tools/metacall-build.sh $METACALL_BUILD_OPTIONS env: METACALL_BUILD_OPTIONS: release benchmarks diff --git a/.github/workflows/docker-hub.yml b/.github/workflows/docker-hub.yml index 123c572b4..2cbe1634d 100644 --- a/.github/workflows/docker-hub.yml +++ b/.github/workflows/docker-hub.yml @@ -19,22 +19,53 @@ env: IMAGE_NAME: core BUILDKIT_VERSION: 0.13.0 + # TODO: Tests failing + # - linux/s390x + # TODO: Not tested or no hooking support + # - linux/mips64le + # - linux/mips64 + # - linux/loong64 + PLATFORM_LIST: > + [ + "linux/amd64", + "linux/amd64/v2", + "linux/amd64/v3", + "linux/386", + "linux/arm64", + "linux/riscv64", + "linux/ppc64le", + "linux/arm/v7", + "linux/arm/v6" + ] + jobs: + matrix: + name: Generate Platform List + runs-on: ubuntu-latest + outputs: + platform_list: ${{ steps.generate_platform_list.outputs.platform_list }} + steps: + - name: Generate platform list + id: generate_platform_list + run: | + set -exuo pipefail + PLATFORM_STRING=$(cat <> $GITHUB_ENV + echo "::set-output name=platform_list::$PLATFORM_LIST" + build: name: Build runs-on: ubuntu-latest + needs: matrix strategy: fail-fast: false matrix: - platform: - - linux/amd64 - - linux/386 - - linux/arm64 - - linux/riscv64 - - linux/ppc64le - - linux/s390x - - linux/arm/v7 - - linux/arm/v6 + platform: ${{ fromJSON(needs.matrix.outputs.platform_list) }} + steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -58,42 +89,44 @@ jobs: - name: Build MetaCall Docker Images env: METACALL_PLATFORM: ${{ matrix.platform }} + DOCKER_BUILDKIT: 1 run: | ./docker-compose.sh platform - - name: Tag Platform Images + - name: Run Tests + env: + DOCKER_BUILDKIT: 1 run: | - platform_tag=$(echo "${{ matrix.platform }}" | tr '/' '-') - echo "Platform Tag: ${platform_tag}" - for tag in "deps" "dev" "runtime" "cli"; do - docker tag metacall/${IMAGE_NAME}:${tag} \ - ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform_tag} - done + set -exuo pipefail + docker image inspect ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:cli --format='{{.Os}}/{{.Architecture}}' + cat < Dockerfile.test + FROM ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:cli + RUN apt-get update && apt-get install -y file + RUN file /usr/local/bin/metacallcli && ldd /usr/local/bin/metacallcli + RUN echo "console.log('0123456789abcdef')" > script.js + RUN metacallcli script.js | tee output.txt + RUN grep 0123456789abcdef output.txt + EOF + + docker buildx build --progress=plain --platform ${{ matrix.platform }} -f Dockerfile.test -t test-image . - - name: Push Platform Images + - name: Tag & Push Platform Images + # Only run when master or when tagging a version + if: (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')) && github.event_name != 'pull_request' run: | platform_tag=$(echo "${{ matrix.platform }}" | tr '/' '-') for tag in "deps" "dev" "runtime" "cli"; do + docker tag \ + ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag} \ + ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform_tag} + echo "Pushing image for tag: ${tag} with platform: ${platform_tag}" docker push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform_tag} done - - name: Run Tests - run: | - set -exuo pipefail - platform_tag=$(echo "${{ matrix.platform }}" | tr '/' '-') - cat < Dockerfile.test - FROM ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:cli-${platform_tag} - RUN echo "console.log('abcde')" > script.js - RUN metacallcli script.js - EOF - - docker build --platform ${{ matrix.platform }} -f Dockerfile.test -t test-image . - docker run --rm --platform=${{ matrix.platform }} test-image - manifest: name: Create and Push Manifest Lists - needs: build + needs: [matrix, build] # Only run when master or when tagging a version if: (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')) && github.event_name != 'pull_request' runs-on: ubuntu-latest @@ -106,8 +139,10 @@ jobs: - name: Create and Push Manifest Lists run: | + set -exuo pipefail + tags=("deps" "dev" "runtime" "cli") - platforms=("linux/amd64" "linux/386" "linux/arm64" "linux/riscv64" "linux/ppc64le" "linux/s390x" "linux/arm/v7" "linux/arm/v6") + platforms=($(echo '${{ needs.matrix.outputs.platform_list }}' | jq -r '.[]')) echo "Create all the tags by platform" @@ -151,14 +186,16 @@ jobs: cleanup: name: Cleanup Platform Specific Tags - needs: [build, manifest] + needs: [matrix, build, manifest] runs-on: ubuntu-latest if: always() steps: - name: Remove Platform-Specific Tags run: | + set -exuo pipefail + tags=("deps" "dev" "runtime" "cli") - platforms=("linux/amd64" "linux/386" "linux/arm64" "linux/riscv64" "linux/ppc64le" "linux/s390x" "linux/arm/v7" "linux/arm/v6") + platforms=($(echo '${{ needs.matrix.outputs.platform_list }}' | jq -r '.[]')) for tag in "${tags[@]}"; do for platform in "${platforms[@]}"; do diff --git a/.github/workflows/macos-test.yml b/.github/workflows/macos-test.yml index 64a768757..c98f66f09 100644 --- a/.github/workflows/macos-test.yml +++ b/.github/workflows/macos-test.yml @@ -77,7 +77,7 @@ jobs: - name: Set up the environment run: sh ./tools/metacall-environment.sh $METACALL_INSTALL_OPTIONS env: - METACALL_INSTALL_OPTIONS: base python nodejs typescript java ruby wasm rpc file cobol go backtrace #netcore5 c rust rapidjson funchook swig pack # clangformat v8rep51 coverage + METACALL_INSTALL_OPTIONS: base python nodejs typescript java ruby wasm rpc file cobol go backtrace #netcore5 c rust rapidjson swig pack # clangformat v8rep51 coverage - name: Configure run: | @@ -89,10 +89,8 @@ jobs: - name: Build working-directory: ./build - # TODO: Remove the disable option for fork safe once funchook problem is solved run: | . .env - cmake -DOPTION_FORK_SAFE=OFF .. bash ../tools/metacall-build.sh $METACALL_BUILD_OPTIONS env: METACALL_BUILD_OPTIONS: ${{ matrix.options.build }} tests diff --git a/.github/workflows/windows-test.yml b/.github/workflows/windows-test.yml index c7af6e0ee..c1a423616 100644 --- a/.github/workflows/windows-test.yml +++ b/.github/workflows/windows-test.yml @@ -48,7 +48,7 @@ jobs: - name: Set up the environment run: cmd.exe /c "powershell .\tools\metacall-environment.ps1 $Env:METACALL_INSTALL_OPTIONS" env: - METACALL_INSTALL_OPTIONS: python nodejs java ruby typescript wasm rpc file # netcore5 java c cobol rust rapidjson funchook swig pack # clangformat v8rep51 coverage + METACALL_INSTALL_OPTIONS: python nodejs java ruby typescript wasm rpc file # netcore5 java c cobol rust rapidjson swig pack # clangformat v8rep51 coverage - name: Configure run: | diff --git a/NOTICE b/NOTICE index 64d3172e0..f51329169 100644 --- a/NOTICE +++ b/NOTICE @@ -19,7 +19,7 @@ All external code and licenses used by **METACALL** are always wrapped into plug - [2. Serials](#2-serials) - [2.1 RapidJSON](#21-rapidjson) - [3. Detours](#3-detours) - - [3.1 FuncHook](#31-funchook) + - [3.1 PLTHook](#31-plthook) - [4. Ports](#4-ports) - [4.1 Swig](#41-swig) @@ -80,11 +80,11 @@ All external code and licenses used by **METACALL** are always wrapped into plug ## 3. Detours -### 3.1 FuncHook +### 3.1 PLTHook -| Software | License | -| :----------: | :-------------------------------------------------------------------------------------------------: | -| **FuncHook** | [GPLv2 or later with a GPL linking exception](https://github.com/kubo/funchook/blob/master/LICENSE) | +| Software | License | +| :----------: | :------------------------------------------------------------------------------------------: | +| **PLTHook** | [2-clause BSD-style license](https://github.com/metacall/plthook?tab=readme-ov-file#license) | ## 4. Ports diff --git a/cmake/FindLibGit2.cmake b/cmake/FindLibGit2.cmake index f9f4497e3..cb1c0cf0a 100644 --- a/cmake/FindLibGit2.cmake +++ b/cmake/FindLibGit2.cmake @@ -44,13 +44,13 @@ endif() if(NOT LibGit2_VERSION AND LibGit2_INCLUDE_DIR) file(STRINGS "${LibGit2_INCLUDE_DIR}/git2/version.h" LibGit2_VERSION_MAJOR REGEX "^#define LIBGIT2_VER_MAJOR +([0-9]+)") - string(REGEX MATCH "([0-9]+)$" LibGit2_VERSION_MAJOR ${LibGit2_VERSION_MAJOR}) + string(REGEX MATCH "([0-9]+)$" LibGit2_VERSION_MAJOR "${LibGit2_VERSION_MAJOR}") file(STRINGS "${LibGit2_INCLUDE_DIR}/git2/version.h" LibGit2_VERSION_MINOR REGEX "^#define LIBGIT2_VER_MINOR +([0-9]+)") - string(REGEX MATCH "([0-9]+)$" LibGit2_VERSION_MINOR ${LibGit2_VERSION_MINOR}) + string(REGEX MATCH "([0-9]+)$" LibGit2_VERSION_MINOR "${LibGit2_VERSION_MINOR}") file(STRINGS "${LibGit2_INCLUDE_DIR}/git2/version.h" LibGit2_VERSION_REVISION REGEX "^#define LIBGIT2_VER_REVISION +([0-9]+)") - string(REGEX MATCH "([0-9]+)$" LibGit2_VERSION_REVISION ${LibGit2_VERSION_REVISION}) + string(REGEX MATCH "([0-9]+)$" LibGit2_VERSION_REVISION "${LibGit2_VERSION_REVISION}") set(LibGit2_VERSION "${LibGit2_VERSION_MAJOR}.${LibGit2_VERSION_MINOR}.${LibGit2_VERSION_REVISION}") endif() diff --git a/cmake/InstallGTest.cmake b/cmake/InstallGTest.cmake index 7977751f0..fa555b16b 100644 --- a/cmake/InstallGTest.cmake +++ b/cmake/InstallGTest.cmake @@ -24,7 +24,7 @@ if(NOT GTEST_FOUND OR USE_BUNDLED_GTEST) if(NOT GTEST_VERSION OR USE_BUNDLED_GTEST) - set(GTEST_VERSION 1.11.0) + set(GTEST_VERSION 1.16.0) endif() find_package(Threads REQUIRED) @@ -38,7 +38,7 @@ if(NOT GTEST_FOUND OR USE_BUNDLED_GTEST) # Import Google Test Framework ExternalProject_Add(google-test-depends GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-${GTEST_VERSION} + GIT_TAG v${GTEST_VERSION} CMAKE_ARGS -Dgtest_build_samples=OFF -Dgtest_build_tests=OFF @@ -65,17 +65,11 @@ if(NOT GTEST_FOUND OR USE_BUNDLED_GTEST) set(GTEST_LIB_SUFFIX "lib") set(GTEST_LIBS_DIR "${binary_dir}/lib/${CMAKE_BUILD_TYPE}") set(GMOCK_LIBS_DIR "${binary_dir}/lib/${CMAKE_BUILD_TYPE}") - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(GTEST_LIB_DEBUG "d") - else() - set(GTEST_LIB_DEBUG "") - endif() else() set(GTEST_LIB_PREFIX "lib") set(GTEST_LIB_SUFFIX "a") set(GTEST_LIBS_DIR "${binary_dir}/lib") set(GMOCK_LIBS_DIR "${binary_dir}/lib") - set(GTEST_LIB_DEBUG "") endif() # Define Paths @@ -85,11 +79,11 @@ if(NOT GTEST_FOUND OR USE_BUNDLED_GTEST) ) set(GTEST_LIBRARY - "${GTEST_LIBS_DIR}/${GTEST_LIB_PREFIX}gtest${GTEST_LIB_DEBUG}.${GTEST_LIB_SUFFIX}" + "${GTEST_LIBS_DIR}/${GTEST_LIB_PREFIX}gtest.${GTEST_LIB_SUFFIX}" ) set(GMOCK_LIBRARY - "${GMOCK_LIBS_DIR}/${GTEST_LIB_PREFIX}gmock${GTEST_LIB_DEBUG}.${GTEST_LIB_SUFFIX}" + "${GMOCK_LIBS_DIR}/${GTEST_LIB_PREFIX}gmock.${GTEST_LIB_SUFFIX}" ) set(GTEST_LIBRARIES diff --git a/cmake/InstallRapidJSON.cmake b/cmake/InstallRapidJSON.cmake index 41c302027..f90dfc4a4 100644 --- a/cmake/InstallRapidJSON.cmake +++ b/cmake/InstallRapidJSON.cmake @@ -24,7 +24,7 @@ if(NOT RAPIDJSON_FOUND OR USE_BUNDLED_RAPIDJSON) if(NOT RAPIDJSON_VERSION OR USE_BUNDLED_RAPIDJSON) - set(RAPIDJSON_VERSION ab1842a2dae061284c0a62dca1cc6d5e7e37e346) + set(RAPIDJSON_VERSION 24b5e7a8b27f42fa16b96fc70aade9106cf7102f) endif() ExternalProject_Add(rapid-json-depends diff --git a/cmake/Portability.cmake b/cmake/Portability.cmake index 86193291c..556427b18 100644 --- a/cmake/Portability.cmake +++ b/cmake/Portability.cmake @@ -146,11 +146,10 @@ set(PROJECT_ARCH_NAME ${CMAKE_SYSTEM_PROCESSOR}) # 32 or 64 bit Linux if(PROJECT_OS_LINUX) - if(${PROJECT_ARCH_NAME} STREQUAL "x86") + if (${PROJECT_ARCH_NAME} MATCHES "^(x86|i[3-6]86|x86_64)$" AND "${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") set(PROJECT_ARCH_32BIT TRUE BOOL INTERNAL) - endif() - - if(${PROJECT_ARCH_NAME} MATCHES "(x86_64)|(amd64)|(AMD64)") + set(PROJECT_ARCH_X86 TRUE BOOL INTERNAL) + elseif(${PROJECT_ARCH_NAME} MATCHES "(x86_64)|(amd64)|(AMD64)") set(PROJECT_ARCH_64BIT TRUE BOOL INTERNAL) set(PROJECT_ARCH_AMD64 TRUE BOOL INTERNAL) elseif(${PROJECT_ARCH_NAME} STREQUAL "aarch64") @@ -162,6 +161,7 @@ if(PROJECT_OS_LINUX) set(PROJECT_ARCH_64BIT TRUE BOOL INTERNAL) endif() + # Verify the architecture is correct if(PROJECT_ARCH_32BIT) if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4") message(STATUS "Linux ${PROJECT_ARCH_NAME} 32bit detected") @@ -183,7 +183,7 @@ endif() if(NOT PROJECT_ARCH_32BIT AND NOT PROJECT_ARCH_64BIT) if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4") message(STATUS "32bit architecture ${PROJECT_ARCH_NAME} detected") - set(PROJECT_ARCH_32BIT TRUE BOOL INTERNAL) + set(PROJECT_ARCH_32BIT TRUE BOOL INTERNAL) if(PROJECT_OS_WIN) set(WINXBITS Win32) @@ -191,7 +191,7 @@ if(NOT PROJECT_ARCH_32BIT AND NOT PROJECT_ARCH_64BIT) elseif("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") message(STATUS "64bit architecture ${PROJECT_ARCH_NAME} detected") - set(PROJECT_ARCH_64BIT TRUE BOOL INTERNAL) + set(PROJECT_ARCH_64BIT TRUE BOOL INTERNAL) if(PROJECT_OS_WIN) set(WINXBITS Win64) diff --git a/cmake/Warnings.cmake b/cmake/Warnings.cmake index 685d3b6a8..23f057afd 100644 --- a/cmake/Warnings.cmake +++ b/cmake/Warnings.cmake @@ -46,6 +46,7 @@ if(WARNINGS_ENABLED) # Define C compiler warning flags if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") + # TODO: Uncomment the rest of the warnings, enable Weverything for clang add_compile_options(-Wall) add_compile_options(-Wextra) add_compile_options(-Wunused) @@ -85,7 +86,7 @@ if(WARNINGS_ENABLED) string(REPLACE "/W1" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") string(REPLACE "/W2" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") string(REPLACE "/W3" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /Wall") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") # /Wall set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CTR_NONSTDC_NO_WARNINGS=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CTR_SECURE_NO_WARNINGS=1") set(WARNINGS_C_AVAILABLE 1) @@ -105,7 +106,7 @@ if(WARNINGS_ENABLED) string(REPLACE "/W1" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE "/W2" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /Wall") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") # /Wall set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _CTR_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _CTR_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _CTR_NONSTDC_NO_WARNINGS=1") diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 5dadee3cb..a6946f3a5 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -25,10 +25,10 @@ services: build: args: METACALL_BUILD_TYPE: ${METACALL_BUILD_TYPE} - METACALL_INSTALL_OPTIONS: base python ruby netcore7 nodejs typescript file rpc wasm java c cobol go rust rapidjson funchook swig pack backtrace sandbox ${METACALL_BUILD_COVERAGE} # clangformat v8rep51 + METACALL_INSTALL_OPTIONS: base python ruby netcore8 nodejs typescript file rpc wasm java c cobol go rust rapidjson swig pack backtrace sandbox ${METACALL_BUILD_COVERAGE} # clangformat v8rep51 dev: image: metacall/core:dev build: args: METACALL_BUILD_TYPE: ${METACALL_BUILD_TYPE} - METACALL_BUILD_OPTIONS: ${METACALL_BUILD_SANITIZER} python ruby netcore7 nodejs typescript file rpc wasm java c cobol go rust examples tests scripts ports install pack sandbox benchmarks ${METACALL_BUILD_COVERAGE} # v8 + METACALL_BUILD_OPTIONS: ${METACALL_BUILD_SANITIZER} python ruby netcore8 nodejs typescript file rpc wasm java c cobol go rust examples tests scripts ports install pack sandbox benchmarks ${METACALL_BUILD_COVERAGE} # v8 diff --git a/docker-compose.yml b/docker-compose.yml index 38e167b44..ff548ba2a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,7 +31,7 @@ services: METACALL_PATH: $METACALL_PATH METACALL_TOOLS_PATH: $METACALL_PATH/tools METACALL_BUILD_TYPE: $METACALL_BUILD_TYPE - METACALL_INSTALL_OPTIONS: base python ruby nodejs typescript file rpc rapidjson funchook swig pack backtrace # clangformat v8rep51 coverage + METACALL_INSTALL_OPTIONS: base python ruby nodejs typescript file rpc rapidjson swig pack backtrace # clangformat v8rep51 coverage environment: DEBIAN_FRONTEND: noninteractive # Work around https://github.com/dotnet/cli/issues/1582 until Docker releases a diff --git a/docs/README.md b/docs/README.md index 446569788..3c348b9f8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -66,7 +66,7 @@ Use the [installer](https://github.com/metacall/install) and try [some examples] - [5.3.2.1 MetaCall](#5321-metacall) - [5.3.2.2 RapidJSON](#5322-rapidjson) - [5.3.3 Detours](#533-detours) - - [5.3.3.1 FuncHook](#5331-funchook) + - [5.3.3.1 PLTHook](#5331-plthook) - [5.4 Ports](#54-ports) - [5.5 Serialization](#55-serialization) - [5.6 Memory Layout](#56-memory-layout) @@ -251,7 +251,7 @@ The environment variables are optional, in case you want to modify default paths - [`detours`](/source/detours) implement the [`detour`](/source/detour) interface by using a plugin architecture. The current list of available detour plugins is the following one. - - [`funchook_detour`](/source/detours/funchook_detour) implemented by means of FuncHook library. + - [`plthook_detour`](/source/detours/plthook_detour) implemented by means of PLTHook library. - [`dynlink`](/source/dynlink) implements a cross-platform method to dynamically load libraries. It is used to dynamically load plugins into **METACALL**. @@ -499,7 +499,7 @@ A loader must implement it to be considered a valid loader. #### 5.3.3 Detours -##### 5.3.3.1 FuncHook +##### 5.3.3.1 PLTHook ### 5.4 Ports @@ -666,7 +666,7 @@ It is possible to enable or disable concrete loaders, script, ports, serials or | **OPTION*BUILD_LOADERS*** | `C` `JS` `CS` `MOCK` `PY` `JSM` `NODE` `RB` `FILE` | | **OPTION*BUILD_SCRIPTS*** | `C` `CS` `JS` `NODE` `PY` `RB` `JAVA` | | **OPTION*BUILD_SERIALS*** | `METACALL` `RAPID_JSON` | -| **OPTION*BUILD_DETOURS*** | `FUNCHOOK` | +| **OPTION*BUILD_DETOURS*** | `PLTHOOK` | | **OPTION*BUILD_PORTS*** | `CS` `CXX` `D` `GO` `JAVA` `JS` `LUA` `NODE` `PHP` `PL` `PY` `R` `RB` | To format the entire C/C++ codebase use: diff --git a/source/adt/source/adt_map.c b/source/adt/source/adt_map.c index 9f54b623f..4f28a10cb 100644 --- a/source/adt/source/adt_map.c +++ b/source/adt/source/adt_map.c @@ -239,9 +239,9 @@ vector map_get(map m, map_key key) { if (m != NULL && key != NULL) { - map_hash hash = m->hash_cb(key); + map_hash h = m->hash_cb(key); - size_t index = hash % m->capacity; + size_t index = h % m->capacity; bucket b = &m->buckets[index]; @@ -255,9 +255,9 @@ int map_contains(map m, map_key key) { if (m != NULL && key != NULL) { - map_hash hash = m->hash_cb(key); + map_hash h = m->hash_cb(key); - size_t index = hash % m->capacity; + size_t index = h % m->capacity; bucket b = &m->buckets[index]; diff --git a/source/adt/source/adt_set.c b/source/adt/source/adt_set.c index d7f38ea95..e54b8faee 100644 --- a/source/adt/source/adt_set.c +++ b/source/adt/source/adt_set.c @@ -256,9 +256,9 @@ set_value set_get(set s, set_key key) { if (s != NULL && key != NULL) { - set_hash hash = s->hash_cb(key); + set_hash h = s->hash_cb(key); - size_t index = hash % s->capacity; + size_t index = h % s->capacity; bucket b = &s->buckets[index]; @@ -277,9 +277,9 @@ int set_contains(set s, set_key key) { if (s != NULL && key != NULL) { - set_hash hash = s->hash_cb(key); + set_hash h = s->hash_cb(key); - size_t index = hash % s->capacity; + size_t index = h % s->capacity; bucket b = &s->buckets[index]; diff --git a/source/detour/include/detour/detour.h b/source/detour/include/detour/detour.h index fca7d3ee1..9eb8d50fc 100644 --- a/source/detour/include/detour/detour.h +++ b/source/detour/include/detour/detour.h @@ -40,7 +40,7 @@ DETOUR_API int detour_initialize(void); * Create detour by @name * * @param[in] name -* Plugin will be used to detourize and detourize +* Plugin will be used for hooking * * @return * Pointer to detour on correct initialization, null otherwise @@ -63,35 +63,77 @@ DETOUR_API const char *detour_name(detour d); /** * @brief -* Get trampoline of the detour +* Initialize the detour of a library from @path * -* @param[in] handle -* Reference to the detour handle +* @param[in] d +* Reference to the detour +* +* @param[in] path +* String to the path or name of the library, in case of NULL, the current process will be used * * @return -* Pointer to the trampoline function +* Pointer to the detour handle * */ -DETOUR_API void (*detour_trampoline(detour_handle handle))(void); +DETOUR_API detour_handle detour_load_file(detour d, const char *path); /** * @brief -* Install detour from @target to @hook +* Initialize the detour of a library from @library dynlink handle * * @param[in] d * Reference to the detour * -* @param[in] target -* Reference to the function to be hooked +* @param[in] library +* Pointer to the library already opened by dynlink +* +* @return +* Pointer to the detour handle +* +*/ +DETOUR_API detour_handle detour_load_handle(detour d, dynlink library); + +/** +* @brief +* Initialize the detour of a library from @address, this function pointer +* must be a pointer to a function of the library that we want to hook +* +* @param[in] d +* Reference to the detour * -* @param[in] hook -* Reference to the function will be called instead of @target +* @param[in] address +* Pointer to a function of the library we want to hook * * @return * Pointer to the detour handle * */ -DETOUR_API detour_handle detour_install(detour d, void (*target)(void), void (*hook)(void)); +DETOUR_API detour_handle detour_load_address(detour d, void (*address)(void)); + +/** +* @brief +* Iterate all symbols of the library already opened +* +* @param[in] d +* Reference to the detour +* +* @param[in] handle +* Pointer to the detour hook implementation +* +* @param[out] position +* Pointer to the current index of the enumeration +* +* @param[out] name +* Pointer to the function name in string form +* +* @param[out] address +* Pointer to the pointer of the function pointer of the function to be hooked +* +* @return +* Return zero on success, different from zero otherwise +* +*/ +DETOUR_API int detour_enumerate(detour d, detour_handle handle, unsigned int *position, const char **name, void (***address)(void)); /** * @brief @@ -103,11 +145,33 @@ DETOUR_API detour_handle detour_install(detour d, void (*target)(void), void (*h * @param[in] handle * Reference to the detour handle * +* @param[in] function_name +* Function name to be hooked, it must belong to the library +* +* @param[in] function_addr +* Function pointer to the function that will replace the original function from the library +* +* @param[out] function_trampoline +* Function pointer to the original function from the library that will be replaced +* * @return * Return zero if success, different from zero otherwise * */ -DETOUR_API int detour_uninstall(detour d, detour_handle handle); +DETOUR_API int detour_replace(detour d, detour_handle handle, const char *function_name, void (*function_addr)(void), void (**function_trampoline)(void)); + +/** +* @brief +* Destroy detour handle previously loaded by detour_load_* functions +* +* @param[in] d +* Reference to the detour +* +* @param[in] handle +* Reference to the detour handle +* +*/ +DETOUR_API void detour_unload(detour d, detour_handle handle); /** * @brief diff --git a/source/detour/include/detour/detour_interface.h b/source/detour/include/detour/detour_interface.h index 5207622ba..d4ac5b5e8 100644 --- a/source/detour/include/detour/detour_interface.h +++ b/source/detour/include/detour/detour_interface.h @@ -25,6 +25,8 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -42,10 +44,13 @@ typedef struct detour_interface_type *detour_interface; struct detour_interface_type { - detour_impl_handle (*initialize)(void); - int (*install)(detour_impl_handle, void (**)(void), void (*)(void)); - int (*uninstall)(detour_impl_handle); - int (*destroy)(detour_impl_handle); + int (*initialize_file)(detour_impl_handle *, const char *); + int (*initialize_handle)(detour_impl_handle *, dynlink); + int (*initialize_address)(detour_impl_handle *, void (*)(void)); + int (*enumerate)(detour_impl_handle, unsigned int *, const char **, void ***); + int (*replace)(detour_impl_handle, const char *, void (*)(void), void **); + const char *(*error)(detour_impl_handle); + void (*destroy)(detour_impl_handle); }; #ifdef __cplusplus diff --git a/source/detour/source/detour.c b/source/detour/source/detour.c index 9da330372..c1e4646e0 100644 --- a/source/detour/source/detour.c +++ b/source/detour/source/detour.c @@ -34,7 +34,13 @@ static plugin_manager_declare(detour_manager); struct detour_handle_type { - void (*target)(void); + /* TODO: Implement hash map for holding the symbol table? */ + /* TODO: Optimize the replace process by exposing the internal replace function + * and store all the symbols in the hash table then iterate and replace at the + * same time, so the functions are accessed in O(1) instead of O(n) + */ + set symbol_map; + set replaced_symbols; detour_impl_handle impl; }; @@ -65,37 +71,62 @@ const char *detour_name(detour d) return plugin_name(d); } -void (*detour_trampoline(detour_handle handle))(void) +static detour_handle detour_handle_allocate(void) { + detour_handle handle = malloc(sizeof(struct detour_handle_type)); + if (handle == NULL) { - return NULL; + goto alloc_handle_error; + } + + handle->symbol_map = set_create(&hash_callback_ptr, &comparable_callback_ptr); + + if (handle->symbol_map == NULL) + { + goto alloc_symbol_map_error; + } + + handle->replaced_symbols = set_create(&hash_callback_ptr, &comparable_callback_ptr); + + if (handle->replaced_symbols == NULL) + { + goto alloc_replaced_symbols_error; } - return handle->target; + handle->impl = NULL; + + return handle; + +alloc_replaced_symbols_error: + set_destroy(handle->symbol_map); +alloc_symbol_map_error: + free(handle); +alloc_handle_error: + return NULL; } -detour_handle detour_install(detour d, void (*target)(void), void (*hook)(void)) +detour_handle detour_load_file(detour d, const char *path) { - if (d == NULL || target == NULL || hook == NULL) + detour_handle handle; + + if (d == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour install arguments"); + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour load arguments"); return NULL; } - detour_handle handle = malloc(sizeof(struct detour_handle_type)); + handle = detour_handle_allocate(); if (handle == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour install handle allocation"); + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour load handle allocation"); return NULL; } - handle->impl = detour_iface(d)->initialize(); - - if (handle->impl == NULL) + if (detour_iface(d)->initialize_file(&handle->impl, path) != 0) { log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour implementation handle initialization"); @@ -104,55 +135,112 @@ detour_handle detour_install(detour d, void (*target)(void), void (*hook)(void)) return NULL; } - void (**target_ptr)(void) = ⌖ + return handle; +} - if (detour_iface(d)->install(handle->impl, target_ptr, hook) != 0) +detour_handle detour_load_handle(detour d, dynlink library) +{ + detour_handle handle; + + if (d == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour implementation handle installation"); + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour load arguments"); - if (detour_iface(d)->destroy(handle->impl) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour implementation handle destruction"); - } + return NULL; + } - free(handle); + handle = detour_handle_allocate(); + + if (handle == NULL) + { + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour load handle allocation"); return NULL; } - handle->target = *target_ptr; + if (detour_iface(d)->initialize_handle(&handle->impl, library) != 0) + { + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour implementation handle initialization"); + + free(handle); + + return NULL; + } return handle; } -int detour_uninstall(detour d, detour_handle handle) +detour_handle detour_load_address(detour d, void (*address)(void)) { - int result = 0; + detour_handle handle; + if (d == NULL) + { + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour load arguments"); + + return NULL; + } + + handle = detour_handle_allocate(); + + if (handle == NULL) + { + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour load handle allocation"); + + return NULL; + } + + if (detour_iface(d)->initialize_address(&handle->impl, address) != 0) + { + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour implementation handle initialization"); + + free(handle); + + return NULL; + } + + return handle; +} + +int detour_enumerate(detour d, detour_handle handle, unsigned int *position, const char **name, void (***address)(void)) +{ if (d == NULL || handle == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid uninstall arguments"); + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour replace arguments"); return 1; } - result |= detour_iface(d)->uninstall(handle->impl); + return detour_iface(d)->enumerate(handle->impl, position, name, (void ***)address); +} - if (result != 0) +int detour_replace(detour d, detour_handle handle, const char *function_name, void (*function_addr)(void), void (**function_trampoline)(void)) +{ + if (d == NULL || handle == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour implementation handle uninstallation"); + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour replace arguments"); + + return 1; } - result |= detour_iface(d)->destroy(handle->impl); + return detour_iface(d)->replace(handle->impl, function_name, function_addr, (void **)function_trampoline); +} - if (result != 0) +void detour_unload(detour d, detour_handle handle) +{ + if (d == NULL || handle == NULL) { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour implementation handle destruction"); + log_write("metacall", LOG_LEVEL_ERROR, "Invalid detour replace arguments"); + return; } - free(handle); + /* TODO: Should we restore all the replaced symbols? */ + + detour_iface(d)->destroy(handle->impl); + + set_destroy(handle->symbol_map); - return result; + set_destroy(handle->replaced_symbols); } int detour_clear(detour d) diff --git a/source/detours/CMakeLists.txt b/source/detours/CMakeLists.txt index c1f851b97..1a3c51030 100644 --- a/source/detours/CMakeLists.txt +++ b/source/detours/CMakeLists.txt @@ -4,7 +4,7 @@ if(NOT OPTION_BUILD_DETOURS) endif() # Detour options -option(OPTION_BUILD_DETOURS_FUNCHOOK "FuncHook library detour." ON) +option(OPTION_BUILD_DETOURS_PLTHOOK "PLTHook library detour." ON) # Detour packages -add_subdirectory(funchook_detour) # FuncHook library +add_subdirectory(plthook_detour) # PLTHook library diff --git a/source/detours/funchook_detour/include/funchook_detour/funchook_detour_impl.h b/source/detours/funchook_detour/include/funchook_detour/funchook_detour_impl.h deleted file mode 100644 index 37cb640cd..000000000 --- a/source/detours/funchook_detour/include/funchook_detour/funchook_detour_impl.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Detour Library by Parra Studios - * A cross-platform library providing detours, function hooks and trampolines. - * - * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia - * - * 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. - * - */ - -#ifndef FUNCHOOK_DETOUR_IMPL_H -#define FUNCHOOK_DETOUR_IMPL_H 1 - -/* -- Headers -- */ - -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* -- Methods -- */ - -/** -* @brief -* Initialize FuncHook detour hook implementation -* -* @return -* Returns pointer to detour hook implementation on success, null pointer otherwise -* -*/ -FUNCHOOK_DETOUR_API detour_impl_handle funchook_detour_impl_initialize(void); - -/** -* @brief -* Install FuncHook detour implementation -* -* @param[in] handle -* Pointer to the detour hook implementation -* -* @param[in] target -* Pointer to the function to be intercepted -* -* @param[in] hook -* Function will be called instead of target -* -* @return -* Return zero on success, different from zero otherwise -* -*/ -FUNCHOOK_DETOUR_API int funchook_detour_impl_install(detour_impl_handle handle, void (**target)(void), void (*hook)(void)); - -/** -* @brief -* Uninstall FuncHook detour implementation -* -* @param[in] handle -* Pointer to the detour hook implementation -* -* @return -* Return zero on success, different from zero otherwise -* -*/ -FUNCHOOK_DETOUR_API int funchook_detour_impl_uninstall(detour_impl_handle handle); - -/** -* @brief -* Destroy FuncHook detour implementation -* -* @return -* Returns zero on correct destruction, distinct from zero otherwise -* -*/ -FUNCHOOK_DETOUR_API int funchook_detour_impl_destroy(detour_impl_handle handle); - -#ifdef __cplusplus -} -#endif - -#endif /* FUNCHOOK_DETOUR_IMPL_H */ diff --git a/source/detours/funchook_detour/source/funchook_detour.c b/source/detours/funchook_detour/source/funchook_detour.c deleted file mode 100644 index 9a15057fa..000000000 --- a/source/detours/funchook_detour/source/funchook_detour.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Detour Library by Parra Studios - * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia - * - * A cross-platform library providing detours, function hooks and trampolines. - * - */ - -/* -- Headers -- */ - -#include - -#include -#include - -/* -- Methods -- */ - -detour_interface funchook_detour_impl_interface_singleton(void) -{ - static struct detour_interface_type interface_instance_funchook = { - &funchook_detour_impl_initialize, - &funchook_detour_impl_install, - &funchook_detour_impl_uninstall, - &funchook_detour_impl_destroy - }; - - return &interface_instance_funchook; -} - -const char *funchook_detour_print_info(void) -{ - static const char funchook_detour_info[] = - "FuncHook Detour Plugin " METACALL_VERSION "\n" - "Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia \n" - -#ifdef FUNCHOOK_DETOUR_STATIC_DEFINE - "Compiled as static library type\n" -#else - "Compiled as shared library type\n" -#endif - - "\n"; - - return funchook_detour_info; -} diff --git a/source/detours/funchook_detour/source/funchook_detour_impl.c b/source/detours/funchook_detour/source/funchook_detour_impl.c deleted file mode 100644 index 83c25a1dc..000000000 --- a/source/detours/funchook_detour/source/funchook_detour_impl.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Detour Library by Parra Studios - * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia - * - * A cross-platform library providing detours, function hooks and trampolines. - * - */ - -/* -- Headers -- */ - -#include - -#include - -#include - -/* -- Member Data -- */ - -union funchook_detour_impl_cast -{ - void (*hook)(void); - void *ptr; -}; - -/* -- Methods -- */ - -detour_impl_handle funchook_detour_impl_initialize(void) -{ - return (detour_impl_handle)funchook_create(); -} - -int funchook_detour_impl_install(detour_impl_handle handle, void (**target)(void), void (*hook)(void)) -{ - funchook_t *handle_impl = handle; - - if (handle_impl != NULL && target != NULL && hook != NULL) - { - union funchook_detour_impl_cast hook_cast = { hook }; - - if (funchook_prepare(handle_impl, (void **)target, hook_cast.ptr) != FUNCHOOK_ERROR_SUCCESS) - { - return 1; - } - - if (funchook_install(handle_impl, 0) != FUNCHOOK_ERROR_SUCCESS) - { - return 1; - } - - return 0; - } - - return 1; -} - -int funchook_detour_impl_uninstall(detour_impl_handle handle) -{ - funchook_t *handle_impl = handle; - - if (handle_impl != NULL) - { - return !(funchook_uninstall(handle_impl, 0) == FUNCHOOK_ERROR_SUCCESS); - } - - return 1; -} - -int funchook_detour_impl_destroy(detour_impl_handle handle) -{ - funchook_t *handle_impl = handle; - - if (handle_impl == NULL) - { - return 0; - } - - return !(funchook_destroy(handle_impl) == FUNCHOOK_ERROR_SUCCESS); -} diff --git a/source/detours/funchook_detour/CMakeLists.txt b/source/detours/plthook_detour/CMakeLists.txt similarity index 50% rename from source/detours/funchook_detour/CMakeLists.txt rename to source/detours/plthook_detour/CMakeLists.txt index ac782f31d..a5db591c1 100644 --- a/source/detours/funchook_detour/CMakeLists.txt +++ b/source/detours/plthook_detour/CMakeLists.txt @@ -1,5 +1,5 @@ # Check if this detour is enabled -if(NOT OPTION_BUILD_DETOURS OR NOT OPTION_BUILD_DETOURS_FUNCHOOK) +if(NOT OPTION_BUILD_DETOURS OR NOT OPTION_BUILD_DETOURS_PLTHOOK) return() endif() @@ -7,66 +7,35 @@ endif() # External dependencies # -find_package(Git REQUIRED) +# PLTHook +include(FetchContent) -# Target depends name -set(target_depends funchook_detour_depends) +set(PLTHook_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/plthook") -include(ExternalProject) - -set(FUNCHOOK_VERSION 1.1.3) +FetchContent_Declare(PLTHook + GIT_REPOSITORY https://github.com/metacall/plthook.git + GIT_TAG master + SOURCE_DIR ${PLTHook_SOURCE_DIR} +) -if(WIN32) - set(FUNCHOOK_LIBRARY_SUFFIX "lib") - set(FUNCHOOK_LIBRARY_INSTALL_SUFFIX "dll") -elseif(APPLE) - set(FUNCHOOK_LIBRARY_SUFFIX "dylib") -else() - set(FUNCHOOK_LIBRARY_SUFFIX "so") -endif() +FetchContent_MakeAvailable(PLTHook) -set(FUNCHOOK_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/funchook/src/funchook") +set(PLTHook_INCLUDE_DIR "${PLTHook_SOURCE_DIR}") -if(WIN32) - set(FUNCHOOK_BUILD_TARGET "INSTALL") - set(FUNCHOOK_LIBRARY_NAME "funchook_dll.${FUNCHOOK_LIBRARY_SUFFIX}") - set(FUNCHOOK_LIBRARY "${FUNCHOOK_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/${FUNCHOOK_LIBRARY_NAME}") - set(FUNCHOOK_LIBRARY_INSTALL_NAME "funchook.${FUNCHOOK_LIBRARY_INSTALL_SUFFIX}") - set(FUNCHOOK_LIBRARY_INSTALL_DIR "${FUNCHOOK_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/${FUNCHOOK_LIBRARY_INSTALL_NAME}") +if(APPLE) + set(PLTHook_SOURCE "${PLTHook_SOURCE_DIR}/plthook_osx.c") +elseif(WIN32 OR MINGW) + set(PLTHook_SOURCE "${PLTHook_SOURCE_DIR}/plthook_win32.c") else() - set(FUNCHOOK_BUILD_TARGET "install") - set(FUNCHOOK_LIBRARY_NAME "libfunchook.${FUNCHOOK_LIBRARY_SUFFIX}") - set(FUNCHOOK_LIBRARY "${FUNCHOOK_SOURCE_DIR}/${FUNCHOOK_LIBRARY_NAME}") - set(FUNCHOOK_LIBRARY_INSTALL_NAME "${FUNCHOOK_LIBRARY_NAME}") - set(FUNCHOOK_LIBRARY_INSTALL_DIR "${FUNCHOOK_LIBRARY}") + set(PLTHook_SOURCE "${PLTHook_SOURCE_DIR}/plthook_elf.c") endif() -set(FUNCHOOK_INSTALL_DIR "${PROJECT_OUTPUT_DIR}") -set(FUNCHOOK_LIBRARY_INSTALL "${PROJECT_OUTPUT_DIR}/${FUNCHOOK_LIBRARY_INSTALL_NAME}") -set(FUNCHOOK_INCLUDE_DIR "${FUNCHOOK_SOURCE_DIR}/include") - -ExternalProject_Add(${target_depends} - PREFIX funchook - SOURCE_DIR ${FUNCHOOK_SOURCE_DIR} - INSTALL_DIR ${FUNCHOOK_INSTALL_DIR} - DOWNLOAD_COMMAND "${GIT_EXECUTABLE}" clone --single-branch --branch v${FUNCHOOK_VERSION} --recursive https://github.com/kubo/funchook.git "${FUNCHOOK_SOURCE_DIR}" - CONFIGURE_COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" -DCMAKE_BUILD_PARALLEL_LEVEL=1 -DCMAKE_PLATFORM_NO_VERSIONED_SONAME=ON -DCMAKE_INSTALL_PREFIX=${FUNCHOOK_INSTALL_DIR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DFUNCHOOK_BUILD_SHARED=ON -DFUNCHOOK_BUILD_TESTS=OFF -DFUNCHOOK_BUILD_STATIC=OFF . - BUILD_COMMAND ${CMAKE_COMMAND} -E env CMAKE_BUILD_PARALLEL_LEVEL=1 ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE} - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy "${FUNCHOOK_LIBRARY_INSTALL_DIR}" "${FUNCHOOK_INSTALL_DIR}" - UPDATE_COMMAND "" - BUILD_IN_SOURCE ON - LOG_DOWNLOAD ON - LOG_CONFIGURE ON - LOG_BUILD ON - LOG_INSTALL ON -) - # # Library name and options # # Target name -set(target funchook_detour) +set(target plthook_detour) # Exit here if required dependencies are not met message(STATUS "Detour ${target}") @@ -96,13 +65,14 @@ set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/${target}") set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") set(headers - ${include_path}/funchook_detour.h - ${include_path}/funchook_detour_impl.h + ${include_path}/plthook_detour.h + ${include_path}/plthook_detour_impl.h ) set(sources - ${source_path}/funchook_detour.c - ${source_path}/funchook_detour_impl.c + ${source_path}/plthook_detour.c + ${source_path}/plthook_detour_impl.c + ${PLTHook_SOURCE} # PLTHook Source ) # Group source files @@ -123,11 +93,6 @@ add_library(${target} MODULE ${headers} ) -# Add target dependencies -add_dependencies(${target} - ${target_depends} -) - # Create namespaced alias add_library(${META_PROJECT_NAME}::${target} ALIAS ${target}) @@ -162,7 +127,7 @@ target_include_directories(${target} ${CMAKE_CURRENT_BINARY_DIR}/include $ # MetaCall includes - ${FUNCHOOK_INCLUDE_DIR} # FuncHook includes + ${PLTHook_INCLUDE_DIR} # PLTHook includes PUBLIC ${DEFAULT_INCLUDE_DIRECTORIES} @@ -180,7 +145,6 @@ target_include_directories(${target} target_link_libraries(${target} PRIVATE ${META_PROJECT_NAME}::metacall # MetaCall library - ${FUNCHOOK_LIBRARY} # FuncHook libraries PUBLIC ${DEFAULT_LIBRARIES} @@ -234,7 +198,6 @@ target_link_options(${target} # Dependency install(FILES - ${FUNCHOOK_LIBRARY_INSTALL} DESTINATION ${INSTALL_LIB} COMPONENT runtime ) diff --git a/source/detours/funchook_detour/include/funchook_detour/funchook_detour.h b/source/detours/plthook_detour/include/plthook_detour/plthook_detour.h similarity index 80% rename from source/detours/funchook_detour/include/funchook_detour/funchook_detour.h rename to source/detours/plthook_detour/include/plthook_detour/plthook_detour.h index 98a71ea43..068ae11c6 100644 --- a/source/detours/funchook_detour/include/funchook_detour/funchook_detour.h +++ b/source/detours/plthook_detour/include/plthook_detour/plthook_detour.h @@ -18,12 +18,12 @@ * */ -#ifndef FUNCHOOK_DETOUR_H -#define FUNCHOOK_DETOUR_H 1 +#ifndef PLTHOOK_DETOUR_H +#define PLTHOOK_DETOUR_H 1 /* -- Headers -- */ -#include +#include #include @@ -41,7 +41,7 @@ extern "C" { * Returns pointer to interface to be used by implementation * */ -FUNCHOOK_DETOUR_API detour_interface funchook_detour_impl_interface_singleton(void); +PLTHOOK_DETOUR_API detour_interface plthook_detour_impl_interface_singleton(void); /** * @brief @@ -51,10 +51,10 @@ FUNCHOOK_DETOUR_API detour_interface funchook_detour_impl_interface_singleton(vo * Static string containing module information * */ -FUNCHOOK_DETOUR_API const char *funchook_detour_print_info(void); +PLTHOOK_DETOUR_API const char *plthook_detour_print_info(void); #ifdef __cplusplus } #endif -#endif /* FUNCHOOK_DETOUR_H */ +#endif /* PLTHOOK_DETOUR_H */ diff --git a/source/detours/plthook_detour/include/plthook_detour/plthook_detour_impl.h b/source/detours/plthook_detour/include/plthook_detour/plthook_detour_impl.h new file mode 100644 index 000000000..680cff01e --- /dev/null +++ b/source/detours/plthook_detour/include/plthook_detour/plthook_detour_impl.h @@ -0,0 +1,151 @@ +/* + * Detour Library by Parra Studios + * A cross-platform library providing detours, function hooks and trampolines. + * + * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia + * + * 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. + * + */ + +#ifndef PLTHOOK_DETOUR_IMPL_H +#define PLTHOOK_DETOUR_IMPL_H 1 + +/* -- Headers -- */ + +#include + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* -- Methods -- */ + +/** +* @brief +* Initialize PLTHook detour hook implementation by file name +* +* @param[out] handle +* When success, it returns the pointer to the detour implementation, null otherwise +* +* @param[in] path +* String containing the path or name to the dynamic library to be opened +* +* @return +* Returns zero on success, different from zero otherwise +* +*/ +PLTHOOK_DETOUR_API int plthook_detour_impl_initialize_file(detour_impl_handle *handle, const char *path); + +/** +* @brief +* Initialize PLTHook detour hook implementation by already l +* +* @param[out] handle +* When success, it returns the pointer to the detour implementation, null otherwiseoaded dynamic library handle +* +* @param[in] library +* Pointer to the dynlink handle of the library +* +* @return +* Returns zero on success, different from zero otherwise +* +*/ +PLTHOOK_DETOUR_API int plthook_detour_impl_initialize_handle(detour_impl_handle *handle, dynlink library); + +/** +* @brief +* Initialize PLTHook detour hook implementation by a functio +* +* @param[out] handle +* When success, it returns the pointer to the detour implementation, null otherwisen pointer of a function belonging to a library +* +* @param[in] address +* Function pointer of a function belonging to the library to be hooked +* +* @return +* Returns zero on success, different from zero otherwise +* +*/ +PLTHOOK_DETOUR_API int plthook_detour_impl_initialize_address(detour_impl_handle *handle, void (*address)(void)); + +/** +* @brief +* Iterate all symbols of the library already opened +* +* @param[in] handle +* Pointer to the detour hook implementation +* +* @param[out] position +* Pointer to the current index of the enumeration +* +* @param[out] name +* Pointer to the function name in string form +* +* @param[out] address +* Pointer to the pointer of the function pointer of the function to be hooked +* +* @return +* Return zero on success, different from zero otherwise +* +*/ +PLTHOOK_DETOUR_API int plthook_detour_impl_enumerate(detour_impl_handle handle, unsigned int *position, const char **name, void ***address); + +/** +* @brief +* Replace function from a library already opened by name, returns the old function pointer +* +* @param[in] handle +* Pointer to the detour hook implementation +* +* @param[in] function_name +* String containing the function name to be replaced +* +* @param[in] function_addr +* Function pointer that will be used to replace the original one +* +* @param[out] function_old_addr +* Function pointer to the original function that has been replaced +* +* @return +* Return zero on success, different from zero otherwise +* +*/ +PLTHOOK_DETOUR_API int plthook_detour_impl_replace(detour_impl_handle handle, const char *function_name, void (*function_addr)(void), void **function_old_addr); + +/** +* @brief +* Error handling PLTHook detour implementation +* +* @return +* Returns string containing the information of the error +* +*/ +PLTHOOK_DETOUR_API const char *plthook_detour_impl_error(detour_impl_handle handle); + +/** +* @brief +* Destroy PLTHook detour implementation +* +*/ +PLTHOOK_DETOUR_API void plthook_detour_impl_destroy(detour_impl_handle handle); + +#ifdef __cplusplus +} +#endif + +#endif /* PLTHOOK_DETOUR_IMPL_H */ diff --git a/source/detours/plthook_detour/source/plthook_detour.c b/source/detours/plthook_detour/source/plthook_detour.c new file mode 100644 index 000000000..b291b0b8e --- /dev/null +++ b/source/detours/plthook_detour/source/plthook_detour.c @@ -0,0 +1,48 @@ +/* + * Detour Library by Parra Studios + * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia + * + * A cross-platform library providing detours, function hooks and trampolines. + * + */ + +/* -- Headers -- */ + +#include + +#include +#include + +/* -- Methods -- */ + +detour_interface plthook_detour_impl_interface_singleton(void) +{ + static struct detour_interface_type interface_instance_plthook = { + &plthook_detour_impl_initialize_file, + &plthook_detour_impl_initialize_handle, + &plthook_detour_impl_initialize_address, + &plthook_detour_impl_enumerate, + &plthook_detour_impl_replace, + &plthook_detour_impl_error, + &plthook_detour_impl_destroy + }; + + return &interface_instance_plthook; +} + +const char *plthook_detour_print_info(void) +{ + static const char plthook_detour_info[] = + "PLTHook Detour Plugin " METACALL_VERSION "\n" + "Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia \n" + +#ifdef PLTHOOK_DETOUR_STATIC_DEFINE + "Compiled as static library type\n" +#else + "Compiled as shared library type\n" +#endif + + "\n"; + + return plthook_detour_info; +} diff --git a/source/detours/plthook_detour/source/plthook_detour_impl.c b/source/detours/plthook_detour/source/plthook_detour_impl.c new file mode 100644 index 000000000..33d23850d --- /dev/null +++ b/source/detours/plthook_detour/source/plthook_detour_impl.c @@ -0,0 +1,122 @@ +/* + * Detour Library by Parra Studios + * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia + * + * A cross-platform library providing detours, function hooks and trampolines. + * + */ + +/* -- Headers -- */ + +#include + +#include + +/* -- Methods -- */ + +int plthook_detour_impl_initialize_file(detour_impl_handle *handle, const char *path) +{ + plthook_t *plthook; + int result; + + if (handle == NULL) + { + return 1; + } + + result = plthook_open(&plthook, path); + + if (result != PLTHOOK_SUCCESS) + { + *handle = NULL; + return result; + } + + *handle = (void *)plthook; + return 0; +} + +int plthook_detour_impl_initialize_handle(detour_impl_handle *handle, dynlink library) +{ + plthook_t *plthook; + int result; + + if (handle == NULL) + { + return 1; + } + + result = plthook_open_by_handle(&plthook, dynlink_get_impl(library)); + + if (result != PLTHOOK_SUCCESS) + { + *handle = NULL; + return result; + } + + *handle = (void *)plthook; + return 0; +} + +int plthook_detour_impl_initialize_address(detour_impl_handle *handle, void (*address)(void)) + +{ + plthook_t *plthook; + void *ptr; + int result; + + if (handle == NULL) + { + return 1; + } + + dynlink_symbol_uncast(address, ptr); + + result = plthook_open_by_address(&plthook, ptr); + + if (result != PLTHOOK_SUCCESS) + { + *handle = NULL; + return result; + } + + *handle = (void *)plthook; + return 0; +} + +int plthook_detour_impl_enumerate(detour_impl_handle handle, unsigned int *position, const char **name, void ***address) +{ + if (handle == NULL) + { + return 1; + } + + return plthook_enum(handle, position, name, address); +} + +int plthook_detour_impl_replace(detour_impl_handle handle, const char *function_name, void (*function_addr)(void), void **function_old_addr) +{ + void *ptr; + + if (handle == NULL) + { + return 1; + } + + dynlink_symbol_uncast(function_addr, ptr); + + return plthook_replace(handle, function_name, ptr, function_old_addr); +} + +const char *plthook_detour_impl_error(detour_impl_handle handle) +{ + /* TODO: The error should be stored in the handle, this must be modified from plthook library itself */ + (void)handle; + + return plthook_error(); +} + +void plthook_detour_impl_destroy(detour_impl_handle handle) +{ + plthook_close(handle); +} diff --git a/source/dynlink/include/dynlink/dynlink.h b/source/dynlink/include/dynlink/dynlink.h index 28080638a..1a94636f0 100644 --- a/source/dynlink/include/dynlink/dynlink.h +++ b/source/dynlink/include/dynlink/dynlink.h @@ -36,6 +36,15 @@ extern "C" { /* -- Methods -- */ +/** +* @brief +* Get the library prefix for specified platform (normally "lib") +* +* @return +* A constant string pointer to the platform prefix +*/ +DYNLINK_API const char *dynlink_prefix(void); + /** * @brief * Get the library extension for specified platform @@ -61,7 +70,7 @@ DYNLINK_API const char *dynlink_extension(void); * @return * A handle to the dynamically linked shared object */ -DYNLINK_API dynlink dynlink_load(dynlink_path path, dynlink_name name, dynlink_flags flags); +DYNLINK_API dynlink dynlink_load(const char *path, const char *name, dynlink_flags flags); /** * @brief @@ -76,7 +85,19 @@ DYNLINK_API dynlink dynlink_load(dynlink_path path, dynlink_name name, dynlink_f * @return * A handle to the dynamically linked shared object */ -DYNLINK_API dynlink dynlink_load_absolute(dynlink_path path, dynlink_flags flags); +DYNLINK_API dynlink dynlink_load_absolute(const char *path, dynlink_flags flags); + +/** +* @brief +* Get the reference of the current process +* +* @param[in] flags +* Dynamic linking flags +* +* @return +* A handle to the current process +*/ +DYNLINK_API dynlink dynlink_load_self(dynlink_flags flags); /** * @brief @@ -88,19 +109,19 @@ DYNLINK_API dynlink dynlink_load_absolute(dynlink_path path, dynlink_flags flags * @return * Reference to the name of the dynamically linked shared object */ -DYNLINK_API dynlink_name dynlink_get_name(dynlink handle); +DYNLINK_API const char *dynlink_get_name(dynlink handle); /** * @brief -* Retreive the file name of the dynamically linked shared object handle +* Retreive the path of the dynamically linked shared object handle * * @param[in] handle * Handle of dynamically linked shared object * * @return -* Reference to the file name of the dynamically linked shared object +* Reference to the path of the dynamically linked shared object */ -DYNLINK_API dynlink_name dynlink_get_name_impl(dynlink handle); +DYNLINK_API const char *dynlink_get_path(dynlink handle); /** * @brief @@ -114,6 +135,18 @@ DYNLINK_API dynlink_name dynlink_get_name_impl(dynlink handle); */ DYNLINK_API dynlink_flags dynlink_get_flags(dynlink handle); +/** +* @brief +* Retreive the internal representation of the dynamically linked shared object +* +* @param[in] handle +* Handle of dynamically linked shared object +* +* @return +* The implementation dependant handle representing the dynamically linked shared object +*/ +DYNLINK_API dynlink_impl dynlink_get_impl(dynlink handle); + /** * @brief * Get a symbol address of dynamically linked shared object by name @@ -130,7 +163,7 @@ DYNLINK_API dynlink_flags dynlink_get_flags(dynlink handle); * @return * Returns zero on correct dynamic linking, distinct from zero otherwise */ -DYNLINK_API int dynlink_symbol(dynlink handle, dynlink_symbol_name symbol_name, dynlink_symbol_addr *symbol_address); +DYNLINK_API int dynlink_symbol(dynlink handle, const char *symbol_name, dynlink_symbol_addr *symbol_address); /** * @brief @@ -157,7 +190,7 @@ DYNLINK_API void dynlink_unload(dynlink handle); * @return * Returns zero if it could find the path, different from zero if not found */ -DYNLINK_API int dynlink_library_path(dynlink_name name, dynlink_library_path_str path, size_t *length); +DYNLINK_API int dynlink_library_path(const char *name, dynlink_path path, size_t *length); /** * @brief @@ -169,7 +202,7 @@ DYNLINK_API int dynlink_library_path(dynlink_name name, dynlink_library_path_str * @param[out] result * The resulting library name that will be generated (i.e libexample.so in Linux, or example.dll in Windows) */ -DYNLINK_API void dynlink_platform_name(dynlink_name name, dynlink_name_impl result); +DYNLINK_API void dynlink_platform_name(const char *name, dynlink_path result); /** * @brief diff --git a/source/dynlink/include/dynlink/dynlink_flags.h b/source/dynlink/include/dynlink/dynlink_flags.h index 2f64619e7..f72708a27 100644 --- a/source/dynlink/include/dynlink/dynlink_flags.h +++ b/source/dynlink/include/dynlink/dynlink_flags.h @@ -36,6 +36,8 @@ extern "C" { #define DYNLINK_FLAGS_BIND_LOCAL (0x01 << 0x02) /**< Private visibility bind flag */ #define DYNLINK_FLAGS_BIND_GLOBAL (0x01 << 0x03) /**< Public visibility bind flag */ +#define DYNLINK_FLAGS_BIND_SELF (0x01 << 0x10) /**< Private flag for when loading the current process */ + /* -- Macros -- */ /** diff --git a/source/dynlink/include/dynlink/dynlink_impl.h b/source/dynlink/include/dynlink/dynlink_impl.h index f6af1d6fb..d5d8728e6 100644 --- a/source/dynlink/include/dynlink/dynlink_impl.h +++ b/source/dynlink/include/dynlink/dynlink_impl.h @@ -35,6 +35,15 @@ extern "C" { /* -- Methods -- */ +/** +* @brief +* Dynamically linked shared object handle prefix implementation (normally "lib") +* +* @return +* A const string reference to the prefix depending on the OS implementation +*/ +DYNLINK_API const char *dynlink_impl_prefix(void); + /** * @brief * Dynamically linked shared object handle extension implementation @@ -51,19 +60,19 @@ DYNLINK_API const char *dynlink_impl_extension(void); * @param[in] name * Name of dynamically linked shared object * -* @param[out] name_impl -* Pointer to the dynamically linked shared object handle +* @param[out] destination +* Pointer to string where final platform dependant name will be stored * * @param[in] size -* Size of string @name_impl +* Size of string @destination */ -DYNLINK_API void dynlink_impl_get_name(dynlink_name name, dynlink_name_impl name_impl, size_t size); +DYNLINK_API void dynlink_impl_get_name(const char *name, dynlink_path destination, size_t size); /** * @brief * Load a dynamically linked shared object implementation * -* @param[in] name +* @param[in] handle * Pointer to the dynamically linked shared object handle * * @return @@ -90,7 +99,7 @@ DYNLINK_API dynlink_impl dynlink_impl_load(dynlink handle); * @return * Returns zero on correct dynamic linking, distinct from zero otherwise */ -DYNLINK_API int dynlink_impl_symbol(dynlink handle, dynlink_impl impl, dynlink_symbol_name symbol_name, dynlink_symbol_addr *symbol_address); +DYNLINK_API int dynlink_impl_symbol(dynlink handle, dynlink_impl impl, const char *symbol_name, dynlink_symbol_addr *symbol_address); /** * @brief diff --git a/source/dynlink/include/dynlink/dynlink_interface.h b/source/dynlink/include/dynlink/dynlink_interface.h index 80b34fc39..445a0cd4d 100644 --- a/source/dynlink/include/dynlink/dynlink_interface.h +++ b/source/dynlink/include/dynlink/dynlink_interface.h @@ -54,16 +54,16 @@ extern "C" { typedef dynlink_symbol_addr *dynlink_symbol_addr_ptr; +typedef const char *(*dynlink_impl_interface_prefix)(void); typedef const char *(*dynlink_impl_interface_extension)(void); -typedef void (*dynlink_impl_interface_get_name)(dynlink_name, dynlink_name_impl, size_t); typedef dynlink_impl (*dynlink_impl_interface_load)(dynlink); -typedef int (*dynlink_impl_interface_symbol)(dynlink, dynlink_impl, dynlink_symbol_name, dynlink_symbol_addr_ptr); +typedef int (*dynlink_impl_interface_symbol)(dynlink, dynlink_impl, const char *, dynlink_symbol_addr_ptr); typedef int (*dynlink_impl_interface_unload)(dynlink, dynlink_impl); struct dynlink_impl_interface_type { + dynlink_impl_interface_prefix prefix; dynlink_impl_interface_extension extension; - dynlink_impl_interface_get_name get_name; dynlink_impl_interface_load load; dynlink_impl_interface_symbol symbol; dynlink_impl_interface_unload unload; diff --git a/source/dynlink/include/dynlink/dynlink_type.h b/source/dynlink/include/dynlink/dynlink_type.h index cc759e25f..d6b737e57 100644 --- a/source/dynlink/include/dynlink/dynlink_type.h +++ b/source/dynlink/include/dynlink/dynlink_type.h @@ -37,14 +37,10 @@ struct dynlink_type; /* -- Type definitions -- */ -typedef struct dynlink_type *dynlink; /**< Dynamically linked shared object handle */ -typedef const char *dynlink_path; /**< Dynamically linked shared object path */ -typedef const char *dynlink_name; /**< Dynamically linked shared object name */ -typedef const char *dynlink_symbol_name; /**< Dynamically linked shared object symbol name */ -typedef portability_library_path_str dynlink_library_path_str; /**< Dynamically linked shared object symbol name */ -typedef void *dynlink_impl; /**< Dynamically linked shared object implementation */ -typedef char dynlink_name_impl[PORTABILITY_PATH_SIZE]; /**< Allocated copy of dynamically linked shared object name */ -typedef void (*dynlink_symbol_addr)(void); /**< Function pointer referring to a symbol address */ +typedef struct dynlink_type *dynlink; /**< Dynamically linked shared object handle */ +typedef void *dynlink_impl; /**< Dynamically linked shared object implementation */ +typedef char dynlink_path[PORTABILITY_PATH_SIZE]; /**< Allocated copy of dynamically linked shared object name */ +typedef void (*dynlink_symbol_addr)(void); /**< Function pointer referring to a symbol address */ /* -- Macros -- */ diff --git a/source/dynlink/source/dynlink.c b/source/dynlink/source/dynlink.c index 16266c163..216c18d37 100644 --- a/source/dynlink/source/dynlink.c +++ b/source/dynlink/source/dynlink.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -34,20 +35,25 @@ struct dynlink_type { - dynlink_name_impl name; /**< Dynamically linked shared object name */ - dynlink_name_impl name_impl; /**< Dynamically linked shared object file name */ - dynlink_flags flags; /**< Dynamically linked shared object flags */ - dynlink_impl impl; /**< Dynamically linked shared object loader implementation */ + dynlink_path name; /**< Dynamically linked shared object name */ + dynlink_path path; /**< Dynamically linked shared object file name */ + dynlink_flags flags; /**< Dynamically linked shared object flags */ + dynlink_impl impl; /**< Dynamically linked shared object loader implementation */ }; /* -- Methods -- */ +const char *dynlink_prefix(void) +{ + return dynlink_impl_prefix(); +} + const char *dynlink_extension(void) { return dynlink_impl_extension(); } -dynlink dynlink_load(dynlink_path path, dynlink_name name, dynlink_flags flags) +dynlink dynlink_load(const char *path, const char *name, dynlink_flags flags) { if (name != NULL) { @@ -55,26 +61,26 @@ dynlink dynlink_load(dynlink_path path, dynlink_name name, dynlink_flags flags) if (handle != NULL) { - dynlink_name_impl name_impl; + dynlink_path name_impl; strncpy(handle->name, name, PORTABILITY_PATH_SIZE - 1); - dynlink_impl_get_name(dynlink_get_name(handle), name_impl, PORTABILITY_PATH_SIZE); + dynlink_impl_get_name(handle->name, name_impl, PORTABILITY_PATH_SIZE); if (path != NULL) { - dynlink_name_impl join_path; + dynlink_path join_path; size_t join_path_size = portability_path_join(path, strnlen(path, PORTABILITY_PATH_SIZE) + 1, name_impl, strnlen(name_impl, PORTABILITY_PATH_SIZE) + 1, join_path, PORTABILITY_PATH_SIZE); - (void)portability_path_canonical(join_path, join_path_size, handle->name_impl, PORTABILITY_PATH_SIZE); + (void)portability_path_canonical(join_path, join_path_size, handle->path, PORTABILITY_PATH_SIZE); } else { - strncpy(handle->name_impl, name_impl, strnlen(name_impl, PORTABILITY_PATH_SIZE) + 1); + strncpy(handle->path, name_impl, strnlen(name_impl, PORTABILITY_PATH_SIZE) + 1); } - handle->flags = flags; + DYNLINK_FLAGS_SET(handle->flags, flags); handle->impl = dynlink_impl_load(handle); @@ -90,8 +96,53 @@ dynlink dynlink_load(dynlink_path path, dynlink_name name, dynlink_flags flags) return NULL; } -dynlink dynlink_load_absolute(dynlink_path path, dynlink_flags flags) +dynlink dynlink_load_absolute(const char *path, dynlink_flags flags) +{ + dynlink handle = malloc(sizeof(struct dynlink_type)); + size_t path_size, name_size, prefix_length; + const char *prefix = dynlink_prefix(); + + if (handle == NULL) + { + return NULL; + } + + path_size = strnlen(path, PORTABILITY_PATH_SIZE) + 1; + + strncpy(handle->path, path, path_size); + + /* Get the library name without any extension */ + name_size = portability_path_get_name_canonical(path, path_size, handle->name, PORTABILITY_PATH_SIZE); + + /* Remove the library prefix */ + prefix_length = strlen(prefix); + + if (strncmp(prefix, handle->name, prefix_length) == 0) + { + size_t current, next = prefix_length, end = name_size - prefix_length; + + for (current = 0; current < end; ++current, ++next) + { + handle->name[current] = handle->name[next]; + } + } + + DYNLINK_FLAGS_SET(handle->flags, flags); + + handle->impl = dynlink_impl_load(handle); + + if (handle->impl == NULL) + { + free(handle); + return NULL; + } + + return handle; +} + +dynlink dynlink_load_self(dynlink_flags flags) { + portability_executable_path_length path_length; dynlink handle = malloc(sizeof(struct dynlink_type)); if (handle == NULL) @@ -99,9 +150,18 @@ dynlink dynlink_load_absolute(dynlink_path path, dynlink_flags flags) return NULL; } - strncpy(handle->name_impl, path, strnlen(path, PORTABILITY_PATH_SIZE) + 1); + /* Retrieve the executable path for the full name */ + portability_executable_path(handle->path, &path_length); + + /* Get the name without the extension */ + portability_path_get_name(handle->path, path_length + 1, handle->name, PORTABILITY_PATH_SIZE); - handle->flags = flags; + /* Set the flags with the additional special flag for itself, + this will help to identify that the handle loaded is the current executable + and behave accordingly depending on the implementation + */ + DYNLINK_FLAGS_SET(handle->flags, flags); + DYNLINK_FLAGS_ADD(handle->flags, DYNLINK_FLAGS_BIND_SELF); handle->impl = dynlink_impl_load(handle); @@ -114,7 +174,7 @@ dynlink dynlink_load_absolute(dynlink_path path, dynlink_flags flags) return handle; } -dynlink_name dynlink_get_name(dynlink handle) +const char *dynlink_get_name(dynlink handle) { if (handle != NULL) { @@ -124,11 +184,11 @@ dynlink_name dynlink_get_name(dynlink handle) return NULL; } -dynlink_name dynlink_get_name_impl(dynlink handle) +const char *dynlink_get_path(dynlink handle) { if (handle != NULL) { - return handle->name_impl; + return handle->path; } return NULL; @@ -144,7 +204,17 @@ dynlink_flags dynlink_get_flags(dynlink handle) return 0; } -int dynlink_symbol(dynlink handle, dynlink_symbol_name symbol_name, dynlink_symbol_addr *symbol_address) +dynlink_impl dynlink_get_impl(dynlink handle) +{ + if (handle != NULL) + { + return handle->impl; + } + + return NULL; +} + +int dynlink_symbol(dynlink handle, const char *symbol_name, dynlink_symbol_addr *symbol_address) { if (handle != NULL && handle->impl != NULL && symbol_name != NULL && symbol_address != NULL) { @@ -164,13 +234,13 @@ void dynlink_unload(dynlink handle) } } -int dynlink_library_path(dynlink_name name, dynlink_library_path_str path, size_t *length) +int dynlink_library_path(const char *name, dynlink_path path, size_t *length) { - dynlink_name_impl name_impl; + dynlink_path name_impl; dynlink_impl_get_name(name, name_impl, PORTABILITY_PATH_SIZE); - if (portability_library_path(name_impl, path, length) != 0) + if (portability_library_path_find(name_impl, path, length) != 0) { return 1; } @@ -181,13 +251,13 @@ int dynlink_library_path(dynlink_name name, dynlink_library_path_str path, size_ } else { - (void)portability_path_get_directory_inplace(path, strnlen(path, sizeof(dynlink_library_path_str) / sizeof(char)) + 1); + (void)portability_path_get_directory_inplace(path, strnlen(path, PORTABILITY_PATH_SIZE)); } return 0; } -void dynlink_platform_name(dynlink_name name, dynlink_name_impl result) +void dynlink_platform_name(const char *name, dynlink_path result) { dynlink_impl_get_name(name, result, PORTABILITY_PATH_SIZE); } diff --git a/source/dynlink/source/dynlink_impl.c b/source/dynlink/source/dynlink_impl.c index 86092ad43..f49fece5c 100644 --- a/source/dynlink/source/dynlink_impl.c +++ b/source/dynlink/source/dynlink_impl.c @@ -28,6 +28,13 @@ /* -- Methods -- */ +const char *dynlink_impl_prefix(void) +{ + dynlink_impl_interface_singleton_ptr singleton = dynlink_interface(); + + return singleton()->prefix(); +} + const char *dynlink_impl_extension(void) { dynlink_impl_interface_singleton_ptr singleton = dynlink_interface(); @@ -35,13 +42,17 @@ const char *dynlink_impl_extension(void) return singleton()->extension(); } -void dynlink_impl_get_name(dynlink_name name, dynlink_name_impl name_impl, size_t size) +void dynlink_impl_get_name(const char *name, dynlink_path destination, size_t size) { - if (name != NULL && name_impl != NULL && size > 1) + if (name != NULL && destination != NULL && size > 1) { - dynlink_impl_interface_singleton_ptr singleton = dynlink_interface(); + strncpy(destination, dynlink_impl_prefix(), size); + + strncat(destination, name, size - 1); + + strncat(destination, ".", size - 1); - singleton()->get_name(name, name_impl, size); + strncat(destination, dynlink_impl_extension(), size - 1); } } @@ -52,7 +63,7 @@ dynlink_impl dynlink_impl_load(dynlink handle) return singleton()->load(handle); } -int dynlink_impl_symbol(dynlink handle, dynlink_impl impl, dynlink_symbol_name symbol_name, dynlink_symbol_addr *symbol_address) +int dynlink_impl_symbol(dynlink handle, dynlink_impl impl, const char *symbol_name, dynlink_symbol_addr *symbol_address) { if (impl != NULL) { diff --git a/source/dynlink/source/dynlink_impl_beos.c b/source/dynlink/source/dynlink_impl_beos.c index 7f9adbbae..98d5a07cc 100644 --- a/source/dynlink/source/dynlink_impl_beos.c +++ b/source/dynlink/source/dynlink_impl_beos.c @@ -31,47 +31,53 @@ /* -- Methods -- */ -const char *dynlink_impl_interface_extension_beos(void) +const char *dynlink_impl_interface_prefix_beos(void) { - static const char extension_beos[] = "so"; + static const char prefix_beos[] = "lib"; - return extension_beos; + return prefix_beos; } -void dynlink_impl_interface_get_name_beos(dynlink_name name, dynlink_name_impl name_impl, size_t size) +const char *dynlink_impl_interface_extension_beos(void) { - strncpy(name_impl, "lib", size); - - strncat(name_impl, name, size - 1); - - strncat(name_impl, ".", size - 1); + static const char extension_beos[] = "so"; - strncat(name_impl, dynlink_impl_extension(), size - 1); + return extension_beos; } dynlink_impl dynlink_impl_interface_load_beos(dynlink handle) { dynlink_flags flags = dynlink_get_flags(handle); + image_id impl = 0; - int flags_impl; - - image_id impl; + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) + { + image_info info; + int32 cookie = 0; - DYNLINK_FLAGS_SET(flags_impl, 0); + if (get_next_image_info(0, &cookie, &info) != B_OK) + { + log_write("metacall", LOG_LEVEL_ERROR, "DynLink error: failed to load BeOS/Haiku image add-on on current executable"); + return NULL; + } - impl = load_add_on(dynlink_get_name_impl(handle)); + impl = load_add_on(info.name); + } + else + { + impl = load_add_on(dynlink_get_path(handle)); + } if (impl < B_NO_ERROR) { - return (dynlink_impl)impl; + log_write("metacall", LOG_LEVEL_ERROR, "DynLink error: failed to load BeOS/Haiku image add-on with error code %d", (int)impl); + return NULL; } - log_write("metacall", LOG_LEVEL_ERROR, "DynLink error: failed to load BeOS/Haiku image add-on"); - - return NULL; + return (dynlink_impl)impl; } -int dynlink_impl_interface_symbol_beos(dynlink handle, dynlink_impl impl, dynlink_symbol_name name, dynlink_symbol_addr *addr) +int dynlink_impl_interface_symbol_beos(dynlink handle, dynlink_impl impl, const char *name, dynlink_symbol_addr *addr) { void *symbol = NULL; @@ -92,8 +98,16 @@ int dynlink_impl_interface_symbol_beos(dynlink handle, dynlink_impl impl, dynlin int dynlink_impl_interface_unload_beos(dynlink handle, dynlink_impl impl) { + dynlink_flags flags = dynlink_get_flags(handle); + (void)handle; + /* Skip unlink when using global handle for loading symbols of the current process */ + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) + { + return 0; + } + #if defined(__MEMORYCHECK__) || defined(__ADDRESS_SANITIZER__) || defined(__THREAD_SANITIZER__) || defined(__MEMORY_SANITIZER__) /* Disable dlclose when running with address sanitizer in order to maintain stacktraces */ (void)impl; @@ -106,8 +120,8 @@ int dynlink_impl_interface_unload_beos(dynlink handle, dynlink_impl impl) dynlink_impl_interface dynlink_impl_interface_singleton(void) { static struct dynlink_impl_interface_type impl_interface_beos = { + &dynlink_impl_interface_prefix_beos, &dynlink_impl_interface_extension_beos, - &dynlink_impl_interface_get_name_beos, &dynlink_impl_interface_load_beos, &dynlink_impl_interface_symbol_beos, &dynlink_impl_interface_unload_beos, diff --git a/source/dynlink/source/dynlink_impl_macos.c b/source/dynlink/source/dynlink_impl_macos.c index 4cfe04209..48c7a4daf 100644 --- a/source/dynlink/source/dynlink_impl_macos.c +++ b/source/dynlink/source/dynlink_impl_macos.c @@ -32,86 +32,92 @@ #include +/* -- Member Data -- */ + +static void *dynlink_impl_global_handle_macos = NULL; + /* -- Methods -- */ -const char *dynlink_impl_interface_extension_macos(void) +const char *dynlink_impl_interface_prefix_macos(void) { - static const char extension_macos[] = "dylib"; + static const char prefix_macos[] = "lib"; - return extension_macos; + return prefix_macos; } -void dynlink_impl_interface_get_name_macos(dynlink_name name, dynlink_name_impl name_impl, size_t size) +const char *dynlink_impl_interface_extension_macos(void) { - strncpy(name_impl, name, size); - - strncat(name_impl, ".", size - 1); + static const char extension_macos[] = "dylib"; - strncat(name_impl, dynlink_impl_extension(), size - 1); + return extension_macos; } dynlink_impl dynlink_impl_interface_load_macos(dynlink handle) { dynlink_flags flags = dynlink_get_flags(handle); - - unsigned long flags_impl; - - NSObjectFileImage image; - NSModule impl; - const char *name = dynlink_get_name_impl(handle); - - NSObjectFileImageReturnCode ret = NSCreateObjectFileImageFromFile(name, &image); - - if (ret != NSObjectFileImageSuccess) + if (!DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) { - char *error; + unsigned long flags_impl; + NSObjectFileImage image; + const char *name = dynlink_get_path(handle); + NSObjectFileImageReturnCode ret = NSCreateObjectFileImageFromFile(name, &image); - switch (ret) + if (ret != NSObjectFileImageSuccess) { - case NSObjectFileImageAccess: - if (access(name, F_OK) == 0) - { - error = "DynLink error: %s permission denied"; - } - else - { - error = "DynLink error: %s no such file or directory"; - } - case NSObjectFileImageArch: - error = "DynLink error: %s is not built for the current architecture"; - break; - case NSObjectFileImageInappropriateFile: - case NSObjectFileImageFormat: - error = "DynLink error: %s is not a loadable module"; - break; - default: - error = "DynLink error: unknown error for %s"; - break; + char *error; + + switch (ret) + { + case NSObjectFileImageAccess: + if (access(name, F_OK) == 0) + { + error = "DynLink error: %s permission denied"; + } + else + { + error = "DynLink error: %s no such file or directory"; + } + case NSObjectFileImageArch: + error = "DynLink error: %s is not built for the current architecture"; + break; + case NSObjectFileImageInappropriateFile: + case NSObjectFileImageFormat: + error = "DynLink error: %s is not a loadable module"; + break; + default: + error = "DynLink error: unknown error for %s"; + break; + } + + log_write("metacall", LOG_LEVEL_ERROR, error, name); + + return NULL; } - log_write("metacall", LOG_LEVEL_ERROR, error, name); + DYNLINK_FLAGS_SET(flags_impl, NSLINKMODULE_OPTION_RETURN_ON_ERROR); - return NULL; - } + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_LOCAL)) + { + DYNLINK_FLAGS_ADD(flags_impl, NSLINKMODULE_OPTION_PRIVATE); + } + + if (!DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_LAZY)) + { + DYNLINK_FLAGS_ADD(flags_impl, NSLINKMODULE_OPTION_BINDNOW); + } - DYNLINK_FLAGS_SET(flags_impl, NSLINKMODULE_OPTION_RETURN_ON_ERROR); + impl = NSLinkModule(image, name, flags_impl); - if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_LOCAL)) - { - DYNLINK_FLAGS_ADD(flags_impl, NSLINKMODULE_OPTION_PRIVATE); + NSDestroyObjectFileImage(image); } - - if (!DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_LAZY)) + else { - DYNLINK_FLAGS_ADD(flags_impl, NSLINKMODULE_OPTION_BINDNOW); + /* We return this for identifying the global handle when loading symbols of the current process */ + impl = (void *)(&dynlink_impl_global_handle_macos); } - impl = NSLinkModule(image, name, flags_impl); - - NSDestroyObjectFileImage(image); - if (impl == NULL) { NSLinkEditErrors link_edit_errors; @@ -130,13 +136,32 @@ dynlink_impl dynlink_impl_interface_load_macos(dynlink handle) return (dynlink_impl)impl; } -int dynlink_impl_interface_symbol_macos(dynlink handle, dynlink_impl impl, dynlink_symbol_name name, dynlink_symbol_addr *addr) +int dynlink_impl_interface_symbol_macos(dynlink handle, dynlink_impl impl, const char *name, dynlink_symbol_addr *addr) { - NSSymbol symbol = NSLookupSymbolInModule(impl, name); - void *symbol_addr = NSAddressOfSymbol(symbol); + dynlink_flags flags = dynlink_get_flags(handle); + NSSymbol symbol; + void *symbol_addr; (void)handle; + /* Skip unlink when using global handle for loading symbols of the current process */ + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) + { + /* Global context, use NSLookupAndBindSymbol */ + if (!NSIsSymbolNameDefined(name)) + { + return 1; + } + + symbol = NSLookupAndBindSymbol(name); + } + else + { + symbol = NSLookupSymbolInModule(impl, name); + } + + symbol_addr = NSAddressOfSymbol(symbol); + dynlink_symbol_cast(void *, symbol_addr, *addr); return (*addr == NULL); @@ -144,16 +169,30 @@ int dynlink_impl_interface_symbol_macos(dynlink handle, dynlink_impl impl, dynli int dynlink_impl_interface_unload_macos(dynlink handle, dynlink_impl impl) { + dynlink_flags flags = dynlink_get_flags(handle); + (void)handle; + /* Skip unlink when using global handle for loading symbols of the current process */ + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) + { + return 0; + } + +#if defined(__MEMORYCHECK__) || defined(__ADDRESS_SANITIZER__) || defined(__THREAD_SANITIZER__) || defined(__MEMORY_SANITIZER__) + /* Disable dlclose when running with address sanitizer in order to maintain stacktraces */ + (void)impl; + return 0; +#else return NSUnLinkModule(impl, 0) == TRUE ? 0 : 1; +#endif } dynlink_impl_interface dynlink_impl_interface_singleton(void) { static struct dynlink_impl_interface_type impl_interface_macos = { + &dynlink_impl_interface_prefix_macos, &dynlink_impl_interface_extension_macos, - &dynlink_impl_interface_get_name_macos, &dynlink_impl_interface_load_macos, &dynlink_impl_interface_symbol_macos, &dynlink_impl_interface_unload_macos, diff --git a/source/dynlink/source/dynlink_impl_unix.c b/source/dynlink/source/dynlink_impl_unix.c index 8892797f9..7a6d35711 100644 --- a/source/dynlink/source/dynlink_impl_unix.c +++ b/source/dynlink/source/dynlink_impl_unix.c @@ -28,41 +28,28 @@ #include -#ifndef _GNU_SOURCE - #define _GNU_SOURCE -#endif -#ifndef __USE_GNU - #define __USE_GNU -#endif - #include /* -- Methods -- */ -const char *dynlink_impl_interface_extension_unix(void) +const char *dynlink_impl_interface_prefix_unix(void) { - static const char extension_unix[] = "so"; + static const char prefix_unix[] = "lib"; - return extension_unix; + return prefix_unix; } -void dynlink_impl_interface_get_name_unix(dynlink_name name, dynlink_name_impl name_impl, size_t size) +const char *dynlink_impl_interface_extension_unix(void) { - strncpy(name_impl, "lib", size); - - strncat(name_impl, name, size - 1); - - strncat(name_impl, ".", size - 1); + static const char extension_unix[] = "so"; - strncat(name_impl, dynlink_impl_extension(), size - 1); + return extension_unix; } dynlink_impl dynlink_impl_interface_load_unix(dynlink handle) { dynlink_flags flags = dynlink_get_flags(handle); - int flags_impl; - void *impl; DYNLINK_FLAGS_SET(flags_impl, 0); @@ -87,19 +74,26 @@ dynlink_impl dynlink_impl_interface_load_unix(dynlink handle) DYNLINK_FLAGS_ADD(flags_impl, RTLD_GLOBAL); } - impl = dlopen(dynlink_get_name_impl(handle), flags_impl); - - if (impl != NULL) + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) + { + impl = dlopen(NULL, flags_impl); + } + else { - return (dynlink_impl)impl; + impl = dlopen(dynlink_get_path(handle), flags_impl); } - log_write("metacall", LOG_LEVEL_ERROR, "DynLink error: %s", dlerror()); + if (impl == NULL) + { + log_write("metacall", LOG_LEVEL_ERROR, "DynLink error: %s", dlerror()); + + return NULL; + } - return NULL; + return (dynlink_impl)impl; } -int dynlink_impl_interface_symbol_unix(dynlink handle, dynlink_impl impl, dynlink_symbol_name name, dynlink_symbol_addr *addr) +int dynlink_impl_interface_symbol_unix(dynlink handle, dynlink_impl impl, const char *name, dynlink_symbol_addr *addr) { void *symbol = dlsym(impl, name); @@ -112,8 +106,16 @@ int dynlink_impl_interface_symbol_unix(dynlink handle, dynlink_impl impl, dynlin int dynlink_impl_interface_unload_unix(dynlink handle, dynlink_impl impl) { + dynlink_flags flags = dynlink_get_flags(handle); + (void)handle; + /* Skip unlink when using global handle for loading symbols of the current process */ + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) + { + return 0; + } + #if defined(__MEMORYCHECK__) || defined(__ADDRESS_SANITIZER__) || defined(__THREAD_SANITIZER__) || defined(__MEMORY_SANITIZER__) /* Disable dlclose when running with valgrind or sanitizers in order to maintain stacktraces */ (void)impl; @@ -126,8 +128,8 @@ int dynlink_impl_interface_unload_unix(dynlink handle, dynlink_impl impl) dynlink_impl_interface dynlink_impl_interface_singleton(void) { static struct dynlink_impl_interface_type impl_interface_unix = { + &dynlink_impl_interface_prefix_unix, &dynlink_impl_interface_extension_unix, - &dynlink_impl_interface_get_name_unix, &dynlink_impl_interface_load_unix, &dynlink_impl_interface_symbol_unix, &dynlink_impl_interface_unload_unix, diff --git a/source/dynlink/source/dynlink_impl_win32.c b/source/dynlink/source/dynlink_impl_win32.c index 8009aea54..d1956a965 100644 --- a/source/dynlink/source/dynlink_impl_win32.c +++ b/source/dynlink/source/dynlink_impl_win32.c @@ -32,31 +32,37 @@ /* -- Methods -- */ -const char *dynlink_impl_interface_extension_win32(void) -{ - static const char extension_win32[] = "dll"; - - return extension_win32; -} - -void dynlink_impl_interface_get_name_win32(dynlink_name name, dynlink_name_impl name_impl, size_t size) +const char *dynlink_impl_interface_prefix_win32(void) { #if defined(__MINGW32__) || defined(__MINGW64__) - strncpy(name_impl, "lib", size); - - strncat(name_impl, name, size - 1); + static const char prefix_win32[] = "lib"; #else - strncpy(name_impl, name, size); + static const char prefix_win32[] = ""; #endif - strncat(name_impl, ".", size - 1); + return prefix_win32; +} + +const char *dynlink_impl_interface_extension_win32(void) +{ + static const char extension_win32[] = "dll"; - strncat(name_impl, dynlink_impl_extension(), size - 1); + return extension_win32; } dynlink_impl dynlink_impl_interface_load_win32(dynlink handle) { - HANDLE impl = LoadLibrary(dynlink_get_name_impl(handle)); + HMODULE impl; + dynlink_flags flags = dynlink_get_flags(handle); + + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) + { + impl = GetModuleHandle(NULL); + } + else + { + impl = LoadLibrary(dynlink_get_path(handle)); + } if (impl == NULL) { @@ -66,7 +72,7 @@ dynlink_impl dynlink_impl_interface_load_win32(dynlink handle) size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&message_buffer, 0, NULL); - log_write("metacall", LOG_LEVEL_ERROR, "Failed to load: %s with error code [%d]: %.*s", dynlink_get_name_impl(handle), error_id, size - 1, (const char *)message_buffer); + log_write("metacall", LOG_LEVEL_ERROR, "Failed to load: %s with error code [%d]: %.*s", dynlink_get_path(handle), error_id, size - 1, (const char *)message_buffer); LocalFree(message_buffer); @@ -76,7 +82,7 @@ dynlink_impl dynlink_impl_interface_load_win32(dynlink handle) return (dynlink_impl)impl; } -int dynlink_impl_interface_symbol_win32(dynlink handle, dynlink_impl impl, dynlink_symbol_name name, dynlink_symbol_addr *addr) +int dynlink_impl_interface_symbol_win32(dynlink handle, dynlink_impl impl, const char *name, dynlink_symbol_addr *addr) { FARPROC proc_addr = GetProcAddress(impl, name); @@ -89,16 +95,30 @@ int dynlink_impl_interface_symbol_win32(dynlink handle, dynlink_impl impl, dynli int dynlink_impl_interface_unload_win32(dynlink handle, dynlink_impl impl) { + dynlink_flags flags = dynlink_get_flags(handle); + (void)handle; + /* Skip unlink when using global handle for loading symbols of the current process */ + if (DYNLINK_FLAGS_CHECK(flags, DYNLINK_FLAGS_BIND_SELF)) + { + return 0; + } + +#if defined(__MEMORYCHECK__) || defined(__ADDRESS_SANITIZER__) || defined(__THREAD_SANITIZER__) || defined(__MEMORY_SANITIZER__) + /* Disable dlclose when running with address sanitizer in order to maintain stacktraces */ + (void)impl; + return 0; +#else return (FreeLibrary(impl) == FALSE); +#endif } dynlink_impl_interface dynlink_impl_interface_singleton(void) { static struct dynlink_impl_interface_type impl_interface_win32 = { + &dynlink_impl_interface_prefix_win32, &dynlink_impl_interface_extension_win32, - &dynlink_impl_interface_get_name_win32, &dynlink_impl_interface_load_win32, &dynlink_impl_interface_symbol_win32, &dynlink_impl_interface_unload_win32, diff --git a/source/environment/source/environment_variable.c b/source/environment/source/environment_variable.c index 9323e0163..a9e94eb23 100644 --- a/source/environment/source/environment_variable.c +++ b/source/environment/source/environment_variable.c @@ -77,7 +77,7 @@ const char *environment_variable_get(const char *name, const char *default_value int environment_variable_set(const char *name, const char *value_string) { -#if defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) return _putenv_s(name, value_string); #else return setenv(name, value_string, 1); diff --git a/source/loader/include/loader/loader.h b/source/loader/include/loader/loader.h index b4b8816a3..441cc938e 100644 --- a/source/loader/include/loader/loader.h +++ b/source/loader/include/loader/loader.h @@ -51,14 +51,18 @@ LOADER_API void loader_initialization_register(loader_impl impl); LOADER_API int loader_initialize(void); -LOADER_NO_EXPORT int loader_initialize_host(const loader_tag tag); - LOADER_API int loader_is_initialized(const loader_tag tag); LOADER_API int loader_register(const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[]); LOADER_API int loader_register_impl(void *impl, void *handle, const char *name, loader_register_invoke invoke, type_id return_type, size_t arg_size, type_id args_type_id[]); +LOADER_API void loader_detour(detour d); + +LOADER_API detour_handle loader_hook(const loader_tag tag, const char *library, int (*load_cb)(detour, detour_handle)); + +LOADER_API detour_handle loader_hook_impl(void *impl, const char *library, int (*load_cb)(detour, detour_handle)); + LOADER_API const char *loader_library_path(void); LOADER_API int loader_execution_path(const loader_tag tag, const loader_path path); @@ -77,14 +81,12 @@ LOADER_API loader_data loader_get(const char *name); LOADER_API void *loader_get_handle(const loader_tag tag, const char *name); -LOADER_API void loader_set_options(const loader_tag tag, void *options); +LOADER_API int loader_set_options(const loader_tag tag, value options); LOADER_API value loader_get_options(const loader_tag tag); LOADER_API value loader_get_option(const loader_tag tag, const char *field); -LOADER_API int loader_get_option_host(const loader_tag tag); - LOADER_API int loader_handle_initialize(loader_impl impl, const loader_path name, void **handle_ptr); LOADER_API const char *loader_handle_id(void *handle); diff --git a/source/loader/include/loader/loader_impl.h b/source/loader/include/loader/loader_impl.h index f7c7d56cb..6f3691d8f 100644 --- a/source/loader/include/loader/loader_impl.h +++ b/source/loader/include/loader/loader_impl.h @@ -29,6 +29,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -43,7 +45,13 @@ LOADER_API loader_impl loader_impl_create(const loader_tag tag); LOADER_API loader_impl loader_impl_create_host(const loader_tag tag); -LOADER_API int loader_impl_dependencies(loader_impl impl); +LOADER_API int loader_impl_dependencies(loader_impl impl, detour d); + +LOADER_API int loader_impl_link(plugin p, loader_impl impl); + +LOADER_API dynlink loader_impl_dependency(loader_impl impl, const char *library); + +LOADER_API detour_handle loader_impl_detour(loader_impl impl, const char *library, int (*load_cb)(detour, detour_handle)); LOADER_API void loader_impl_attach(loader_impl impl, plugin p); @@ -69,7 +77,7 @@ LOADER_API int loader_impl_load_from_package(plugin_manager manager, plugin p, l LOADER_API void *loader_impl_get_handle(loader_impl impl, const char *name); -LOADER_API void loader_impl_set_options(loader_impl impl, void *options); +LOADER_API void loader_impl_set_options(loader_impl impl, value options); LOADER_API value loader_impl_get_options(loader_impl impl); diff --git a/source/loader/include/loader/loader_manager_impl.h b/source/loader/include/loader/loader_manager_impl.h index 124aaf55c..3e9c4d82c 100644 --- a/source/loader/include/loader/loader_manager_impl.h +++ b/source/loader/include/loader/loader_manager_impl.h @@ -53,6 +53,7 @@ struct loader_manager_impl_type uint64_t init_thread_id; /* Stores the thread id of the thread that initialized metacall */ vector script_paths; /* Vector of search path for the scripts */ set destroy_map; /* Tracks the list of destroyed runtimes during destruction of the manager (loader_impl -> NULL) */ + detour d; /* Stores the detour manager that is being used for hooking */ }; /* -- Type Definitions -- */ diff --git a/source/loader/source/loader.c b/source/loader/source/loader.c index 02ec13573..0c055b01c 100644 --- a/source/loader/source/loader.c +++ b/source/loader/source/loader.c @@ -33,8 +33,6 @@ #include -#include - #include #include @@ -76,6 +74,8 @@ static void loader_initialization_register_plugin(plugin p); static plugin loader_get_impl_plugin(const loader_tag tag); +static plugin loader_get_impl_plugin_options(const loader_tag tag, value options); + static int loader_get_cb_iterate(plugin_manager manager, plugin p, void *data); static int loader_metadata_cb_iterate(plugin_manager manager, plugin p, void *data); @@ -134,6 +134,9 @@ int loader_initialize(void) /* Insert into destruction list */ loader_initialization_register_plugin(manager_impl->host); + /* Initialize detours */ + manager_impl->d = NULL; + /* TODO: Disable logs here until log is completely thread safe and async signal safe */ /* log_write("metacall", LOG_LEVEL_DEBUG, "Loader host initialized"); */ @@ -201,29 +204,6 @@ void loader_initialization_register_plugin(plugin p) } } -int loader_initialize_host(const loader_tag tag) -{ - plugin p = plugin_manager_get(&loader_manager, tag); - - if (p == NULL) - { - return 1; - } - - if (loader_impl_initialize(&loader_manager, p, plugin_impl_type(p, loader_impl)) != 0) - { - return 1; - } - else - { - loader_manager_impl manager_impl = plugin_manager_impl_type(&loader_manager, loader_manager_impl); - - manager_impl->host = p; - - return 0; - } -} - int loader_is_initialized(const loader_tag tag) { plugin p = plugin_manager_get(&loader_manager, tag); @@ -248,26 +228,53 @@ int loader_register_impl(void *impl, void *handle, const char *name, loader_regi return loader_host_register((loader_impl)impl, loader_impl_handle_context(handle), name, invoke, NULL, return_type, arg_size, args_type_id); } +void loader_detour(detour d) +{ + loader_manager_impl manager_impl = plugin_manager_impl_type(&loader_manager, loader_manager_impl); + + manager_impl->d = d; +} + +detour_handle loader_hook(const loader_tag tag, const char *library, int (*load_cb)(detour, detour_handle)) +{ + return loader_impl_detour(loader_get_impl(tag), library, load_cb); +} + +detour_handle loader_hook_impl(void *impl, const char *library, int (*load_cb)(detour, detour_handle)) +{ + return loader_impl_detour((loader_impl)impl, library, load_cb); +} + plugin loader_get_impl_plugin(const loader_tag tag) +{ + return loader_get_impl_plugin_options(tag, NULL); +} + +plugin loader_get_impl_plugin_options(const loader_tag tag, value options) { plugin p = plugin_manager_get(&loader_manager, tag); + loader_impl impl; + if (p != NULL) { return p; } - loader_impl impl = loader_impl_create(tag); + impl = loader_impl_create(tag); if (impl == NULL) { goto loader_create_error; } + /* Define the options */ + loader_impl_set_options(impl, options); + /* Dynamic link loader dependencies if it is not host */ - if (loader_impl_get_option_host(impl) == 0) + if (loader_impl_dependencies(impl, plugin_manager_impl_type(&loader_manager, loader_manager_impl)->d) != 0) { - loader_impl_dependencies(impl); + goto plugin_manager_create_error; } /* Dynamic link the loader */ @@ -278,9 +285,30 @@ plugin loader_get_impl_plugin(const loader_tag tag) goto plugin_manager_create_error; } + /* If it is host, link the loader symbols to the host (either the executable or a library) */ + if (loader_impl_link(p, impl) != 0) + { + goto plugin_manager_create_error; + } + /* Store in the loader implementation the reference to the plugin which belongs to */ loader_impl_attach(impl, p); + /* Check if it is host, initialize it and set it as host */ + if (options != NULL && loader_impl_get_option_host(impl) == 1) + { + loader_manager_impl manager_impl; + + if (loader_impl_initialize(&loader_manager, p, plugin_impl_type(p, loader_impl)) != 0) + { + goto plugin_manager_create_error; + } + + manager_impl = plugin_manager_impl_type(&loader_manager, loader_manager_impl); + + manager_impl->host = p; + } + /* TODO: Disable logs here until log is completely thread safe and async signal safe */ /* log_write("metacall", LOG_LEVEL_DEBUG, "Created loader (%s) implementation <%p>", tag, (void *)impl); */ @@ -570,11 +598,11 @@ void *loader_get_handle(const loader_tag tag, const char *name) return loader_impl_get_handle(plugin_impl_type(p, loader_impl), name); } -void loader_set_options(const loader_tag tag, void *options) +int loader_set_options(const loader_tag tag, value options) { - plugin p = loader_get_impl_plugin(tag); + plugin p = loader_get_impl_plugin_options(tag, options); - loader_impl_set_options(plugin_impl_type(p, loader_impl), options); + return (p == NULL); } value loader_get_options(const loader_tag tag) @@ -591,13 +619,6 @@ value loader_get_option(const loader_tag tag, const char *field) return loader_impl_get_option(plugin_impl_type(p, loader_impl), field); } -int loader_get_option_host(const loader_tag tag) -{ - plugin p = loader_get_impl_plugin(tag); - - return loader_impl_get_option_host(plugin_impl_type(p, loader_impl)); -} - int loader_handle_initialize(loader_impl impl, const loader_path name, void **handle_ptr) { if (loader_initialize() == 1) @@ -784,7 +805,7 @@ void loader_unload_children(loader_impl impl) * the loader has been unloaded, and the function interface will point to an unloaded * plugin, generating a segmentation fault. All the plugins will be unloaded on plugin_manager_destroy. */ - plugin_destroy_delayed(order->p); + plugin_destructor(order->p); /* Mark loader as destroyed (prevents access to already freed memory and defines what loaders are destroyed) */ loader_manager_impl_set_destroyed(manager_impl, destroyed_impl); diff --git a/source/loader/source/loader_host.c b/source/loader/source/loader_host.c index 440e3d36a..7ddfb65a4 100644 --- a/source/loader/source/loader_host.c +++ b/source/loader/source/loader_host.c @@ -44,7 +44,7 @@ union loader_host_invoke_cast static value function_host_interface_invoke(function func, function_impl func_impl, function_args args, size_t size); -static function_return function_host_interface_await(function func, function_impl impl, function_args args, size_t size, function_resolve_callback resolve_callback, function_reject_callback reject_callback, void *context); +static function_return function_host_interface_await(function func, function_impl impl, function_args args, size_t size, function_resolve_callback resolve_callback, function_reject_callback reject_callback, void *ctx); static function_interface function_host_singleton(void); @@ -64,7 +64,7 @@ function_return function_host_interface_invoke(function func, function_impl func return invoke_cast.fn(size, args, data); } -function_return function_host_interface_await(function func, function_impl impl, function_args args, size_t size, function_resolve_callback resolve_callback, function_reject_callback reject_callback, void *context) +function_return function_host_interface_await(function func, function_impl impl, function_args args, size_t size, function_resolve_callback resolve_callback, function_reject_callback reject_callback, void *ctx) { /* TODO */ @@ -74,7 +74,7 @@ function_return function_host_interface_await(function func, function_impl impl, (void)size; (void)resolve_callback; (void)reject_callback; - (void)context; + (void)ctx; return NULL; } diff --git a/source/loader/source/loader_impl.c b/source/loader/source/loader_impl.c index 2ad8034d8..33c232af6 100644 --- a/source/loader/source/loader_impl.c +++ b/source/loader/source/loader_impl.c @@ -36,6 +36,8 @@ #include +#include + #include #include @@ -90,6 +92,9 @@ struct loader_impl_type value options; /* Additional initialization options passed in the initialize phase */ set exec_path_map; /* Set of execution paths passed by the end user */ configuration config; /* Reference to the loader configuration, it contains execution_paths, dependencies and additional info */ + set library_map; /* List of handles (dynlink) to the dependencies of the loader and the loader itself */ + detour d; /* Reference to the detour which was used for hooking the loader or its dependencies */ + set detour_map; /* List of detour handles (detour_handle) to the dependencies of the loader and the loader itself */ }; struct loader_handle_impl_type @@ -120,6 +125,14 @@ struct loader_impl_metadata_cb_iterator_type static loader_impl loader_impl_allocate(const loader_tag tag); +static void loader_impl_configuration_execution_paths(loader_impl_interface iface, loader_impl impl); + +static int loader_impl_dependencies_self_list(const char *library, void *data); + +static int loader_impl_dependencies_self_find(loader_impl impl, const char *key_str, vector dependencies_self); + +static int loader_impl_dependencies_load(loader_impl impl, const char *key_str, value *paths_array, size_t paths_size); + static configuration loader_impl_initialize_configuration(const loader_tag tag); static int loader_impl_initialize_registered(plugin_manager manager, plugin p); @@ -208,8 +221,26 @@ loader_impl loader_impl_allocate(const loader_tag tag) goto alloc_exec_path_map_error; } + impl->library_map = set_create(&hash_callback_str, &comparable_callback_str); + + if (impl->library_map == NULL) + { + goto alloc_library_map_error; + } + + impl->detour_map = set_create(&hash_callback_str, &comparable_callback_str); + + if (impl->detour_map == NULL) + { + goto alloc_detour_map_error; + } + return impl; +alloc_detour_map_error: + set_destroy(impl->library_map); +alloc_library_map_error: + set_destroy(impl->exec_path_map); alloc_exec_path_map_error: context_destroy(impl->ctx); alloc_ctx_error: @@ -289,10 +320,85 @@ void loader_impl_configuration_execution_paths(loader_impl_interface iface, load } } -int loader_impl_dependencies(loader_impl impl) +int loader_impl_dependencies_self_list(const char *library, void *data) { - /* Dependencies have the following format */ - /* + vector dependencies_self = (vector)data; + + vector_push_back_empty(dependencies_self); + + strncpy(vector_back(dependencies_self), library, strnlen(library, PORTABILITY_PATH_SIZE) + 1); + + return 0; +} + +int loader_impl_dependencies_self_find(loader_impl impl, const char *key_str, vector dependencies_self) +{ + size_t iterator, size = vector_size(dependencies_self); + char library_self_name[PORTABILITY_PATH_SIZE]; + dynlink handle; + + /* Try to load it from the dependencies of the executable */ + for (iterator = 0; iterator < size; ++iterator) + { + const char *library_self = vector_at(dependencies_self, iterator); + + /* Get the name of the library */ + portability_path_get_fullname(library_self, strnlen(library_self, PORTABILITY_PATH_SIZE) + 1, library_self_name, PORTABILITY_PATH_SIZE); + + /* Try to find the dependency name in the library */ + if (strstr(library_self_name, key_str) != NULL) + { + handle = dynlink_load_absolute(library_self, DYNLINK_FLAGS_BIND_LAZY | DYNLINK_FLAGS_BIND_GLOBAL); + + goto dependencies_map_insert; + } + } + + /* If it is not found in the dependencies, it is linked statically to the executable, load it */ + handle = dynlink_load_self(DYNLINK_FLAGS_BIND_LAZY | DYNLINK_FLAGS_BIND_GLOBAL); + +dependencies_map_insert: + + if (handle != NULL && set_insert(impl->library_map, (const set_key)key_str, (set_value)handle) == 0) + { + return 0; + } + + dynlink_unload(handle); + + return 1; +} + +int loader_impl_dependencies_load(loader_impl impl, const char *key_str, value *paths_array, size_t paths_size) +{ + size_t iterator; + + for (iterator = 0; iterator < paths_size; ++iterator) + { + if (value_type_id(paths_array[iterator]) == TYPE_STRING) + { + const char *library_path = value_to_string(paths_array[iterator]); + + if (library_path != NULL) + { + dynlink handle = dynlink_load_absolute(library_path, DYNLINK_FLAGS_BIND_LAZY | DYNLINK_FLAGS_BIND_GLOBAL); + + if (handle != NULL && set_insert(impl->library_map, (const set_key)key_str, (set_value)handle) == 0) + { + return 0; + } + + dynlink_unload(handle); + } + } + } + + return 1; +} + +int loader_impl_dependencies(loader_impl impl, detour d) +{ + /* Dependencies have the following format: { "dependencies": { "node": ["/usr/lib/x86_64-linux-gnu/libnode.so.72"] @@ -301,58 +407,224 @@ int loader_impl_dependencies(loader_impl impl) */ value dependencies_value = configuration_value_type(impl->config, "dependencies", TYPE_MAP); + /* The algorithm works in the following way: + 1) If current loader is the host: + - Take the dependency name and try to find if it is already + loaded as a library in the current process, for example: + + "dependencies": { + "node": ["/usr/lib/x86_64-linux-gnu/libnode.so.72"] + } + + Will search for all libraries, looking for the library name + with the following substring (lib)node, so if we find: + + "/usr/lib/x86_64-linux-gnu/libnode.so.108" + + It will test against libnode.so.108 the substring (lib)node. + + - If it has not been found, then get the handle of the current process. + + 2) Otherwise, the current loader is not the host: + - Iterate the dependencies and if they are properly loaded, index + them by name in the dependency map, for example: + + [ Key ] => [ Value ] + "node" => "/usr/lib/x86_64-linux-gnu/libnode.so.72" + + The value in this case will be the library loaded, instead of the full path. + */ + + /* Initialize the loader detour */ + impl->d = d; + + /* Check if the loader has dependencies and load them */ if (dependencies_value != NULL) { size_t size = value_type_count(dependencies_value); value *dependencies_map = value_to_map(dependencies_value); + vector dependencies_self = NULL; size_t iterator; + const int host = loader_impl_get_option_host(impl); + /* In case of host, get all loaded dependencies into an array */ + if (host == 1) + { + dependencies_self = vector_create(sizeof(char) * PORTABILITY_PATH_SIZE); + + if (dependencies_self == NULL) + { + return 1; + } + + if (portability_library_path_list(&loader_impl_dependencies_self_list, (void *)dependencies_self) != 0) + { + vector_destroy(dependencies_self); + return 1; + } + } + + /* Iterate through the dependencies */ for (iterator = 0; iterator < size; ++iterator) { if (value_type_id(dependencies_map[iterator]) == TYPE_ARRAY) { value *library_tuple = value_to_array(dependencies_map[iterator]); - if (value_type_id(library_tuple[1]) == TYPE_ARRAY) + if (value_type_id(library_tuple[0]) == TYPE_STRING) { - value *paths_array = value_to_array(library_tuple[1]); - size_t paths_size = value_type_count(library_tuple[1]); - size_t path; - int found = 0; + const char *key_str = value_to_string(library_tuple[0]); - for (path = 0; path < paths_size; ++path) + if (host == 0) { - if (value_type_id(paths_array[iterator]) == TYPE_STRING) + /* If the loader is not the host, iterate through all dependencies and load them */ + if (value_type_id(library_tuple[1]) == TYPE_ARRAY) { - const char *library_path = value_to_string(paths_array[iterator]); + value *paths_array = value_to_array(library_tuple[1]); + size_t paths_size = value_type_count(library_tuple[1]); - if (library_path != NULL) + if (loader_impl_dependencies_load(impl, key_str, paths_array, paths_size) != 0) { - dynlink handle = dynlink_load_absolute(library_path, DYNLINK_FLAGS_BIND_LAZY | DYNLINK_FLAGS_BIND_GLOBAL); + log_write("metacall", LOG_LEVEL_ERROR, "Failed to load dependency '%s' from loader configuration '%s.json'", key_str, plugin_name(impl->p)); + return 1; + } + } + } + else + { + /* Otherwise try to find if the library is already loaded, and if not, load the process */ + if (loader_impl_dependencies_self_find(impl, key_str, dependencies_self) != 0) + { + log_write("metacall", LOG_LEVEL_ERROR, "Failed to load dependency '%s' from loader '%s' as a host", key_str, plugin_name(impl->p)); + vector_destroy(dependencies_self); + return 1; + } + } + } + } + } + + vector_destroy(dependencies_self); + } + + return 0; +} + +int loader_impl_link(plugin p, loader_impl impl) +{ + plugin_descriptor desc = plugin_desc(p); - if (handle != NULL) + /* On Linux and MacOS, if the symbols are exported, + the linker when loading the library automatically resolves the symbols + so there is no need for doing the link manually, in Windows meanwhile + we link the dependency with delay load linking. Before we execute anything, + we should relink all the symbols to the host. + */ +#if defined(WIN32) || defined(_WIN32) + if (loader_impl_get_option_host(impl) == 1) + { + /* Replace loader symbols by the dependency (aka the already loaded + library if the host is linked dynamically, or the executable if it is + linked statically) */ + detour_handle loader_handle; + void *position = NULL; + char name[DETOUR_SYMBOL_SIZE]; + void *addr = NULL; + + loader_handle = detour_load_handle(impl->d, desc->handle); + + if (loader_handle != NULL) + { + set_iterator it; + size_t iterator; + + while (detour_enumerate(impl->d, loader_handle, &position, name, &addr)) + { + /* Iterate through all library handles in the library map */ + it = set_iterator_begin(impl->library_map); + + for (iterator = 0; iterator < set_size(impl->library_map); ++iterator) + { + dynlink library_handle = set_iterator_value(it); + void *symbol = NULL; + + if (library_handle != NULL) + { + if (dynlink_symbol(library_handle, name, &symbol) == 0) + { + if (symbol != NULL) + { + if (detour_replace(impl->d, loader_handle, name, symbol, NULL) == 0) { - found = 1; + /* Symbol successfully replaced */ + break; } } } } - - if (!found) - { - const char *dependency = value_type_id(library_tuple[0]) == TYPE_STRING ? value_to_string(library_tuple[0]) : "unknown_library"; - log_write("metacall", LOG_LEVEL_ERROR, "Failed to load dependency '%s' from loader configuration '%s.json'", dependency, plugin_name(impl->p)); - return 1; - } + + it = set_iterator_next(it); } } + + detour_unload(impl->d, loader_handle); } } +#endif + + /* Store itself in the library map along with the dependencies */ + if (set_insert(impl->library_map, (set_key)desc->library_name, (set_value)desc->handle) != 0) + { + return 1; + } return 0; } +dynlink loader_impl_dependency(loader_impl impl, const char *library) +{ + dynlink library_handle = set_get(impl->library_map, (const set_key)library); + + return library_handle; +} + +detour_handle loader_impl_detour(loader_impl impl, const char *library, int (*load_cb)(detour, detour_handle)) +{ + detour_handle handle = set_get(impl->detour_map, (const set_key)library); + + if (handle == NULL) + { + dynlink library_handle = set_get(impl->library_map, (const set_key)library); + + if (library_handle == NULL) + { + return NULL; + } + + handle = detour_load_handle(impl->d, library_handle); + + if (handle == NULL) + { + return NULL; + } + + if (load_cb(impl->d, handle) != 0) + { + detour_unload(impl->d, handle); + return NULL; + } + + if (set_insert(impl->detour_map, (set_key)library, handle) != 0) + { + detour_unload(impl->d, handle); + return NULL; + } + } + + return handle; +} + configuration loader_impl_initialize_configuration(const loader_tag tag) { static const char configuration_key_suffix[] = "_loader"; @@ -1208,7 +1480,7 @@ void *loader_impl_get_handle(loader_impl impl, const char *name) return NULL; } -void loader_impl_set_options(loader_impl impl, void *options) +void loader_impl_set_options(loader_impl impl, value options) { if (impl != NULL && options != NULL) { @@ -1580,6 +1852,38 @@ int loader_impl_destroy_exec_path_map_cb_iterate(set s, set_key key, set_value v return 0; } +int loader_impl_destroy_detour_map_cb_iterate(set s, set_key key, set_value val, set_cb_iterate_args args) +{ + (void)s; + (void)key; + + if (val != NULL && args != NULL) + { + detour d = args; + detour_handle handle = val; + + detour_unload(d, handle); + } + + return 0; +} + +int loader_impl_destroy_dependencies_map_cb_iterate(set s, set_key key, set_value val, set_cb_iterate_args args) +{ + (void)s; + (void)key; + (void)args; + + if (val != NULL) + { + dynlink dependency = val; + + dynlink_unload(dependency); + } + + return 0; +} + void loader_impl_destroy_objects(loader_impl impl) { /* This iterates through all functions, classes objects and types, @@ -1637,6 +1941,24 @@ void loader_impl_destroy_deallocate(loader_impl impl) value_type_destroy(impl->options); } + /* Destroy detour map */ + set_iterate(impl->detour_map, &loader_impl_destroy_detour_map_cb_iterate, impl->d); + + set_destroy(impl->detour_map); + + /* Unload all the dependencies. + This must be done when the plugin dynlink handle (aka the loader) gets unloaded, + at this point it is not unloaded yet, because the plugin destructor is called before doing: + dynlink_unload(p->descriptor->handle); + As the destroy mechanism requires the loaders to be unloaded at the end after all the destroy methods of all + loaders have been called, this generates an ourobros that cannot be solved easily. In any case, + this method still should work because normally those handles are reference counted and we increment + the reference counter at the beginning, so they will be properly unloaded when the dynlink handle gets unloaded. + */ + set_iterate(impl->library_map, &loader_impl_destroy_dependencies_map_cb_iterate, NULL); + + set_destroy(impl->library_map); + free(impl); } @@ -1665,6 +1987,11 @@ void loader_impl_destroy(plugin p, loader_impl impl) impl->init = 1; } + + /* Remove the loader library from the library list */ + plugin_descriptor desc = plugin_desc(p); + + set_remove(impl->library_map, (set_key)desc->library_name); } else { diff --git a/source/loaders/c_loader/source/c_loader_impl.cpp b/source/loaders/c_loader/source/c_loader_impl.cpp index f9530b7ab..a4e57914c 100644 --- a/source/loaders/c_loader/source/c_loader_impl.cpp +++ b/source/loaders/c_loader/source/c_loader_impl.cpp @@ -315,7 +315,7 @@ typedef struct loader_impl_c_handle_dynlink_type : loader_impl_c_handle_base_typ { /* This function will try to check if the library exists before loading it, so we avoid error messages from dynlink when guessing the file path for relative load from file */ - dynlink_name_impl platform_name; + dynlink_path platform_name; dynlink_platform_name(library_name, platform_name); diff --git a/source/loaders/ext_loader/source/ext_loader_impl.cpp b/source/loaders/ext_loader/source/ext_loader_impl.cpp index c41db8f1b..ab4f182bd 100644 --- a/source/loaders/ext_loader/source/ext_loader_impl.cpp +++ b/source/loaders/ext_loader/source/ext_loader_impl.cpp @@ -142,7 +142,7 @@ dynlink ext_loader_impl_load_from_file_dynlink(const char *path, const char *lib { /* This function will try to check if the library exists before loading it, so we avoid error messages from dynlink when guessing the file path for relative load from file */ - dynlink_name_impl platform_name; + dynlink_path platform_name; dynlink_platform_name(library_name, platform_name); diff --git a/source/loaders/node_loader/CMakeLists.txt b/source/loaders/node_loader/CMakeLists.txt index e557fba41..e76ed66f5 100644 --- a/source/loaders/node_loader/CMakeLists.txt +++ b/source/loaders/node_loader/CMakeLists.txt @@ -22,6 +22,34 @@ if(NodeJS_LIBRARY_NAME_PATH AND WIN32) file(COPY "${NodeJS_LIBRARY_NAME_PATH}" DESTINATION ${PROJECT_OUTPUT_DIR}) endif() +# Runtime (pack NodeJS DLL in windows) +# TODO: https://cmake.org/cmake/help/latest/command/file.html#get-runtime-dependencies +# TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da +set(NodeJS_LIBRARY_DEVELOPMENT "${NodeJS_LIBRARY}") + +if(NodeJS_LIBRARY_NAME_PATH AND WIN32) + install(FILES + "${NodeJS_LIBRARY_NAME_PATH}" + DESTINATION ${INSTALL_LIB} + COMPONENT runtime + ) + + get_filename_component(NodeJS_LIBRARY_NAME "${NodeJS_LIBRARY_NAME_PATH}" NAME) + set(NodeJS_LIBRARY_DEVELOPMENT "${NodeJS_LIBRARY_NAME_PATH}") + set(NodeJS_LIBRARY_INSTALL "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB}/${NodeJS_LIBRARY_NAME}") +elseif(NodeJS_BUILD_FROM_SOURCE AND NOT WIN32) + install(FILES + "${NodeJS_LIBRARY}" + DESTINATION ${INSTALL_LIB} + COMPONENT runtime + ) + + get_filename_component(NodeJS_LIBRARY_NAME "${NodeJS_LIBRARY}" NAME) + set(NodeJS_LIBRARY_INSTALL "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB}/${NodeJS_LIBRARY_NAME}") +else() + set(NodeJS_LIBRARY_INSTALL "${NodeJS_LIBRARY}") +endif() + # # Plugin name and options # @@ -74,13 +102,6 @@ set(sources ${source_path}/node_loader_trampoline.cpp ) -if(WIN32 AND MSVC_VERSION GREATER_EQUAL 1200) - set(headers - ${headers} - ${include_path}/node_loader_win32_delay_load.h - ) -endif() - # Group source files set(header_group "Header Files (API)") set(source_group "Source Files") @@ -157,8 +178,9 @@ target_link_libraries(${target} PRIVATE ${META_PROJECT_NAME}::metacall # MetaCall library - # TODO: Replace this by /FORCE:UNRESOLVED on MSVC for later on resolving it ourselves? + # Delay load for MSVC $<$:${NodeJS_LIBRARY}> # NodeJS library + $<$:delayimp> PUBLIC ${DEFAULT_LIBRARIES} @@ -172,7 +194,6 @@ target_link_libraries(${target} target_compile_definitions(${target} PRIVATE - $<$:NODEJS_LIBRARY_NAME="${NodeJS_LIBRARY_NAME}"> $<$>:_LARGEFILE_SOURCE> $<$>:_FILE_OFFSET_BITS=64> $<$,$>:_DARWIN_USE_64_BIT_INODE=1> @@ -204,6 +225,7 @@ target_compile_options(${target} target_link_options(${target} PRIVATE $<$,$>:-Wl,-undefined,dynamic_lookup> + $<$:/DELAYLOAD:${NodeJS_LIBRARY_NAME}> PUBLIC ${DEFAULT_LINKER_OPTIONS} @@ -231,34 +253,6 @@ install(TARGETS ${target} ARCHIVE DESTINATION ${INSTALL_LIB} COMPONENT dev ) -set(NodeJS_LIBRARY_DEVELOPMENT "${NodeJS_LIBRARY}") - -# Runtime (pack NodeJS DLL in windows) -# TODO: https://cmake.org/cmake/help/latest/command/file.html#get-runtime-dependencies -# TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da -if(NodeJS_LIBRARY_NAME_PATH AND WIN32) - install(FILES - "${NodeJS_LIBRARY_NAME_PATH}" - DESTINATION ${INSTALL_LIB} - COMPONENT runtime - ) - - get_filename_component(NodeJS_LIBRARY_NAME "${NodeJS_LIBRARY_NAME_PATH}" NAME) - set(NodeJS_LIBRARY_DEVELOPMENT "${NodeJS_LIBRARY_NAME_PATH}") - set(NodeJS_LIBRARY_INSTALL "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB}/${NodeJS_LIBRARY_NAME}") -elseif(NodeJS_BUILD_FROM_SOURCE AND NOT WIN32) - install(FILES - "${NodeJS_LIBRARY}" - DESTINATION ${INSTALL_LIB} - COMPONENT runtime - ) - - get_filename_component(NodeJS_LIBRARY_NAME "${NodeJS_LIBRARY}" NAME) - set(NodeJS_LIBRARY_INSTALL "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB}/${NodeJS_LIBRARY_NAME}") -else() - set(NodeJS_LIBRARY_INSTALL "${NodeJS_LIBRARY}") -endif() - # # Configuration # diff --git a/source/loaders/node_loader/include/node_loader/node_loader_impl.h b/source/loaders/node_loader/include/node_loader/node_loader_impl.h index 094f3b24e..ee424c9b3 100644 --- a/source/loaders/node_loader/include/node_loader/node_loader_impl.h +++ b/source/loaders/node_loader/include/node_loader/node_loader_impl.h @@ -67,7 +67,7 @@ NODE_LOADER_NO_EXPORT void node_loader_impl_destroy_safe_impl(loader_impl_node n NODE_LOADER_NO_EXPORT void node_loader_impl_print_handles(loader_impl_node node_impl); -NODE_LOADER_NO_EXPORT int64_t node_loader_impl_user_async_handles_count(loader_impl_node node_impl); +NODE_LOADER_NO_EXPORT uint64_t node_loader_impl_user_async_handles_count(loader_impl_node node_impl); NODE_LOADER_NO_EXPORT napi_value node_loader_impl_register_bootstrap_startup(loader_impl_node node_impl, napi_env env); diff --git a/source/loaders/node_loader/include/node_loader/node_loader_win32_delay_load.h b/source/loaders/node_loader/include/node_loader/node_loader_win32_delay_load.h deleted file mode 100644 index 47d425cee..000000000 --- a/source/loaders/node_loader/include/node_loader/node_loader_win32_delay_load.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Loader Library by Parra Studios - * A plugin for loading nodejs code at run-time into a process. - * - * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia - * - * 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. - * - */ - -/* -- Headers -- */ - -#define WIN32_LEAN_AND_MEAN -#include - -#include -#include - -inline void *node_loader_hook_import_address_table(const char *module_name, const char *function_name, void *hook) -{ - LPVOID image_base = GetModuleHandle(module_name); - PIMAGE_DOS_HEADER dos_headers = (PIMAGE_DOS_HEADER)image_base; - - if (dos_headers->e_magic != IMAGE_DOS_SIGNATURE) - { - return NULL; - } - - PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD_PTR)image_base + dos_headers->e_lfanew); - - if (nt_headers->Signature != IMAGE_NT_SIGNATURE) - { - return NULL; - } - - IMAGE_DATA_DIRECTORY *imports_directory = &nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; - - if (imports_directory->Size == 0 || imports_directory->VirtualAddress == 0) - { - return NULL; - } - - PIMAGE_IMPORT_DESCRIPTOR import_descriptor = (PIMAGE_IMPORT_DESCRIPTOR)(imports_directory->VirtualAddress + (DWORD_PTR)image_base); - - for (; import_descriptor->FirstThunk != NULL; ++import_descriptor) - { - PIMAGE_THUNK_DATA original_first_thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)image_base + import_descriptor->OriginalFirstThunk); // Image thunk data names - PIMAGE_THUNK_DATA first_thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)image_base + import_descriptor->FirstThunk); // Image thunk data address - - for (; original_first_thunk->u1.AddressOfData != NULL; ++original_first_thunk, ++first_thunk) - { - if ((original_first_thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0) - { - PIMAGE_IMPORT_BY_NAME func = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)image_base + original_first_thunk->u1.AddressOfData); - - if (strcmp(func->Name, function_name) == 0) - { - LPVOID original_address = (LPVOID)(first_thunk->u1.Function); - LPVOID import_func_load_address = (LPVOID)(&first_thunk->u1.Function); - DWORD old_page_protect, unused_old_page_protect; - - VirtualProtect(import_func_load_address, sizeof(void *), PAGE_EXECUTE_READWRITE, &old_page_protect); - - memcpy(import_func_load_address, &hook, sizeof(hook)); - - VirtualProtect(import_func_load_address, sizeof(void *), old_page_protect, &unused_old_page_protect); - - return (void *)original_address; - } - } - } - } - - return NULL; -} diff --git a/source/loaders/node_loader/source/node_loader_impl.cpp b/source/loaders/node_loader/source/node_loader_impl.cpp index e15575fec..77e66b08a 100644 --- a/source/loaders/node_loader/source/node_loader_impl.cpp +++ b/source/loaders/node_loader/source/node_loader_impl.cpp @@ -49,7 +49,7 @@ extern char **environ; #include #if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1200) - #include + #include /* Required for the DelayLoad hook interposition, solves bug of NodeJS extensions requiring node.exe instead of node.dll*/ #include @@ -619,7 +619,7 @@ typedef struct node_loader_impl_startup_args_type } /* Get node impl pointer */ - ssize_t node_impl_ptr_length = snprintf(NULL, 0, "%p", (void *)node_impl); + ssize_t node_impl_ptr_length = snprintf(NULL, 0, "%" PRIxPTR, (uintptr_t)(node_impl)); if (node_impl_ptr_length <= 0) { @@ -636,10 +636,10 @@ typedef struct node_loader_impl_startup_args_type return 1; } - snprintf(node_impl_ptr_str, node_impl_ptr_str_size, "%p", (void *)node_impl); + snprintf(node_impl_ptr_str, node_impl_ptr_str_size, "%" PRIxPTR, (uintptr_t)(node_impl)); /* Get register pointer */ - ssize_t register_ptr_length = snprintf(NULL, 0, "%p", (void *)&node_loader_impl_register); + ssize_t register_ptr_length = snprintf(NULL, 0, "%" PRIxPTR, (uintptr_t)(&node_loader_impl_register)); if (register_ptr_length <= 0) { @@ -656,7 +656,7 @@ typedef struct node_loader_impl_startup_args_type return 1; } - snprintf(register_ptr_str, register_ptr_str_size, "%p", (void *)&node_loader_impl_register); + snprintf(register_ptr_str, register_ptr_str_size, "%" PRIxPTR, (uintptr_t)(&node_loader_impl_register)); return 0; } @@ -704,8 +704,8 @@ struct loader_impl_node_type /* TODO: This implementation won't work for multi-isolate environments. We should test it. */ std::thread::id js_thread_id; - int64_t base_active_handles; - std::atomic_int64_t extra_active_handles; + uint64_t base_active_handles; + std::atomic_uint64_t extra_active_handles; uv_prepare_t destroy_prepare; uv_check_t destroy_check; std::atomic_bool event_loop_empty; @@ -805,23 +805,6 @@ typedef struct loader_impl_napi_to_value_callback_closure_type } * loader_impl_napi_to_value_callback_closure; -class loader_impl_napi_constructor -{ -public: - loader_impl_napi_constructor() - { - if (metacall_link_register("napi_register_module_v1", (void (*)(void))(&node_loader_port_initialize)) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Node loader failed register the link hook"); - } - } - - ~loader_impl_napi_constructor() {} -}; - -/* Initializer of napi_register_module_v1 */ -static loader_impl_napi_constructor loader_impl_napi_ctor; - /* Type conversion */ static napi_value node_loader_impl_napi_to_value_callback(napi_env env, napi_callback_info info); @@ -891,7 +874,7 @@ static void node_loader_impl_thread_log(void *data); static void node_loader_impl_walk_async_handles_count(uv_handle_t *handle, void *arg); #endif -static int64_t node_loader_impl_async_handles_count(loader_impl_node node_impl); +static uint64_t node_loader_impl_async_handles_count(loader_impl_node node_impl); static void node_loader_impl_try_destroy(loader_impl_node node_impl); @@ -899,6 +882,7 @@ static void node_loader_impl_try_destroy(loader_impl_node node_impl); /* Required for the DelayLoad hook interposition, solves bug of NodeJS extensions requiring node.exe instead of node.dll */ static HMODULE node_loader_node_dll_handle = NULL; static HMODULE (*get_module_handle_a_ptr)(_In_opt_ LPCSTR) = NULL; /* TODO: Implement W version too? */ +static detour_handle node_module_handle_a_handle = NULL; #endif /* -- Methods -- */ @@ -935,11 +919,34 @@ static HMODULE (*get_module_handle_a_ptr)(_In_opt_ LPCSTR) = NULL; /* TODO: Impl void node_loader_impl_register_linked_bindings() { + /* + * For now napi_module_register won't be deprecated: https://github.com/nodejs/node/issues/56153 + * If this changes, we can investigate the alternative approach. + */ +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4996) +#elif defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#elif defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + /* Initialize Node Loader Trampoline */ node_loader_impl_register_module("node_loader_trampoline_module", node_loader_trampoline_initialize); /* Initialize Node Loader Port */ node_loader_impl_register_module("node_loader_port_module", node_loader_port_initialize); + +#if defined(_MSC_VER) + #pragma warning(pop) +#elif defined(__clang__) + #pragma clang diagnostic pop +#elif defined(__GNUC__) + #pragma GCC diagnostic pop +#endif } void node_loader_impl_exception(napi_env env, napi_status status) @@ -3690,8 +3697,43 @@ void *node_loader_impl_register(void *node_impl_ptr, void *env_ptr, void *functi /* On Windows, hook node extension loading mechanism in order to patch extensions linked to node.exe */ #if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1200) - node_loader_node_dll_handle = GetModuleHandle(NODEJS_LIBRARY_NAME); - get_module_handle_a_ptr = (HMODULE(*)(_In_opt_ LPCSTR))node_loader_hook_import_address_table("kernel32.dll", "GetModuleHandleA", &get_module_handle_a_hook); + { + /* As the library handle is correctly resolved here, either to executable, library of the executable, + or the loader dependency we can directly get the handle of this dependency */ + dynlink node_library = loader_impl_dependency(node_impl->impl, "node"); + + node_loader_node_dll_handle = static_cast(dynlink_get_impl(node_library)); + + if (node_loader_node_dll_handle == NULL) + { + napi_throw_error(env, nullptr, "Failed to initialize the hooking against node extensions load mechanism"); + return NULL; + } + + detour d = detour_create(metacall_detour()); + + node_module_handle_a_handle = detour_load_file(d, "kernel32.dll"); + + if (node_module_handle_a_handle == NULL) + { + napi_throw_type_error(env, nullptr, "Invalid creation of the detour handle for hooking node extension load mechanism"); + } + else + { + typedef HMODULE (*get_module_handle_a_type)(_In_opt_ LPCSTR); + + union + { + get_module_handle_a_type *trampoline; + void (**ptr)(void); + } cast = { &get_module_handle_a_ptr }; + + if (detour_replace(d, node_module_handle_a_handle, "GetModuleHandleA", (void (*)(void))(&get_module_handle_a_hook), cast.ptr) != 0) + { + napi_throw_type_error(env, nullptr, "Invalid replacement of GetModuleHandle for hooking node extension load mechanism"); + } + } + } #endif /* On host mode, register delayed paths */ @@ -3993,6 +4035,11 @@ loader_impl_data node_loader_impl_initialize(loader_impl impl, configuration con /* Result will never be defined properly */ node_impl->result = 0; + + if (metacall_link_register_loader(impl, "node", "napi_register_module_v1", (void (*)(void))(&node_loader_port_initialize)) != 0) + { + log_write("metacall", LOG_LEVEL_ERROR, "Node Loader failed to hook napi_register_module_v1"); + } } /* Register initialization */ @@ -4026,7 +4073,7 @@ napi_value node_loader_impl_register_bootstrap_startup(loader_impl_node node_imp argv[3] = node_loader_trampoline_initialize_object(env); /* Set the values */ - for (size_t iterator = 0; iterator < 4; ++iterator) + for (uint32_t iterator = 0; iterator < 4; ++iterator) { status = napi_set_element(env, v, iterator, argv[iterator]); node_loader_impl_exception(env, status); @@ -4326,7 +4373,7 @@ static void node_loader_impl_destroy_cb(loader_impl_node node_impl) node_loader_impl_print_handles(node_impl); #endif - if (node_impl->event_loop_empty.load() == false && node_loader_impl_user_async_handles_count(node_impl) <= 0) + if (node_impl->event_loop_empty.load() == false && node_loader_impl_user_async_handles_count(node_impl) == 0) { loader_impl_handle_safe_cast destroy_prepare_cast = { NULL }; loader_impl_handle_safe_cast destroy_check_cast = { NULL }; @@ -4379,7 +4426,7 @@ void node_loader_impl_destroy_safe(napi_env env, loader_impl_async_destroy_safe_ node_loader_impl_exception(env, status); /* Check if there are async handles, destroy if the queue is empty, otherwise request the destroy */ - if (node_loader_impl_user_async_handles_count(node_impl) <= 0 || node_impl->event_loop_empty.load() == true) + if (node_loader_impl_user_async_handles_count(node_impl) == 0 || node_impl->event_loop_empty.load() == true) { node_loader_impl_destroy_safe_impl(node_impl, env); destroy_safe->has_finished = true; @@ -4411,7 +4458,7 @@ static inline int uv__queue_empty(const struct node_loader_impl_uv__queue *q) #if (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) void node_loader_impl_walk_async_handles_count(uv_handle_t *handle, void *arg) { - int64_t *async_count = static_cast(arg); + uint64_t *async_count = static_cast(arg); if (uv_is_active(handle) && !uv_is_closing(handle)) { @@ -4427,11 +4474,11 @@ void node_loader_impl_walk_async_handles_count(uv_handle_t *handle, void *arg) } #endif -int64_t node_loader_impl_async_closing_handles_count(loader_impl_node node_impl) +uint64_t node_loader_impl_async_closing_handles_count(loader_impl_node node_impl) { #if defined(WIN32) || defined(_WIN32) - return (int64_t)(node_impl->thread_loop->pending_reqs_tail != NULL) + - (int64_t)(node_impl->thread_loop->endgame_handles != NULL); + return (uint64_t)(node_impl->thread_loop->pending_reqs_tail != NULL) + + (uint64_t)(node_impl->thread_loop->endgame_handles != NULL); #else union { @@ -4441,49 +4488,66 @@ int64_t node_loader_impl_async_closing_handles_count(loader_impl_node node_impl) uv__queue_cast.data = (void *)&node_impl->thread_loop->pending_queue; - return (int64_t)(!uv__queue_empty(uv__queue_cast.ptr)) + - (int64_t)(node_impl->thread_loop->closing_handles != NULL); + return (uint64_t)(!uv__queue_empty(uv__queue_cast.ptr)) + + (uint64_t)(node_impl->thread_loop->closing_handles != NULL); #endif } -int64_t node_loader_impl_async_handles_count(loader_impl_node node_impl) +uint64_t node_loader_impl_async_handles_count(loader_impl_node node_impl) { #if (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) - int64_t active_handles = 0; + uint64_t active_handles = 0; uv_walk(node_impl->thread_loop, node_loader_impl_walk_async_handles_count, (void *)&active_handles); return active_handles + - (int64_t)(node_impl->thread_loop->active_reqs.count > 0) + + (uint64_t)(node_impl->thread_loop->active_reqs.count > 0) + node_loader_impl_async_closing_handles_count(node_impl); #else - int64_t active_handles = (int64_t)node_impl->thread_loop->active_handles + - (int64_t)(node_impl->thread_loop->active_reqs.count > 0) + - node_loader_impl_async_closing_handles_count(node_impl); + uint64_t active_handles = (uint64_t)node_impl->thread_loop->active_handles + + (uint64_t)(node_impl->thread_loop->active_reqs.count > 0) + + node_loader_impl_async_closing_handles_count(node_impl); return active_handles; #endif } -int64_t node_loader_impl_user_async_handles_count(loader_impl_node node_impl) +uint64_t node_loader_impl_user_async_handles_count(loader_impl_node node_impl) { - int64_t active_handles = node_loader_impl_async_handles_count(node_impl); - int64_t extra_active_handles = node_impl->extra_active_handles.load(); + uint64_t active_handles = node_loader_impl_async_handles_count(node_impl); + uint64_t extra_active_handles = node_impl->extra_active_handles.load(); + uint64_t base_active_handles = node_impl->base_active_handles; /* TODO: Uncomment for debugging handles */ /* #if (!defined(NDEBUG) || defined(DEBUG) || defined(_DEBUG) || defined(__DEBUG) || defined(__DEBUG__)) - int64_t closing = node_loader_impl_async_closing_handles_count(node_impl); + uint64_t closing = node_loader_impl_async_closing_handles_count(node_impl); printf("[active_handles] - [base_active_handles] - [extra_active_handles] + [active_reqs] + [closing]\n"); - printf(" %" PRId64 " - %" PRId64 " - %" PRId64 " + %" PRId64 " [> 0] + %" PRId64 "\n", - (int64_t)node_impl->thread_loop->active_handles, - node_impl->base_active_handles, + printf(" %" PRIu64 " - %" PRIu64 " - %" PRIu64 " + %" PRIu64 " [> 0] + %" PRIu64 "\n", + (uint64_t)node_impl->thread_loop->active_handles, + base_active_handles, extra_active_handles, - (int64_t)node_impl->thread_loop->active_reqs.count, + (uint64_t)node_impl->thread_loop->active_reqs.count, closing); #endif */ - return active_handles - node_impl->base_active_handles - extra_active_handles; + /* Check for overflow */ + uint64_t total_base_handles = base_active_handles + extra_active_handles; + + if (total_base_handles < base_active_handles) + { + /* Overflow occurred */ + return UINT64_MAX; + } + + /* Check for underflow */ + if (active_handles < total_base_handles) + { + /* Underflow occurred */ + return 0; + } + + return active_handles - total_base_handles; } void node_loader_impl_print_handles(loader_impl_node node_impl) @@ -4492,8 +4556,8 @@ void node_loader_impl_print_handles(loader_impl_node node_impl) /* TODO: Uncomment for debugging handles */ /* - printf("Number of active handles: %" PRId64 "\n", node_loader_impl_async_handles_count(node_impl)); - printf("Number of user active handles: %" PRId64 "\n", node_loader_impl_user_async_handles_count(node_impl)); + printf("Number of active handles: %" PRIu64 "\n", node_loader_impl_async_handles_count(node_impl)); + printf("Number of user active handles: %" PRIu64 "\n", node_loader_impl_user_async_handles_count(node_impl)); uv_print_active_handles(node_impl->thread_loop, stdout); fflush(stdout); */ @@ -4628,6 +4692,20 @@ int node_loader_impl_destroy(loader_impl impl) uv_thread_join(&node_impl->thread_log_id); #endif + /* On Windows, destroy the node extension hooking mechanism */ +#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1200) + { + if (node_module_handle_a_handle != NULL) + { + detour d = detour_create(metacall_detour()); + + detour_unload(d, node_module_handle_a_handle); + + node_module_handle_a_handle = NULL; + } + } +#endif + /* Print NodeJS execution result */ log_write("metacall", LOG_LEVEL_DEBUG, "NodeJS execution return status %d", node_impl->result); diff --git a/source/loaders/node_loader/source/node_loader_port.cpp b/source/loaders/node_loader/source/node_loader_port.cpp index f96f1f295..82eaafbff 100644 --- a/source/loaders/node_loader/source/node_loader_port.cpp +++ b/source/loaders/node_loader/source/node_loader_port.cpp @@ -1114,7 +1114,7 @@ napi_value node_loader_port_initialize(napi_env env, napi_value exports) node_loader_port_exports(env, exports); /* Unregister NAPI Hook */ - if (metacall_link_unregister("napi_register_module_v1") != 0) + if (metacall_link_unregister(node_loader_tag, "node", "napi_register_module_v1") != 0) { // TODO: Handle error } diff --git a/source/loaders/node_loader/source/node_loader_trampoline.cpp b/source/loaders/node_loader/source/node_loader_trampoline.cpp index 9083223a1..5d5aebbc8 100644 --- a/source/loaders/node_loader/source/node_loader_trampoline.cpp +++ b/source/loaders/node_loader/source/node_loader_trampoline.cpp @@ -9,7 +9,8 @@ #include #include -#include /* TODO: Improve this trick */ +#include +#include /* TODO: Improve this trick */ #define NODE_LOADER_TRAMPOLINE_DECLARE_NAPI_METHOD(name, func) \ { \ @@ -45,7 +46,7 @@ union loader_impl_trampoline_cast */ static void node_loader_trampoline_parse_pointer(napi_env env, napi_value v, void **ptr) { - const size_t ptr_str_size = (sizeof(void *) * 2) + 1; + const size_t ptr_str_size = (sizeof(uintptr_t) * 2) + 1; size_t ptr_str_size_copied = 0; char ptr_str[ptr_str_size]; napi_status status = napi_get_value_string_utf8(env, v, ptr_str, ptr_str_size, &ptr_str_size_copied); @@ -53,7 +54,9 @@ static void node_loader_trampoline_parse_pointer(napi_env env, napi_value v, voi node_loader_impl_exception(env, status); /* Convert the string to pointer type */ - sscanf(ptr_str, "%p", ptr); + uintptr_t uint_ptr; + sscanf(ptr_str, "%" SCNxPTR, &uint_ptr); + *ptr = (void *)uint_ptr; } napi_value node_loader_trampoline_register(napi_env env, napi_callback_info info) @@ -394,12 +397,17 @@ napi_value node_loader_trampoline_active_handles(napi_env env, napi_callback_inf return nullptr; } - int64_t active_handles = node_loader_impl_user_async_handles_count(node_impl_cast.data); + uint64_t active_handles = node_loader_impl_user_async_handles_count(node_impl_cast.data); /* Create the integer return value */ napi_value result; - status = napi_create_int64(env, active_handles, &result); + if (active_handles > (uint64_t)INT64_MAX) + { + active_handles = (uint64_t)INT64_MAX; + } + + status = napi_create_int64(env, (int64_t)active_handles, &result); node_loader_impl_exception(env, status); diff --git a/source/loaders/py_loader/source/py_loader_dict.c b/source/loaders/py_loader/source/py_loader_dict.c index 2982a4367..48c1bdee6 100644 --- a/source/loaders/py_loader/source/py_loader_dict.c +++ b/source/loaders/py_loader/source/py_loader_dict.c @@ -26,10 +26,32 @@ #include #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13 + /* Disable warnings from Python */ + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wredundant-decls" + #pragma clang diagnostic ignored "-Wstrict-aliasing" + #pragma clang diagnostic ignored "-Wunused-parameter" + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #elif defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wredundant-decls" + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + #pragma GCC diagnostic ignored "-Wunused-parameter" + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif + #ifndef Py_BUILD_CORE #define Py_BUILD_CORE #endif #include + + /* Disable warnings from Python */ + #if defined(__clang__) + #pragma clang diagnostic pop + #elif defined(__GNUC__) + #pragma GCC diagnostic pop + #endif #endif struct py_loader_impl_dict_obj diff --git a/source/loaders/py_loader/source/py_loader_impl.c b/source/loaders/py_loader/source/py_loader_impl.c index 79d655d01..32fedc692 100644 --- a/source/loaders/py_loader/source/py_loader_impl.c +++ b/source/loaders/py_loader/source/py_loader_impl.c @@ -44,8 +44,6 @@ #include #include -#include - #define PY_LOADER_IMPL_FUNCTION_TYPE_INVOKE_FUNC "__py_loader_impl_function_type_invoke__" #define PY_LOADER_IMPL_FINALIZER_FUNC "__py_loader_impl_finalizer__" diff --git a/source/loaders/py_loader/source/py_loader_threading.cpp b/source/loaders/py_loader/source/py_loader_threading.cpp index c49add1c3..5aa5173a9 100644 --- a/source/loaders/py_loader/source/py_loader_threading.cpp +++ b/source/loaders/py_loader/source/py_loader_threading.cpp @@ -24,8 +24,6 @@ #include -#include - struct py_thread_state { uint64_t ref_count; diff --git a/source/loaders/rb_loader/source/rb_loader_impl.c b/source/loaders/rb_loader/source/rb_loader_impl.c index ea3f817ae..3451dec8f 100644 --- a/source/loaders/rb_loader/source/rb_loader_impl.c +++ b/source/loaders/rb_loader/source/rb_loader_impl.c @@ -42,6 +42,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wredundant-decls" #pragma GCC diagnostic ignored "-Wpedantic" + #pragma GCC diagnostic ignored "-Wunused-parameter" #endif #include diff --git a/source/log/source/log_policy_format_text.c b/source/log/source/log_policy_format_text.c index 1deea2c22..7f30cae36 100644 --- a/source/log/source/log_policy_format_text.c +++ b/source/log/source/log_policy_format_text.c @@ -20,8 +20,8 @@ /* -- Definitions -- */ -#define LOG_POLICY_FORMAT_TEXT_STR_DEBUG "[%.19s] #%" PRIuS " [ %" PRIuS " | %s | %s ] @%s : " -#define LOG_POLICY_FORMAT_TEXT_STR_RELEASE "[%.19s] #%" PRIuS " @%s : " +#define LOG_POLICY_FORMAT_TEXT_STR_DEBUG "[%.19s] #%" PRIu64 " [ %" PRIuS " | %s | %s ] @%s : " +#define LOG_POLICY_FORMAT_TEXT_STR_RELEASE "[%.19s] #%" PRIu64 " @%s : " #define LOG_POLICY_FORMAT_TEXT_STR_PRETTY "\x1b[32m%s\x1b[0m: " /* -- Macros -- */ diff --git a/source/metacall/CMakeLists.txt b/source/metacall/CMakeLists.txt index 7aefaabd1..25f45878e 100644 --- a/source/metacall/CMakeLists.txt +++ b/source/metacall/CMakeLists.txt @@ -202,6 +202,9 @@ target_link_libraries(${target} $<$:${CMAKE_DL_LIBS}> # Native dynamic load library + # Fix issues with atomics in armv6 and armv7 + $<$:-latomic> + INTERFACE ) diff --git a/source/metacall/include/metacall/metacall_fork.h b/source/metacall/include/metacall/metacall_fork.h index fd9915fce..53eb2478e 100644 --- a/source/metacall/include/metacall/metacall_fork.h +++ b/source/metacall/include/metacall/metacall_fork.h @@ -88,11 +88,8 @@ METACALL_API void metacall_fork(metacall_pre_fork_callback_ptr pre_callback, met /** * @brief * Unregister fork detours and destroy shared memory -* -* @return -* Zero if success, different from zero otherwise */ -METACALL_API int metacall_fork_destroy(void); +METACALL_API void metacall_fork_destroy(void); #ifdef __cplusplus } diff --git a/source/metacall/include/metacall/metacall_link.h b/source/metacall/include/metacall/metacall_link.h index fc4f3a2c4..4e023d090 100644 --- a/source/metacall/include/metacall/metacall_link.h +++ b/source/metacall/include/metacall/metacall_link.h @@ -50,6 +50,12 @@ METACALL_API int metacall_link_initialize(void); * Function interposition is required in order to hook into runtimes * and dynamically interpose our functions. * +* @param[in] tag +* Name of the loader which the @library belongs to +* +* @param[in] library +* Name of the library that is going to be hooked +* * @param[in] symbol * Name of the function to be interposed * @@ -59,28 +65,58 @@ METACALL_API int metacall_link_initialize(void); * @return * Zero if success, different from zero otherwise */ -METACALL_API int metacall_link_register(const char *symbol, void (*fn)(void)); +METACALL_API int metacall_link_register(const char *tag, const char *library, const char *symbol, void (*fn)(void)); /** * @brief -* Remove the hook previously registered +* Register a function pointer in order to allow function +* interposition when loading a library, if you register a +* function @symbol called 'foo', when you try to dlsym (or the equivalent +* on every platform), you will get the pointer to @fn, even if +* the symbol does not exist in the library, it will work. +* Function interposition is required in order to hook into runtimes +* and dynamically interpose our functions. +* +* @param[in] loader +* Pointer to the loader which the @library belongs to +* +* @param[in] library +* Name of the library that is going to be hooked * * @param[in] symbol -* Name of the function to be removed +* Name of the function to be interposed +* +* @param[in] fn +* Function pointer that will be returned by dlsym (or equivalent) when accessing to @symbol * * @return * Zero if success, different from zero otherwise */ -METACALL_API int metacall_link_unregister(const char *symbol); +METACALL_API int metacall_link_register_loader(void *loader, const char *library, const char *symbol, void (*fn)(void)); /** * @brief -* Unregister link detours and destroy shared memory +* Remove the hook previously registered +* +* @param[in] tag +* Name of the loader which the @library belongs to +* +* @param[in] library +* Name of the library that is going to be hooked +* +* @param[in] symbol +* Name of the function to be interposed * * @return * Zero if success, different from zero otherwise */ -METACALL_API int metacall_link_destroy(void); +METACALL_API int metacall_link_unregister(const char *tag, const char *library, const char *symbol); + +/** +* @brief +* Unregister link detours and destroy shared memory +*/ +METACALL_API void metacall_link_destroy(void); #ifdef __cplusplus } diff --git a/source/metacall/source/metacall.c b/source/metacall/source/metacall.c index dec8182d2..fcba2931a 100644 --- a/source/metacall/source/metacall.c +++ b/source/metacall/source/metacall.c @@ -47,7 +47,7 @@ #define METACALL_ARGS_SIZE 0x10 #define METACALL_SERIAL "rapid_json" -#define METACALL_DETOUR "funchook" +#define METACALL_DETOUR "plthook" /* -- Type Definitions -- */ @@ -199,19 +199,13 @@ int metacall_plugin_extension_load(void) void metacall_detour_destructor(void) { /* Destroy link */ - if (metacall_link_destroy() != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid MetaCall link destruction"); - } + metacall_link_destroy(); /* Destroy fork */ #ifdef METACALL_FORK_SAFE if (metacall_config_flags & METACALL_FLAGS_FORK_SAFE) { - if (metacall_fork_destroy() != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid MetaCall fork destruction"); - } + metacall_fork_destroy(); } #endif /* METACALL_FORK_SAFE */ @@ -262,12 +256,6 @@ int metacall_initialize(void) return 1; } - /* Initialize link */ - if (metacall_link_initialize() != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "Invalid MetaCall link initialization"); - } - #ifdef METACALL_FORK_SAFE if (metacall_config_flags & METACALL_FLAGS_FORK_SAFE) { @@ -322,6 +310,7 @@ int metacall_initialize(void) } } + /* Initialize loader subsystem */ if (loader_initialize() != 0) { configuration_destroy(); @@ -329,6 +318,12 @@ int metacall_initialize(void) return 1; } + /* Initialize link */ + if (metacall_link_initialize() != 0) + { + log_write("metacall", LOG_LEVEL_ERROR, "Invalid MetaCall link initialization"); + } + /* Load core plugins */ if (metacall_plugin_extension_load() != 0) { @@ -351,26 +346,12 @@ int metacall_initialize_ex(struct metacall_initialize_configuration_type initial while (!(initialize_config[index].tag == NULL && initialize_config[index].options == NULL)) { - loader_impl impl = loader_get_impl(initialize_config[index].tag); - - if (impl == NULL) + if (loader_set_options(initialize_config[index].tag, initialize_config[index].options) != 0) { - log_write("metacall", LOG_LEVEL_ERROR, "MetaCall failed to find '%s_loader'", initialize_config[index].tag); + log_write("metacall", LOG_LEVEL_ERROR, "MetaCall failed to set options of '%s_loader'", initialize_config[index].tag); return 1; } - loader_set_options(initialize_config[index].tag, initialize_config[index].options); - - /* If we are initializing a loader as a host, we must initialize it */ - if (loader_get_option_host(initialize_config[index].tag)) - { - if (loader_initialize_host(initialize_config[index].tag) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "MetaCall failed to initialize '%s_loader' as host", initialize_config[index].tag); - return 1; - } - } - ++index; } diff --git a/source/metacall/source/metacall_fork.c b/source/metacall/source/metacall_fork.c index 422c00a0e..0c626a96d 100644 --- a/source/metacall/source/metacall_fork.c +++ b/source/metacall/source/metacall_fork.c @@ -29,6 +29,8 @@ #include +/* -- Methods -- */ + #if defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) @@ -43,10 +45,6 @@ #endif #include -/* -- Definitions -- */ - - #define metacall_fork_pid _getpid - /* -- Type Definitions -- */ typedef long NTSTATUS; @@ -89,8 +87,6 @@ typedef NTSTATUS(NTAPI *RtlCloneUserProcessPtr)(ULONG ProcessFlags, /* -- Methods -- */ -void (*metacall_fork_func(void))(void); - NTSTATUS NTAPI metacall_fork_hook(ULONG ProcessFlags, PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, @@ -104,8 +100,6 @@ NTSTATUS NTAPI metacall_fork_hook(ULONG ProcessFlags, /* -- Methods -- */ -void (*metacall_fork_func(void))(void); - pid_t metacall_fork_hook(void); #else @@ -125,21 +119,14 @@ static metacall_post_fork_callback_ptr metacall_post_fork_callback = NULL; defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) -void (*metacall_fork_func(void))(void) -{ - HMODULE module; - RtlCloneUserProcessPtr clone_ptr; +typedef RtlCloneUserProcessPtr metacall_fork_trampoline_type; - module = GetModuleHandle("ntdll.dll"); +static const char metacall_fork_func_name[] = "RtlCloneUserProcess"; +static metacall_fork_trampoline_type metacall_fork_trampoline = NULL; - if (!module) - { - return NULL; - } - - clone_ptr = (RtlCloneUserProcessPtr)GetProcAddress(module, "RtlCloneUserProcess"); - - return (void (*)(void))clone_ptr; +static detour_handle metacall_fork_handle(detour d) +{ + return detour_load_file(d, "ntdll.dll"); } NTSTATUS NTAPI metacall_fork_hook(ULONG ProcessFlags, @@ -148,8 +135,6 @@ NTSTATUS NTAPI metacall_fork_hook(ULONG ProcessFlags, HANDLE DebugPort, PRTL_USER_PROCESS_INFORMATION ProcessInformation) { - RtlCloneUserProcessPtr metacall_fork_trampoline = (RtlCloneUserProcessPtr)detour_trampoline(detour_fork_handle); - metacall_pre_fork_callback_ptr pre_callback = metacall_pre_fork_callback; metacall_post_fork_callback_ptr post_callback = metacall_post_fork_callback; @@ -213,15 +198,18 @@ NTSTATUS NTAPI metacall_fork_hook(ULONG ProcessFlags, defined(__CYGWIN__) || defined(__CYGWIN32__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) -void (*metacall_fork_func(void))(void) +typedef pid_t (*metacall_fork_trampoline_type)(void); + +static const char metacall_fork_func_name[] = "fork"; +static metacall_fork_trampoline_type metacall_fork_trampoline = NULL; + +static detour_handle metacall_fork_handle(detour d) { - return (void (*)(void))(&fork); + return detour_load_file(d, NULL); } pid_t metacall_fork_hook(void) { - pid_t (*metacall_fork_trampoline)(void) = (pid_t(*)(void))detour_trampoline(detour_fork_handle); - metacall_pre_fork_callback_ptr pre_callback = metacall_pre_fork_callback; metacall_post_fork_callback_ptr post_callback = metacall_post_fork_callback; @@ -285,7 +273,14 @@ int metacall_fork_initialize(void) if (detour_fork_handle == NULL) { - detour_fork_handle = detour_install(d, (void (*)(void))metacall_fork_func(), (void (*)(void))(&metacall_fork_hook)); + /* Casting for getting the original function */ + union + { + metacall_fork_trampoline_type *trampoline; + void (**ptr)(void); + } cast = { &metacall_fork_trampoline }; + + detour_fork_handle = metacall_fork_handle(d); if (detour_fork_handle == NULL) { @@ -295,6 +290,15 @@ int metacall_fork_initialize(void) return 1; } + + if (detour_replace(d, detour_fork_handle, metacall_fork_func_name, (void (*)(void))(&metacall_fork_hook), cast.ptr) != 0) + { + log_write("metacall", LOG_LEVEL_ERROR, "MetaCall invalid detour fork replacement"); + + metacall_link_destroy(); + + return 1; + } } return 0; @@ -306,26 +310,19 @@ void metacall_fork(metacall_pre_fork_callback_ptr pre_callback, metacall_post_fo metacall_post_fork_callback = post_callback; } -int metacall_fork_destroy(void) +void metacall_fork_destroy(void) { - int result = 0; - if (detour_fork_handle != NULL) { detour d = detour_create(metacall_detour()); - if (detour_uninstall(d, detour_fork_handle) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "MetaCall invalid detour fork uninstall"); + /* TODO: Restore the hook? We need support for this on the detour API */ - result = 1; - } + detour_unload(d, detour_fork_handle); detour_fork_handle = NULL; } metacall_pre_fork_callback = NULL; metacall_post_fork_callback = NULL; - - return result; } diff --git a/source/metacall/source/metacall_link.c b/source/metacall/source/metacall_link.c index 3526c6b18..cc261644e 100644 --- a/source/metacall/source/metacall_link.c +++ b/source/metacall/source/metacall_link.c @@ -33,11 +33,12 @@ #include +#include + #include /* -- Private Variables -- */ -static detour_handle detour_link_handle = NULL; static set metacall_link_table = NULL; static threading_mutex_type link_mutex = THREADING_MUTEX_INITIALIZE; @@ -47,23 +48,22 @@ static threading_mutex_type link_mutex = THREADING_MUTEX_INITIALIZE; #include -void (*metacall_link_func(void))(void) +typedef FARPROC (*metacall_link_trampoline_type)(HMODULE, LPCSTR); + +static const char metacall_link_func_name[] = "GetProcAddress"; +static metacall_link_trampoline_type metacall_link_trampoline = NULL; + +static metacall_link_trampoline_type metacall_link_func(void) { - return (void (*)(void))(&GetProcAddress); + return &GetProcAddress; } FARPROC metacall_link_hook(HMODULE handle, LPCSTR symbol) { - typedef FARPROC (*metacall_link_func_ptr)(HMODULE, LPCSTR); - - metacall_link_func_ptr metacall_link_trampoline; - void *ptr; threading_mutex_lock(&link_mutex); - metacall_link_trampoline = (metacall_link_func_ptr)detour_trampoline(detour_link_handle); - /* Intercept if any */ ptr = set_get(metacall_link_table, (set_key)symbol); @@ -88,23 +88,22 @@ FARPROC metacall_link_hook(HMODULE handle, LPCSTR symbol) #include -void (*metacall_link_func(void))(void) +typedef void *(*metacall_link_trampoline_type)(void *, const char *); + +static const char metacall_link_func_name[] = "dlsym"; +static metacall_link_trampoline_type metacall_link_trampoline = NULL; + +static metacall_link_trampoline_type metacall_link_func(void) { - return (void (*)(void))(&dlsym); + return &dlsym; } void *metacall_link_hook(void *handle, const char *symbol) { - typedef void *(*metacall_link_func_ptr)(void *, const char *); - - metacall_link_func_ptr metacall_link_trampoline; - void *ptr; threading_mutex_lock(&link_mutex); - metacall_link_trampoline = (metacall_link_func_ptr)detour_trampoline(detour_link_handle); - /* Intercept function if any */ ptr = set_get(metacall_link_table, (set_key)symbol); @@ -129,8 +128,6 @@ void *metacall_link_hook(void *handle, const char *symbol) int metacall_link_initialize(void) { - detour d = detour_create(metacall_detour()); - if (threading_mutex_initialize(&link_mutex) != 0) { log_write("metacall", LOG_LEVEL_ERROR, "MetaCall invalid link mutex initialization"); @@ -138,18 +135,13 @@ int metacall_link_initialize(void) return 1; } - if (detour_link_handle == NULL) - { - detour_link_handle = detour_install(d, (void (*)(void))metacall_link_func(), (void (*)(void))(&metacall_link_hook)); + /* Initialize the default detour for the loaders */ + loader_detour(detour_create(metacall_detour())); - if (detour_link_handle == NULL) - { - log_write("metacall", LOG_LEVEL_ERROR, "MetaCall invalid detour link installation"); - - metacall_link_destroy(); - - return 1; - } + if (metacall_link_trampoline == NULL) + { + /* Store the original symbol link function */ + metacall_link_trampoline = metacall_link_func(); } if (metacall_link_table == NULL) @@ -169,7 +161,14 @@ int metacall_link_initialize(void) return 0; } -int metacall_link_register(const char *symbol, void (*fn)(void)) +static int metacall_link_register_load_cb(detour d, detour_handle handle) +{ + void (*addr)(void) = NULL; + + return detour_replace(d, handle, metacall_link_func_name, (void (*)(void))(&metacall_link_hook), &addr); +} + +int metacall_link_register(const char *tag, const char *library, const char *symbol, void (*fn)(void)) { void *ptr; @@ -178,40 +177,57 @@ int metacall_link_register(const char *symbol, void (*fn)(void)) return 1; } + if (loader_hook(tag, library, metacall_link_register_load_cb) == NULL) + { + return 1; + } + dynlink_symbol_uncast(fn, ptr); return set_insert(metacall_link_table, (set_key)symbol, ptr); } -int metacall_link_unregister(const char *symbol) +int metacall_link_register_loader(void *loader, const char *library, const char *symbol, void (*fn)(void)) { + void *ptr; + if (metacall_link_table == NULL) { return 1; } - return (set_remove(metacall_link_table, (set_key)symbol) == NULL); + if (loader_hook_impl(loader, library, metacall_link_register_load_cb) == NULL) + { + return 1; + } + + dynlink_symbol_uncast(fn, ptr); + + return set_insert(metacall_link_table, (set_key)symbol, ptr); } -int metacall_link_destroy(void) +int metacall_link_unregister(const char *tag, const char *library, const char *symbol) { - int result = 0; - - threading_mutex_lock(&link_mutex); + if (metacall_link_table == NULL) + { + return 1; + } - if (detour_link_handle != NULL) + if (set_get(metacall_link_table, (set_key)symbol) == NULL) { - detour d = detour_create(metacall_detour()); + return 0; + } - if (detour_uninstall(d, detour_link_handle) != 0) - { - log_write("metacall", LOG_LEVEL_ERROR, "MetaCall invalid detour fork uninstall"); + /* TODO: Restore the hook? We need support for this on the detour API */ + (void)tag; + (void)library; - result = 1; - } + return (set_remove(metacall_link_table, (set_key)symbol) == NULL); +} - detour_link_handle = NULL; - } +void metacall_link_destroy(void) +{ + threading_mutex_lock(&link_mutex); if (metacall_link_table != NULL) { @@ -223,6 +239,4 @@ int metacall_link_destroy(void) threading_mutex_unlock(&link_mutex); threading_mutex_destroy(&link_mutex); - - return result; } diff --git a/source/plugin/include/plugin/plugin_impl.h b/source/plugin/include/plugin/plugin_impl.h index c74706197..bc8b51ecf 100644 --- a/source/plugin/include/plugin/plugin_impl.h +++ b/source/plugin/include/plugin/plugin_impl.h @@ -59,7 +59,7 @@ PLUGIN_API void *plugin_iface(plugin p); PLUGIN_API void *plugin_impl(plugin p); -PLUGIN_API void plugin_destroy_delayed(plugin p); +PLUGIN_API void plugin_destructor(plugin p); PLUGIN_API void plugin_destroy(plugin p); diff --git a/source/plugin/source/plugin_impl.c b/source/plugin/source/plugin_impl.c index 1de83e55f..5cb9e6f2c 100644 --- a/source/plugin/source/plugin_impl.c +++ b/source/plugin/source/plugin_impl.c @@ -101,7 +101,7 @@ void *plugin_impl(plugin p) return p->impl; } -void plugin_destroy_delayed(plugin p) +void plugin_destructor(plugin p) { if (p != NULL) { diff --git a/source/plugin/source/plugin_manager.c b/source/plugin/source/plugin_manager.c index 94e6cc5d3..8f7f615a0 100644 --- a/source/plugin/source/plugin_manager.c +++ b/source/plugin/source/plugin_manager.c @@ -105,13 +105,13 @@ int plugin_manager_initialize(plugin_manager manager, const char *name, const ch /* Initialize the library path */ if (manager->library_path == NULL) { - const char name[] = "metacall" + const char library_name[] = "metacall" #if (!defined(NDEBUG) || defined(DEBUG) || defined(_DEBUG) || defined(__DEBUG) || defined(__DEBUG__)) - "d" + "d" #endif ; - dynlink_library_path_str path; + dynlink_path path; size_t length = 0; /* The order of precedence is: @@ -119,7 +119,7 @@ int plugin_manager_initialize(plugin_manager manager, const char *name, const ch * 2) Dynamic link library path of the host library * 3) Default compile time path */ - if (dynlink_library_path(name, path, &length) == 0) + if (dynlink_library_path(library_name, path, &length) == 0) { default_library_path = path; } diff --git a/source/plugins/backtrace_plugin/CMakeLists.txt b/source/plugins/backtrace_plugin/CMakeLists.txt index ba955b7d8..441fe1b40 100644 --- a/source/plugins/backtrace_plugin/CMakeLists.txt +++ b/source/plugins/backtrace_plugin/CMakeLists.txt @@ -12,7 +12,7 @@ if(NOT OPTION_BUILD_GUIX) FetchContent_Declare(BackwardCpp GIT_REPOSITORY https://github.com/bombela/backward-cpp - GIT_TAG f30744bcf726ea3735df7ecf9e9de9ddac540283 + GIT_TAG 94718085efa256fb25a311a46b5948ee0d95890a ) FetchContent_MakeAvailable(BackwardCpp) @@ -23,7 +23,7 @@ if(NOT OPTION_BUILD_GUIX) ) if(NOT BackwardCpp_POPULATED) - FetchContent_Populate(backward-cpp) + FetchContent_Populate(BackwardCpp) endif() endif() @@ -31,18 +31,6 @@ if(NOT BackwardCpp_POPULATED OR NOT BackwardCpp_SOURCE) message(STATUS "BackwardCpp could not be installed, trying to find it on the system") endif() -find_package(Backward - CONFIG - PATHS ${BackwardCpp_SOURCE} -) - -if(NOT BACKWARD_FOUND) - message(WARNING "BackwardCpp could not be found, skipping backtrace plugin compilation") - return() -endif() - -include(${BackwardCpp_SOURCE}/BackwardConfig.cmake) - # # Plugin name and options # @@ -159,8 +147,6 @@ target_include_directories(${target} $ # MetaCall includes - ${BACKWARD_INCLUDE_DIR} # Backward-cpp includes - PUBLIC ${DEFAULT_INCLUDE_DIRECTORIES} @@ -178,11 +164,11 @@ target_link_libraries(${target} PRIVATE ${META_PROJECT_NAME}::metacall # MetaCall library + Backward::Interface # Backward-cpp library + PUBLIC ${DEFAULT_LIBRARIES} - Backward::Backward # Backward-cpp library - INTERFACE ) diff --git a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp index 884342633..48bd7a715 100644 --- a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp +++ b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp @@ -378,7 +378,10 @@ void *sandbox_signals(size_t argc, void *args[], void *data) SCMP_SYS(sigsuspend), SCMP_SYS(sigreturn), SCMP_SYS(rt_sigaction), - SCMP_SYS(rt_sigprocmask), + /* TODO: For some reason this makes the metacall-sandbox-plugin-test fail, + disabled it for now, we should review it + */ + /* SCMP_SYS(rt_sigprocmask), */ SCMP_SYS(rt_sigpending), SCMP_SYS(rt_sigsuspend), SCMP_SYS(rt_sigreturn), diff --git a/source/portability/include/portability/portability_library_path.h b/source/portability/include/portability/portability_library_path.h index 5e266a5a3..5daee5b8d 100644 --- a/source/portability/include/portability/portability_library_path.h +++ b/source/portability/include/portability/portability_library_path.h @@ -27,13 +27,15 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* -- Type Definitions -- */ typedef char portability_library_path_str[PORTABILITY_PATH_SIZE]; -#ifdef __cplusplus -extern "C" { -#endif +typedef int (*portability_library_path_list_cb)(const char *library, void *data); /* -- Methods -- */ @@ -53,7 +55,22 @@ extern "C" { * @return * Returns zero if it could find the path, different from zero if not found */ -PORTABILITY_API int portability_library_path(const char name[], portability_library_path_str path, size_t *length); +PORTABILITY_API int portability_library_path_find(const char name[], portability_library_path_str path, size_t *length); + +/** +* @brief +* List all the libraries loaded in the current process +* +* @param[in] callback +* Function pointer that will be called for each library loaded in the process +* +* @param[inout] data +* User defined data to pass to the callback +* +* @return +* Returns zero if it there is no error, different from zero on error +*/ +PORTABILITY_API int portability_library_path_list(portability_library_path_list_cb callback, void *data); #ifdef __cplusplus } diff --git a/source/portability/include/portability/portability_path.h b/source/portability/include/portability/portability_path.h index 36885514a..79ff0761b 100644 --- a/source/portability/include/portability/portability_path.h +++ b/source/portability/include/portability/portability_path.h @@ -111,6 +111,8 @@ extern "C" { PORTABILITY_API size_t portability_path_get_name(const char *path, size_t path_size, char *name, size_t name_size); +PORTABILITY_API size_t portability_path_get_name_canonical(const char *path, size_t path_size, char *name, size_t name_size); + PORTABILITY_API size_t portability_path_get_fullname(const char *path, size_t path_size, char *name, size_t name_size); PORTABILITY_API size_t portability_path_get_extension(const char *path, size_t path_size, char *extension, size_t extension_size); diff --git a/source/portability/source/portability_atexit.c b/source/portability/source/portability_atexit.c index 5dafc48a9..ee18e7795 100644 --- a/source/portability/source/portability_atexit.c +++ b/source/portability/source/portability_atexit.c @@ -54,6 +54,7 @@ static void portability_atexit_destroy(void) } free(prev); + } while (atexit_list != NULL); atexit_list = NULL; diff --git a/source/portability/source/portability_library_path.c b/source/portability/source/portability_library_path.c index 8bf167036..10e3ad64b 100644 --- a/source/portability/source/portability_library_path.c +++ b/source/portability/source/portability_library_path.c @@ -20,14 +20,14 @@ #include +#include #include -#define PORTABILITY_LIBRARY_PATH_SIZE (sizeof(portability_library_path_str) / sizeof(char)) - static int portability_library_path_ends_with(const char path[], const char name[]); #if defined(unix) || defined(__unix__) || defined(__unix) || \ - defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) + defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ + defined(__FreeBSD__) #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -38,48 +38,20 @@ static int portability_library_path_ends_with(const char path[], const char name #include -struct phdr_callback_type -{ - const char *name; - char *path; - size_t length; -}; - -static int portability_library_path_phdr_callback(struct dl_phdr_info *info, size_t size, void *data) -{ - struct phdr_callback_type *cb = (struct phdr_callback_type *)data; - - (void)size; - - if (portability_library_path_ends_with(info->dlpi_name, cb->name) == 0) - { - cb->length = strnlen(info->dlpi_name, PORTABILITY_LIBRARY_PATH_SIZE); - - if (cb->length >= PORTABILITY_LIBRARY_PATH_SIZE) - { - return 2; - } - - memcpy(cb->path, info->dlpi_name, sizeof(char) * (cb->length + 1)); - - return 1; - } +#elif (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) - return 0; -} + #include #elif defined(WIN32) || defined(_WIN32) || \ defined(__CYGWIN__) || defined(__CYGWIN32__) || \ defined(__MINGW32__) || defined(__MINGW64__) #define WIN32_LEAN_AND_MEAN - #include #include + #include -#elif (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) - - #include - +#else + #error "Unsupported platform for portability_library_path" #endif int portability_library_path_ends_with(const char path[], const char name[]) @@ -95,18 +67,74 @@ int portability_library_path_ends_with(const char path[], const char name[]) return !(name_length <= path_length && strncmp(path + path_length - name_length, name, name_length) == 0); } -int portability_library_path(const char name[], portability_library_path_str path, size_t *length) +#if defined(unix) || defined(__unix__) || defined(__unix) || \ + defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ + defined(__FreeBSD__) + +/* -- Type Definitions -- */ + +typedef struct portability_library_path_find_phdr_type *portability_library_path_find_phdr; +typedef struct portability_library_path_list_phdr_type *portability_library_path_list_phdr; + +/* -- Member Data -- */ + +struct portability_library_path_find_phdr_type +{ + const char *name; + char *path; + size_t length; +}; + +struct portability_library_path_list_phdr_type +{ + portability_library_path_list_cb callback; + void *data; +}; + +/* -- Private Methods -- */ + +static int portability_library_path_find_phdr_callback(struct dl_phdr_info *info, size_t size, void *data) +{ + portability_library_path_find_phdr find_phdr = (portability_library_path_find_phdr)data; + + (void)size; + + if (portability_library_path_ends_with(info->dlpi_name, find_phdr->name) == 0) + { + find_phdr->length = strnlen(info->dlpi_name, PORTABILITY_PATH_SIZE); + + memcpy(find_phdr->path, info->dlpi_name, sizeof(char) * (find_phdr->length + 1)); + + return 1; + } + + return 0; +} + +static int portability_library_path_list_phdr_callback(struct dl_phdr_info *info, size_t size, void *data) +{ + portability_library_path_list_phdr list_phdr = (portability_library_path_list_phdr)data; + + (void)size; + + return list_phdr->callback(info->dlpi_name, list_phdr->data); +} + +#endif + +int portability_library_path_find(const char name[], portability_library_path_str path, size_t *length) { #if defined(unix) || defined(__unix__) || defined(__unix) || \ - defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) + defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ + defined(__FreeBSD__) - struct phdr_callback_type data = { + struct portability_library_path_find_phdr_type data = { name, path, 0 }; - if (dl_iterate_phdr(&portability_library_path_phdr_callback, (void *)&data) != 1) + if (dl_iterate_phdr(&portability_library_path_find_phdr_callback, (void *)&data) != 1) { return 1; } @@ -124,21 +152,21 @@ int portability_library_path(const char name[], portability_library_path_str pat HMODULE handle_modules[1024]; HANDLE handle_process = GetCurrentProcess(); - DWORD cb_needed; + DWORD modules_size; - if (EnumProcessModules(handle_process, handle_modules, sizeof(handle_modules), &cb_needed)) + if (EnumProcessModules(handle_process, handle_modules, sizeof(handle_modules), &modules_size)) { - size_t iterator; + size_t iterator, size = modules_size / sizeof(HMODULE); - for (iterator = 0; iterator < (cb_needed / sizeof(HMODULE)); ++iterator) + for (iterator = 0; iterator < size; ++iterator) { - if (GetModuleFileNameEx(handle_process, handle_modules[iterator], path, PORTABILITY_LIBRARY_PATH_SIZE)) + if (GetModuleFileNameEx(handle_process, handle_modules[iterator], path, PORTABILITY_PATH_SIZE)) { if (portability_library_path_ends_with(path, name) == 0) { if (length != NULL) { - *length = strnlen(path, PORTABILITY_LIBRARY_PATH_SIZE); + *length = strnlen(path, PORTABILITY_PATH_SIZE); } return 0; @@ -153,10 +181,10 @@ int portability_library_path(const char name[], portability_library_path_str pat static const char dylib_suffix[] = "dylib"; uint32_t image_index, size = _dyld_image_count(); - size_t name_length = strnlen(name, PORTABILITY_LIBRARY_PATH_SIZE); + size_t name_length = strnlen(name, PORTABILITY_PATH_SIZE); size_t name_dylib_length = name_length + 3; - if (portability_library_path_ends_with(name, "so") == 0 && name_dylib_length < PORTABILITY_LIBRARY_PATH_SIZE) + if (portability_library_path_ends_with(name, "so") == 0 && name_dylib_length < PORTABILITY_PATH_SIZE) { memcpy(path, name, sizeof(char) * (name_length - 2)); memcpy(path, dylib_suffix, sizeof(dylib_suffix)); @@ -168,9 +196,9 @@ int portability_library_path(const char name[], portability_library_path_str pat if (portability_library_path_ends_with(image_name, path) == 0) { - size_t image_length = strnlen(image_name, PORTABILITY_LIBRARY_PATH_SIZE); + size_t image_length = strnlen(image_name, PORTABILITY_PATH_SIZE); - if (image_length >= PORTABILITY_LIBRARY_PATH_SIZE) + if (image_length >= PORTABILITY_PATH_SIZE) { return 1; } @@ -189,7 +217,69 @@ int portability_library_path(const char name[], portability_library_path_str pat return 1; #else - /* Not supported */ - return 1; + #error "Unsupported platform for portability_library_path" +#endif +} + +int portability_library_path_list(portability_library_path_list_cb callback, void *data) +{ + if (callback == NULL) + { + return 1; + } + +#if defined(linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux) || \ + defined(__FreeBSD__) + { + struct portability_library_path_list_phdr_type list_phdr = { + callback, + data + }; + + return dl_iterate_phdr(&portability_library_path_list_phdr_callback, (void *)&list_phdr); + } +#elif (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__) + { + uint32_t iterator, size = _dyld_image_count(); + + for (iterator = 0; iterator < size; ++iterator) + { + const char *image_name = _dyld_get_image_name(iterator); + + if (callback(image_name, data) != 0) + { + return 1; + } + } + + return 0; + } +#elif defined(WIN32) || defined(_WIN32) + { + HANDLE process = GetCurrentProcess(); + HMODULE modules[1024]; + DWORD modules_size; + + if (EnumProcessModules(process, modules, sizeof(modules), &modules_size)) + { + size_t iterator, size = modules_size / sizeof(HMODULE); + char module_name[MAX_PATH]; + + for (iterator = 0; iterator < size; ++iterator) + { + if (GetModuleFileNameExA(process, modules[iterator], module_name, sizeof(module_name) / sizeof(char))) + { + if (callback(module_name, data) != 0) + { + return 1; + } + } + } + } + + return 0; + } +#else + #error "Unsupported platform for portability_library_path" #endif } diff --git a/source/portability/source/portability_path.c b/source/portability/source/portability_path.c index 9e5232c27..9606a7d69 100644 --- a/source/portability/source/portability_path.c +++ b/source/portability/source/portability_path.c @@ -26,6 +26,54 @@ #define PORTABILITY_PATH_SEPARATOR_ALL(chr) (chr == '\\' || chr == '/') size_t portability_path_get_name(const char *path, size_t path_size, char *name, size_t name_size) +{ + size_t i, count, last; + + if (path == NULL || name == NULL) + { + return 0; + } + + for (i = 0, count = 0, last = 0; path[i] != '\0' && i < path_size && count < name_size; ++i) + { + name[count++] = path[i]; + + if (PORTABILITY_PATH_SEPARATOR(path[i])) + { + count = 0; + } + else if (path[i] == '.') + { + if (i > 0 && path[i - 1] == '.') + { + last = 0; + count = 0; + } + else + { + if (count > 0) + { + last = count - 1; + } + else + { + last = 0; + } + } + } + } + + if ((last == 0 && count > 1) || last > count) + { + last = count; + } + + name[last] = '\0'; + + return last + 1; +} + +size_t portability_path_get_name_canonical(const char *path, size_t path_size, char *name, size_t name_size) { if (path == NULL || name == NULL) { @@ -59,6 +107,13 @@ size_t portability_path_get_name(const char *path, size_t path_size, char *name, { last = 0; } + + /* This function is the same as portability_path_get_name but + returns the name of the file without any extension, for example: + - portability_path_get_name of libnode.so.72 is libnode.so + - portability_path_get_name_canonical of libnode.so.72 is libnode + */ + break; } } } diff --git a/source/ports/node_port/CMakeLists.txt b/source/ports/node_port/CMakeLists.txt index 5ddccd023..4fb44685c 100644 --- a/source/ports/node_port/CMakeLists.txt +++ b/source/ports/node_port/CMakeLists.txt @@ -89,7 +89,7 @@ install(FILES # # Check if loaders are enabled -if(NOT OPTION_BUILD_CLI OR NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_NODE OR NOT OPTION_BUILD_LOADERS_PY OR NOT OPTION_BUILD_LOADERS_RB OR NOT OPTION_BUILD_LOADERS_TS OR NOT OPTION_BUILD_SCRIPTS OR NOT OPTION_BUILD_SCRIPTS_PY OR NOT OPTION_BUILD_SCRIPTS_RB OR NOT OPTION_BUILD_SCRIPTS_TS) +if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_NODE OR NOT OPTION_BUILD_LOADERS_PY OR NOT OPTION_BUILD_LOADERS_RB OR NOT OPTION_BUILD_LOADERS_TS OR NOT OPTION_BUILD_SCRIPTS OR NOT OPTION_BUILD_SCRIPTS_PY OR NOT OPTION_BUILD_SCRIPTS_RB OR NOT OPTION_BUILD_SCRIPTS_TS) return() endif() @@ -116,30 +116,9 @@ if(OPTION_BUILD_THREAD_SANITIZER AND OPTION_BUILD_LOADERS_CS) endif() # -# Define test +# Define environment variables # -set(node_port_test "${target}_test") - -message(STATUS "Test ${node_port_test}") - -add_test(NAME ${target} - COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/commands/node_port.txt" -P "${CMAKE_SOURCE_DIR}/source/cli/metacallcli/test/commands/command_runner.cmake" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -# -# Define test labels -# - -set_property(TEST ${target} - PROPERTY LABELS ${node_port_test} -) - -set_tests_properties(${target} PROPERTIES - PASS_REGULAR_EXPRESSION "Tests passed without errors" -) - include(TestEnvironmentVariables) # Enable cobol test if it is built @@ -160,19 +139,7 @@ if(OPTION_BUILD_LOADERS_RS) set(TESTS_ENVIRONMENT_VARIABLES_RS "OPTION_BUILD_LOADERS_RS=1") endif() -# Add dependencies and optional dependencies -add_dependencies(${target} - node_loader - mock_loader - py_loader - rb_loader - ts_loader - ${COBOL_DEPENDENCY} - ${C_DEPENDENCY} - ${RS_DEPENDENCY} -) - -# Disable OpenSSL related tests if versions are incompatible +# Disable OpenSSL related tests if versions are incompatible (TODO: Review this bug and remove the workaround if possible) set(NodeJS_EXECUTABLE_ONLY ON) find_package(NodeJS) @@ -207,14 +174,54 @@ if(NodeJS_FOUND AND Python_Interpreter_FOUND) endif() endif() -test_environment_variables(${target} - "" - ${TESTS_ENVIRONMENT_VARIABLES} - ${TESTS_ENVIRONMENT_VARIABLES_COB} - ${TESTS_ENVIRONMENT_VARIABLES_C} - ${TESTS_ENVIRONMENT_VARIABLES_RS} - ${TESTS_ENVIRONMENT_VARIABLES_OPENSSL} -) +# +# Test importing NodeJS Port from CLI +# + +set(node_port_test "${target}_test") + +if(OPTION_BUILD_CLI) + message(STATUS "Test ${node_port_test}") + + add_test(NAME ${target} + COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/commands/node_port.txt" -P "${CMAKE_SOURCE_DIR}/source/cli/metacallcli/test/commands/command_runner.cmake" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + + # + # Define test labels + # + + set_property(TEST ${target} + PROPERTY LABELS ${node_port_test} + ) + + set_tests_properties(${target} PROPERTIES + PASS_REGULAR_EXPRESSION "Tests passed without errors" + ) + + # Add dependencies and optional dependencies + add_dependencies(${target} + node_loader + mock_loader + py_loader + rb_loader + ts_loader + ${COBOL_DEPENDENCY} + ${C_DEPENDENCY} + ${RS_DEPENDENCY} + ) + + # Environment variables + test_environment_variables(${target} + "" + ${TESTS_ENVIRONMENT_VARIABLES} + ${TESTS_ENVIRONMENT_VARIABLES_COB} + ${TESTS_ENVIRONMENT_VARIABLES_C} + ${TESTS_ENVIRONMENT_VARIABLES_RS} + ${TESTS_ENVIRONMENT_VARIABLES_OPENSSL} + ) +endif() # # Test importing NodeJS Port from node.exe diff --git a/source/ports/py_port/helper.py b/source/ports/py_port/helper.py index 86f851381..1a0a77df8 100644 --- a/source/ports/py_port/helper.py +++ b/source/ports/py_port/helper.py @@ -112,7 +112,7 @@ def pre_install(components): def pre_install_prompt(): answers = {'yes': True, 'y': True, 'no': False, 'n': False} - components = ['python', 'ruby', 'netcore7', 'v8', 'nodejs', 'ports'] + components = ['python', 'ruby', 'netcore8', 'v8', 'nodejs', 'ports'] args = [] try: diff --git a/source/ports/rs_port/src/bindings.rs b/source/ports/rs_port/src/bindings.rs index c4319b2ac..26a41b7bd 100644 --- a/source/ports/rs_port/src/bindings.rs +++ b/source/ports/rs_port/src/bindings.rs @@ -627,8 +627,8 @@ unsafe extern "C" { ); } unsafe extern "C" { - #[doc = " @brief\n Unregister fork detours and destroy shared memory\n\n @return\n Zero if success, different from zero otherwise"] - pub fn metacall_fork_destroy() -> ::std::os::raw::c_int; + #[doc = " @brief\n Unregister fork detours and destroy shared memory"] + pub fn metacall_fork_destroy(); } #[repr(C)] #[derive(Debug, Copy, Clone)] diff --git a/source/ports/zig_port/src/metacall-bindings.zig b/source/ports/zig_port/src/metacall-bindings.zig index 0615eb723..9e51c89cd 100644 --- a/source/ports/zig_port/src/metacall-bindings.zig +++ b/source/ports/zig_port/src/metacall-bindings.zig @@ -1235,7 +1235,7 @@ pub const metacall_pre_fork_callback_ptr = ?*const fn (?*anyopaque) callconv(.C) pub const metacall_post_fork_callback_ptr = ?*const fn (metacall_pid, ?*anyopaque) callconv(.C) c_int; pub extern fn metacall_fork_initialize() c_int; pub extern fn metacall_fork(pre_callback: metacall_pre_fork_callback_ptr, post_callback: metacall_post_fork_callback_ptr) void; -pub extern fn metacall_fork_destroy() c_int; +pub extern fn metacall_fork_destroy() void; pub const struct_metacall_initialize_configuration_type = extern struct { tag: [*c]u8 = @import("std").mem.zeroes([*c]u8), options: ?*anyopaque = @import("std").mem.zeroes(?*anyopaque), diff --git a/source/reflect/source/reflect_class.c b/source/reflect/source/reflect_class.c index 77ea42baa..63643a24f 100644 --- a/source/reflect/source/reflect_class.c +++ b/source/reflect/source/reflect_class.c @@ -42,7 +42,7 @@ struct class_type enum accessor_type_id accessor; class_impl impl; class_interface interface; - struct threading_atomic_ref_count_type ref; + threading_atomic_ref_count_type ref; vector constructors; map methods; map static_methods; @@ -123,6 +123,7 @@ klass class_create(const char *name, enum accessor_type_id accessor, class_impl log_write("metacall", LOG_LEVEL_ERROR, "Invalid class (%s) create callback <%p>", cls->name, cls->interface->create); free(cls->name); + threading_atomic_ref_count_destroy(&cls->ref); vector_destroy(cls->constructors); map_destroy(cls->methods); map_destroy(cls->static_methods); diff --git a/source/reflect/source/reflect_exception.c b/source/reflect/source/reflect_exception.c index 179aa237a..34b3dc2d3 100644 --- a/source/reflect/source/reflect_exception.c +++ b/source/reflect/source/reflect_exception.c @@ -37,7 +37,7 @@ struct exception_type int64_t code; /* Numeric code of error */ char *stacktrace; /* Stack trace of the error */ uint64_t id; /* Thread id where the error was raised */ - struct threading_atomic_ref_count_type ref; + threading_atomic_ref_count_type ref; /* TODO: value attributes; // This should implement a map for representing the extra attributes of an exception */ }; @@ -138,9 +138,15 @@ exception exception_create_const(const char *message, const char *label, int64_t return ex; stacktrace_bad_alloc: - free(ex->label); + if (ex->label != NULL) + { + free(ex->label); + } label_bad_alloc: - free(ex->message); + if (ex->message != NULL) + { + free(ex->message); + } message_bad_alloc: free(ex); exception_bad_alloc: diff --git a/source/reflect/source/reflect_function.c b/source/reflect/source/reflect_function.c index d64ab1c90..b9a03512f 100644 --- a/source/reflect/source/reflect_function.c +++ b/source/reflect/source/reflect_function.c @@ -36,7 +36,7 @@ struct function_type signature s; function_impl impl; function_interface interface; - struct threading_atomic_ref_count_type ref; + threading_atomic_ref_count_type ref; enum async_id async; void *data; }; @@ -66,9 +66,7 @@ function function_create(const char *name, size_t args_count, function_impl impl { log_write("metacall", LOG_LEVEL_ERROR, "Invalid function name allocation <%s>", name); - free(func); - - return NULL; + goto name_error; } memcpy(func->name, name, func_name_size); @@ -88,7 +86,7 @@ function function_create(const char *name, size_t args_count, function_impl impl { log_write("metacall", LOG_LEVEL_ERROR, "Invalid function signature allocation"); - goto function_create_error; + goto signature_error; } threading_atomic_ref_count_initialize(&func->ref); @@ -101,7 +99,7 @@ function function_create(const char *name, size_t args_count, function_impl impl { log_write("metacall", LOG_LEVEL_ERROR, "Invalid function (%s) create callback <%p>", func->name, func->interface->create); - goto function_create_error; + goto interface_create_error; } } @@ -109,8 +107,14 @@ function function_create(const char *name, size_t args_count, function_impl impl return func; -function_create_error: - free(func->name); +interface_create_error: + signature_destroy(func->s); +signature_error: + if (func->name != NULL) + { + free(func->name); + } +name_error: free(func); return NULL; diff --git a/source/reflect/source/reflect_object.c b/source/reflect/source/reflect_object.c index 1938d55ec..a568b24d7 100644 --- a/source/reflect/source/reflect_object.c +++ b/source/reflect/source/reflect_object.c @@ -40,7 +40,7 @@ struct object_type enum accessor_type_id accessor; object_impl impl; object_interface interface; - struct threading_atomic_ref_count_type ref; + threading_atomic_ref_count_type ref; klass cls; }; @@ -67,9 +67,7 @@ object object_create(const char *name, enum accessor_type_id accessor, object_im { log_write("metacall", LOG_LEVEL_ERROR, "Invalid object name allocation <%s>", name); - free(obj); - - return NULL; + goto name_error; } memcpy(obj->name, name, obj_name_size); @@ -79,12 +77,11 @@ object object_create(const char *name, enum accessor_type_id accessor, object_im obj->name = NULL; } - obj->impl = impl; - obj->accessor = accessor; threading_atomic_ref_count_initialize(&obj->ref); + obj->impl = impl; + obj->accessor = accessor; obj->interface = singleton ? singleton() : NULL; - obj->cls = cls; if (obj->interface != NULL && obj->interface->create != NULL) @@ -93,16 +90,23 @@ object object_create(const char *name, enum accessor_type_id accessor, object_im { log_write("metacall", LOG_LEVEL_ERROR, "Invalid object (%s) create callback <%p>", obj->name, obj->interface->create); - free(obj->name); - free(obj); - - return NULL; + goto interface_create_error; } } reflect_memory_tracker_allocation(object_stats); return obj; + +interface_create_error: + if (obj->name != NULL) + { + free(obj->name); + } +name_error: + free(obj); + + return NULL; } int object_increment_reference(object obj) diff --git a/source/reflect/source/reflect_scope.c b/source/reflect/source/reflect_scope.c index a8fbe4944..3942bb8ee 100644 --- a/source/reflect/source/reflect_scope.c +++ b/source/reflect/source/reflect_scope.c @@ -200,17 +200,17 @@ int scope_metadata_array_cb_iterate(set s, set_key key, set_value val, set_cb_it (void)s; (void)key; - int type_id = value_type_id(val); + type_id id = value_type_id(val); - if (type_id == TYPE_FUNCTION) + if (id == TYPE_FUNCTION) { metadata_iterator->functions[metadata_iterator->functions_size++] = function_metadata(value_to_function(val)); } - else if (type_id == TYPE_CLASS) + else if (id == TYPE_CLASS) { metadata_iterator->classes[metadata_iterator->classes_size++] = class_metadata(value_to_class(val)); } - else if (type_id == TYPE_OBJECT) + else if (id == TYPE_OBJECT) { metadata_iterator->objects[metadata_iterator->objects_size++] = object_metadata(value_to_object(val)); } diff --git a/source/serials/metacall_serial/source/metacall_serial_impl_serialize.c b/source/serials/metacall_serial/source/metacall_serial_impl_serialize.c index e618f935e..16dd1d267 100644 --- a/source/serials/metacall_serial/source/metacall_serial_impl_serialize.c +++ b/source/serials/metacall_serial/source/metacall_serial_impl_serialize.c @@ -221,7 +221,7 @@ void metacall_serial_impl_serialize_array(value v, char *dest, size_t size, cons (void)format; - /* Calculate sum of all array values lenght */ + /* Calculate sum of all array values length */ for (iterator = 0; iterator < array_size; ++iterator) { value current_value = array_value[iterator]; diff --git a/source/serials/rapid_json_serial/source/rapid_json_serial_impl.cpp b/source/serials/rapid_json_serial/source/rapid_json_serial_impl.cpp index 973c06da3..e2e981d7f 100644 --- a/source/serials/rapid_json_serial/source/rapid_json_serial_impl.cpp +++ b/source/serials/rapid_json_serial/source/rapid_json_serial_impl.cpp @@ -12,14 +12,27 @@ #include -// TODO: RapidJSON seems to be outdated, but we use it meanwhile there's a better solution. -// Here's a patch for some of the bugs in the library: https://github.com/Tencent/rapidjson/issues/1928 +/* Disable warnings from RapidJSON */ +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wstrict-overflow" +#elif defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-overflow" +#endif #include #include #include #include +/* Disable warnings from RapidJSON */ +#if defined(__clang__) + #pragma clang diagnostic pop +#elif defined(__GNUC__) + #pragma GCC diagnostic pop +#endif + #include /* -- Type Definitions -- */ @@ -41,7 +54,6 @@ static value rapid_json_serial_impl_deserialize_value(const rapidjson::Value *v) /* -- Classes -- */ -// https://techoverflow.net/2020/01/13/how-to-fix-rapidjson-segmentation-faults-when-building-nested-documents/ rapidjson::MemoryPoolAllocator<> rapid_json_allocator; /* -- Methods -- */ @@ -91,9 +103,7 @@ void rapid_json_serial_impl_serialize_value(value v, rapidjson::Value *json_v) { short s = value_to_short(v); - int i = (int)s; - - json_v->SetInt(i); + json_v->SetInt((int)s); } else if (id == TYPE_INT) { @@ -105,9 +115,7 @@ void rapid_json_serial_impl_serialize_value(value v, rapidjson::Value *json_v) { long l = value_to_long(v); - log_write("metacall", LOG_LEVEL_WARNING, "Casting long to int64_t (posible incompatible types) in RapidJSON implementation"); - - json_v->SetInt64(l); + json_v->SetInt64((int64_t)l); } else if (id == TYPE_FLOAT) { @@ -394,6 +402,7 @@ value rapid_json_serial_impl_deserialize_value(const rapidjson::Value *v) { unsigned int ui = v->GetUint(); + /* TODO: Review this, in case of underflow/overflow store it in a bigger type? */ log_write("metacall", LOG_LEVEL_WARNING, "Casting unsigned integer to integer (posible overflow) in RapidJSON implementation"); return value_create_int((int)ui); @@ -402,13 +411,21 @@ value rapid_json_serial_impl_deserialize_value(const rapidjson::Value *v) { int64_t i = v->GetInt64(); + /* TODO: Review this, in case of underflow/overflow store it in a bigger type? */ +#if LONG_MAX < INT64_MAX + log_write("metacall", LOG_LEVEL_WARNING, "Casting long to int (posible overflow) in RapidJSON implementation"); +#endif + return value_create_long((long)i); } else if (v->IsUint64() == true) { uint64_t ui = v->GetUint64(); + /* TODO: Review this, in case of underflow/overflow store it in a bigger type? */ +#if LONG_MAX < UINT64_MAX log_write("metacall", LOG_LEVEL_WARNING, "Casting unsigned long to int (posible overflow) in RapidJSON implementation"); +#endif return value_create_long((long)ui); } diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index aca1cfdaa..bf31bbbf9 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -12,7 +12,7 @@ if("${CMAKE_VERSION}" VERSION_LESS "3.11" AND POLICY CMP0037) set_policy(CMP0037 OLD) endif() -set(GTEST_VERSION 1.11.0) +set(GTEST_VERSION 1.16.0) find_package(GTest ${GTEST_VERSION}) diff --git a/source/tests/adt_map_test/CMakeLists.txt b/source/tests/adt_map_test/CMakeLists.txt index 29ae7e7e9..0767bcbb2 100644 --- a/source/tests/adt_map_test/CMakeLists.txt +++ b/source/tests/adt_map_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/adt_set_test/CMakeLists.txt b/source/tests/adt_set_test/CMakeLists.txt index d46b7064f..a3d3b1c3f 100644 --- a/source/tests/adt_set_test/CMakeLists.txt +++ b/source/tests/adt_set_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/adt_trie_test/CMakeLists.txt b/source/tests/adt_trie_test/CMakeLists.txt index 1bac7e403..19babf556 100644 --- a/source/tests/adt_trie_test/CMakeLists.txt +++ b/source/tests/adt_trie_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/adt_vector_test/CMakeLists.txt b/source/tests/adt_vector_test/CMakeLists.txt index dab9ae9a6..e454f0266 100644 --- a/source/tests/adt_vector_test/CMakeLists.txt +++ b/source/tests/adt_vector_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/configuration_test/CMakeLists.txt b/source/tests/configuration_test/CMakeLists.txt index c9f804954..0700e2bf7 100644 --- a/source/tests/configuration_test/CMakeLists.txt +++ b/source/tests/configuration_test/CMakeLists.txt @@ -115,6 +115,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/detour_test/CMakeLists.txt b/source/tests/detour_test/CMakeLists.txt index 7b722beeb..06e3ef979 100644 --- a/source/tests/detour_test/CMakeLists.txt +++ b/source/tests/detour_test/CMakeLists.txt @@ -1,5 +1,5 @@ # Check if detours are enabled -if(NOT OPTION_BUILD_DETOURS OR NOT OPTION_BUILD_DETOURS_FUNCHOOK) +if(NOT OPTION_BUILD_DETOURS OR NOT OPTION_BUILD_DETOURS_PLTHOOK) return() endif() @@ -117,6 +117,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -134,6 +143,14 @@ add_test(NAME ${target} COMMAND $ ) +# +# Define dependencies +# + +add_dependencies(${target} + plthook_detour +) + # # Define test properties # diff --git a/source/tests/detour_test/source/detour_test.cpp b/source/tests/detour_test/source/detour_test.cpp index 6b84295fd..15b56ec58 100644 --- a/source/tests/detour_test/source/detour_test.cpp +++ b/source/tests/detour_test/source/detour_test.cpp @@ -24,6 +24,8 @@ #include +#include + #include class detour_test : public testing::Test @@ -31,27 +33,60 @@ class detour_test : public testing::Test public: }; -static detour_handle handle; +static detour_handle handle = NULL; +static const char *(*trampoline)(void) = NULL; -int hook_function(int x) +int check_detour_hook(const char *(*fp)(void)) { - EXPECT_EQ((int)128, (int)x); + static const char str_without_hook[] = "Detour Library"; + + const char *str = fp(); + + log_write("metacall", LOG_LEVEL_DEBUG, "Check: %s", str); - log_write("metacall", LOG_LEVEL_DEBUG, "Hook function %d", x); + return strncmp(str, str_without_hook, sizeof(str_without_hook) - 1); +} - int (*target_function_ptr)(int) = (int (*)(int))detour_trampoline(handle); +const char *hook_function(void) +{ + static const char str_with_hook[] = "Yeet"; - int result = target_function_ptr(x + 2) + 2; + log_write("metacall", LOG_LEVEL_DEBUG, "HOOK WORKING PROPERLY"); + log_write("metacall", LOG_LEVEL_DEBUG, "Original function: %s", trampoline()); - log_write("metacall", LOG_LEVEL_DEBUG, "Hook function result %d", result); + /* Here we check that we got the correct trampoline implementation (aka the original function) + and we can call it from inside of the body of the hook function */ + EXPECT_EQ((int)0, (int)check_detour_hook(trampoline)); - return result; + return str_with_hook; } -int target_function(int x) +/* TODO: +* This test is not going to work because detour_enumeration does not walk in +* the following sections: +* T Global text symbol +* t Local text symbol +* This funtion we are searching for is stored in: +* 0000000000073630 T test_exported_symbols_from_executable +* 00000000000736e0 t _Z13hook_functionv +* 0000000000072e34 t _Z13hook_functionv.cold +* 0000000000073680 t _Z17check_detour_hookPFPKcvE +* We can find all the sections here: https://en.wikipedia.org/wiki/Nm_(Unix) +* For listing properly all the symbols we should replicate something like +* GNU libc does under the hood for dlsym, which is implemented through do_lookup: +* https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=elf/dl-lookup.c;hb=HEAD +* We will leave this for future versions, including support for GNU hashed symbols. +*/ +#define TODO_TEST_EXPORTED_SYMBOLS_FROM_EXECUTABLE 1 + +#ifdef _WIN32 + #define EXPORT_SYMBOL __declspec(dllexport) +#else + #define EXPORT_SYMBOL __attribute__((visibility("default"))) +#endif + +extern "C" EXPORT_SYMBOL int test_exported_symbols_from_executable(int x) { - EXPECT_EQ((int)130, (int)x); - log_write("metacall", LOG_LEVEL_DEBUG, "Target function %d", x); return x; @@ -59,7 +94,7 @@ int target_function(int x) TEST_F(detour_test, DefaultConstructor) { - static const char name[] = "funchook"; + static const char name[] = "plthook"; /* Initialize log */ EXPECT_EQ((int)0, (int)log_configure("metacall", @@ -71,23 +106,55 @@ TEST_F(detour_test, DefaultConstructor) /* Initialize detour */ EXPECT_EQ((int)0, (int)detour_initialize()); - /* Create detour funchook */ + /* Create detour plthook */ detour d = detour_create(name); - EXPECT_NE((detour)NULL, (detour)d); + ASSERT_NE((detour)NULL, (detour)d); EXPECT_EQ((int)0, (int)strcmp(name, detour_name(d))); + /* Load detour of detour library */ + handle = detour_load_file(d, NULL); + + ASSERT_NE((detour_handle)NULL, (detour_handle)handle); + + /* Check if it can list exported symbols from executable */ +#ifndef TODO_TEST_EXPORTED_SYMBOLS_FROM_EXECUTABLE + test_exported_symbols_from_executable(3); + + unsigned int position = 0; + const char *fn_name = NULL; + void (**addr)(void) = NULL; + bool found = false; + while (detour_enumerate(d, handle, &position, &fn_name, &addr) == 0) + { + log_write("metacall", LOG_LEVEL_DEBUG, "[%d] %p %s", position, *addr, fn_name); + + if (strcmp("test_exported_symbols_from_executable", fn_name) == 0) + { + found = true; + EXPECT_EQ((void *)(*addr), (void *)(&test_exported_symbols_from_executable)); + break; + } + } + + EXPECT_EQ((bool)true, (bool)found); +#endif + /* Install detour */ - handle = detour_install(d, (void (*)(void)) & target_function, (void (*)(void)) & hook_function); + union + { + const char *(**trampoline)(void); + void (**ptr)(void); + } cast = { &trampoline }; - EXPECT_NE((detour_handle)NULL, (detour_handle)handle); + ASSERT_EQ((int)0, detour_replace(d, handle, "detour_print_info", (void (*)(void))(&hook_function), cast.ptr)); - /* Call detour, it should call hooked function */ - EXPECT_EQ((int)132, (int)target_function(128)); + /* This must return "Yeet", so when checking the test it should return distinct from 0, then the funtion is properly hooked */ + EXPECT_NE((int)0, (int)check_detour_hook(&detour_print_info)); /* Uninstall detour */ - EXPECT_EQ((int)0, (int)detour_uninstall(d, handle)); + detour_unload(d, handle); /* Clear detour */ EXPECT_EQ((int)0, (int)detour_clear(d)); diff --git a/source/tests/dynlink_test/CMakeLists.txt b/source/tests/dynlink_test/CMakeLists.txt index d0e0d844d..ae0eabeee 100644 --- a/source/tests/dynlink_test/CMakeLists.txt +++ b/source/tests/dynlink_test/CMakeLists.txt @@ -97,6 +97,8 @@ target_link_libraries(${target} target_compile_definitions(${target} PRIVATE ${DEFAULT_COMPILE_DEFINITIONS} + + $<$,$>:DYNLINK_TEST_MOCK_LOADER> ) # @@ -108,6 +110,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -115,6 +126,9 @@ target_compile_options(${target} target_link_options(${target} PRIVATE ${DEFAULT_LINKER_OPTIONS} + + $<$,$>:-Wl,-export_dynamic> + $<$:-rdynamic> ) # @@ -125,6 +139,16 @@ add_test(NAME ${target} COMMAND $ ) +# +# Define dependencies +# + +if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_MOCK) + add_dependencies(${target} + mock_loader + ) +endif() + # # Define test labels # diff --git a/source/tests/dynlink_test/source/dynlink_test.cpp b/source/tests/dynlink_test/source/dynlink_test.cpp index ed6aec997..1ebd63613 100644 --- a/source/tests/dynlink_test/source/dynlink_test.cpp +++ b/source/tests/dynlink_test/source/dynlink_test.cpp @@ -28,13 +28,26 @@ #define DYNLINK_TEST_LIBRARY_PATH "DYNLINK_TEST_LIBRARY_PATH" -typedef void (*mock_loader_print_func)(void); +typedef const char *(*mock_loader_print_func)(void); class dynlink_test : public testing::Test { protected: }; +#ifdef _WIN32 + #define EXPORT_SYMBOL __declspec(dllexport) +#else + #define EXPORT_SYMBOL __attribute__((visibility("default"))) +#endif + +extern "C" EXPORT_SYMBOL int function_from_current_executable(void) +{ + log_write("metacall", LOG_LEVEL_INFO, "function_from_current_executable"); + + return 48; +} + TEST_F(dynlink_test, DefaultConstructor) { EXPECT_EQ((int)0, (int)log_configure("metacall", @@ -47,46 +60,122 @@ TEST_F(dynlink_test, DefaultConstructor) log_write("metacall", LOG_LEVEL_DEBUG, "Dynamic linked shared object extension: %s", dynlink_extension()); + /* Test loading symbols from current process */ + { + dynlink proc = dynlink_load_self(DYNLINK_FLAGS_BIND_GLOBAL | DYNLINK_FLAGS_BIND_LAZY); + + ASSERT_NE((dynlink)proc, (dynlink)(NULL)); + + dynlink_symbol_addr addr; + + EXPECT_EQ((int)0, dynlink_symbol(proc, "function_from_current_executable", &addr)); + + ASSERT_NE((dynlink_symbol_addr)addr, (dynlink_symbol_addr)NULL); + + int (*fn_ptr)(void) = (int (*)(void))addr; + + EXPECT_EQ((int)48, fn_ptr()); + + EXPECT_EQ((int (*)(void))(&function_from_current_executable), (int (*)(void))fn_ptr); + + dynlink_unload(proc); /* Should do nothing except by freeing the handle */ + } + +#ifdef DYNLINK_TEST_MOCK_LOADER { -#if (!defined(NDEBUG) || defined(DEBUG) || defined(_DEBUG) || defined(__DEBUG) || defined(__DEBUG__)) + #if (!defined(NDEBUG) || defined(DEBUG) || defined(_DEBUG) || defined(__DEBUG) || defined(__DEBUG__)) const char library_name[] = "mock_loaderd"; -#else + #else const char library_name[] = "mock_loader"; -#endif + #endif char *path = environment_variable_path_create(DYNLINK_TEST_LIBRARY_PATH, NULL, 0, NULL); - dynlink handle = dynlink_load(path, library_name, DYNLINK_FLAGS_BIND_NOW | DYNLINK_FLAGS_BIND_GLOBAL); + ASSERT_NE((char *)path, (char *)NULL); - environment_variable_path_destroy(path); + /* Test library loading */ + { + dynlink handle = dynlink_load(path, library_name, DYNLINK_FLAGS_BIND_NOW | DYNLINK_FLAGS_BIND_GLOBAL); + + ASSERT_NE(handle, (dynlink)NULL); - EXPECT_NE(handle, (dynlink)NULL); + log_write("metacall", LOG_LEVEL_DEBUG, "Dynamic linked shared object file: %s", dynlink_get_path(handle)); + + EXPECT_EQ((int)0, (int)strcmp(library_name, dynlink_get_name(handle))); + + if (handle != NULL) + { + dynlink_symbol_addr mock_loader_print_info_addr; - log_write("metacall", LOG_LEVEL_DEBUG, "Dynamic linked shared object file: %s", dynlink_get_name_impl(handle)); + EXPECT_EQ((int)0, dynlink_symbol(handle, "mock_loader_print_info", &mock_loader_print_info_addr)); - if (handle != NULL) + if (mock_loader_print_info_addr != NULL) + { + mock_loader_print_func print = (mock_loader_print_func)mock_loader_print_info_addr; + + log_write("metacall", LOG_LEVEL_DEBUG, "Print function: %p", (void *)print); + + log_write("metacall", LOG_LEVEL_DEBUG, "Symbol pointer: %p", (void *)mock_loader_print_info_addr); + + if (mock_loader_print_info_addr != NULL) + { + log_write("metacall", LOG_LEVEL_DEBUG, "Pointer is valid"); + } + + log_write("metacall", LOG_LEVEL_DEBUG, "Print: %s", print()); + } + + dynlink_unload(handle); + } + } + + /* Test loading symbols from absolute path */ { - static dynlink_symbol_addr mock_loader_print_info_addr; + char library_name_platform[PORTABILITY_PATH_SIZE]; + char absolute_path[PORTABILITY_PATH_SIZE]; - EXPECT_EQ((int)0, dynlink_symbol(handle, "mock_loader_print_info", &mock_loader_print_info_addr)); + dynlink_platform_name(library_name, library_name_platform); - if (mock_loader_print_info_addr != NULL) - { - mock_loader_print_func print = mock_loader_print_info_addr; + portability_path_join(path, strlen(path) + 1, library_name_platform, strlen(library_name_platform) + 1, absolute_path, PORTABILITY_PATH_SIZE); + + dynlink handle = dynlink_load_absolute(absolute_path, DYNLINK_FLAGS_BIND_NOW | DYNLINK_FLAGS_BIND_GLOBAL); - log_write("metacall", LOG_LEVEL_DEBUG, "Print function: %p", (void *)print); + ASSERT_NE(handle, (dynlink)NULL); - log_write("metacall", LOG_LEVEL_DEBUG, "Symbol pointer: %p", (void *)mock_loader_print_info_addr); + log_write("metacall", LOG_LEVEL_DEBUG, "Dynamic linked shared object absolute path: %s", absolute_path); + log_write("metacall", LOG_LEVEL_DEBUG, "Dynamic linked shared object file name: %s", dynlink_get_path(handle)); + log_write("metacall", LOG_LEVEL_DEBUG, "Dynamic linked shared object file: %s", dynlink_get_name(handle)); + + EXPECT_EQ((int)0, (int)strcmp(absolute_path, dynlink_get_path(handle))); + EXPECT_EQ((int)0, (int)strcmp(library_name, dynlink_get_name(handle))); + + if (handle != NULL) + { + dynlink_symbol_addr mock_loader_print_info_addr; + + EXPECT_EQ((int)0, dynlink_symbol(handle, "mock_loader_print_info", &mock_loader_print_info_addr)); if (mock_loader_print_info_addr != NULL) { - log_write("metacall", LOG_LEVEL_DEBUG, "Pointer is valid"); + mock_loader_print_func print = (mock_loader_print_func)mock_loader_print_info_addr; + + log_write("metacall", LOG_LEVEL_DEBUG, "Print function: %p", (void *)print); + + log_write("metacall", LOG_LEVEL_DEBUG, "Symbol pointer: %p", (void *)mock_loader_print_info_addr); + + if (mock_loader_print_info_addr != NULL) + { + log_write("metacall", LOG_LEVEL_DEBUG, "Pointer is valid"); + } + + log_write("metacall", LOG_LEVEL_DEBUG, "Print: %s", print()); } - print(); + dynlink_unload(handle); } - - dynlink_unload(handle); } + + environment_variable_path_destroy(path); } +#endif } diff --git a/source/tests/environment_test/CMakeLists.txt b/source/tests/environment_test/CMakeLists.txt index ec3e14449..3472e06a8 100644 --- a/source/tests/environment_test/CMakeLists.txt +++ b/source/tests/environment_test/CMakeLists.txt @@ -103,6 +103,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/log_custom_test/CMakeLists.txt b/source/tests/log_custom_test/CMakeLists.txt index 73ef1f64a..f46ff859e 100644 --- a/source/tests/log_custom_test/CMakeLists.txt +++ b/source/tests/log_custom_test/CMakeLists.txt @@ -105,6 +105,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/log_custom_test/source/log_custom_test.cpp b/source/tests/log_custom_test/source/log_custom_test.cpp index 51754be99..f97ebcc6b 100644 --- a/source/tests/log_custom_test/source/log_custom_test.cpp +++ b/source/tests/log_custom_test/source/log_custom_test.cpp @@ -25,7 +25,7 @@ #include #include -static const char format[] = "%.19s #%" PRIuS " %s:%" PRIuS " %s @%s "; +static const char format[] = "%.19s #%" PRIu64 " %s:%" PRIuS " %s @%s "; class log_custom_test : public testing::Test { diff --git a/source/tests/log_test/CMakeLists.txt b/source/tests/log_test/CMakeLists.txt index d3f70ddc3..d091de149 100644 --- a/source/tests/log_test/CMakeLists.txt +++ b/source/tests/log_test/CMakeLists.txt @@ -105,6 +105,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_backtrace_plugin_test/CMakeLists.txt b/source/tests/metacall_backtrace_plugin_test/CMakeLists.txt index 013b1d742..900355faa 100644 --- a/source/tests/metacall_backtrace_plugin_test/CMakeLists.txt +++ b/source/tests/metacall_backtrace_plugin_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_c_lib_test/CMakeLists.txt b/source/tests/metacall_c_lib_test/CMakeLists.txt index eace7e1da..d3a375064 100644 --- a/source/tests/metacall_c_lib_test/CMakeLists.txt +++ b/source/tests/metacall_c_lib_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_c_test/CMakeLists.txt b/source/tests/metacall_c_test/CMakeLists.txt index 7599f98cb..a5c3e0edd 100644 --- a/source/tests/metacall_c_test/CMakeLists.txt +++ b/source/tests/metacall_c_test/CMakeLists.txt @@ -120,6 +120,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_callback_complex_test/CMakeLists.txt b/source/tests/metacall_callback_complex_test/CMakeLists.txt index 00183a9c2..ddf680698 100644 --- a/source/tests/metacall_callback_complex_test/CMakeLists.txt +++ b/source/tests/metacall_callback_complex_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_cast_test/CMakeLists.txt b/source/tests/metacall_cast_test/CMakeLists.txt index ec7b1876b..674a14516 100644 --- a/source/tests/metacall_cast_test/CMakeLists.txt +++ b/source/tests/metacall_cast_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_clear_test/CMakeLists.txt b/source/tests/metacall_clear_test/CMakeLists.txt index bb461a5e9..859807d95 100644 --- a/source/tests/metacall_clear_test/CMakeLists.txt +++ b/source/tests/metacall_clear_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_cli_core_plugin_await_test/CMakeLists.txt b/source/tests/metacall_cli_core_plugin_await_test/CMakeLists.txt index 9c444e084..13284fb39 100644 --- a/source/tests/metacall_cli_core_plugin_await_test/CMakeLists.txt +++ b/source/tests/metacall_cli_core_plugin_await_test/CMakeLists.txt @@ -119,6 +119,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_cli_core_plugin_test/CMakeLists.txt b/source/tests/metacall_cli_core_plugin_test/CMakeLists.txt index 8de5b40ef..f0ecb936b 100644 --- a/source/tests/metacall_cli_core_plugin_test/CMakeLists.txt +++ b/source/tests/metacall_cli_core_plugin_test/CMakeLists.txt @@ -108,6 +108,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_cobol_test/CMakeLists.txt b/source/tests/metacall_cobol_test/CMakeLists.txt index c524b462c..3667141bc 100644 --- a/source/tests/metacall_cobol_test/CMakeLists.txt +++ b/source/tests/metacall_cobol_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_configuration_default_test/CMakeLists.txt b/source/tests/metacall_configuration_default_test/CMakeLists.txt index 571fc6786..8cf0d4007 100644 --- a/source/tests/metacall_configuration_default_test/CMakeLists.txt +++ b/source/tests/metacall_configuration_default_test/CMakeLists.txt @@ -125,6 +125,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_configuration_exec_path_test/CMakeLists.txt b/source/tests/metacall_configuration_exec_path_test/CMakeLists.txt index e63ff23b9..ff845b77b 100644 --- a/source/tests/metacall_configuration_exec_path_test/CMakeLists.txt +++ b/source/tests/metacall_configuration_exec_path_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_cs_test/CMakeLists.txt b/source/tests/metacall_cs_test/CMakeLists.txt index 084e5f819..6eb981ca3 100644 --- a/source/tests/metacall_cs_test/CMakeLists.txt +++ b/source/tests/metacall_cs_test/CMakeLists.txt @@ -113,6 +113,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_csharp_function_test/CMakeLists.txt b/source/tests/metacall_csharp_function_test/CMakeLists.txt index 53e8df1ac..0a70cedb5 100644 --- a/source/tests/metacall_csharp_function_test/CMakeLists.txt +++ b/source/tests/metacall_csharp_function_test/CMakeLists.txt @@ -121,6 +121,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_csharp_static_class_test/CMakeLists.txt b/source/tests/metacall_csharp_static_class_test/CMakeLists.txt index 9b04dac50..7c2289c3d 100644 --- a/source/tests/metacall_csharp_static_class_test/CMakeLists.txt +++ b/source/tests/metacall_csharp_static_class_test/CMakeLists.txt @@ -121,6 +121,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_depends_test/CMakeLists.txt b/source/tests/metacall_depends_test/CMakeLists.txt index ddc10ae8d..46fe418c7 100644 --- a/source/tests/metacall_depends_test/CMakeLists.txt +++ b/source/tests/metacall_depends_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_distributable_test/CMakeLists.txt b/source/tests/metacall_distributable_test/CMakeLists.txt index 87354950d..07d558161 100644 --- a/source/tests/metacall_distributable_test/CMakeLists.txt +++ b/source/tests/metacall_distributable_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_ducktype_test/CMakeLists.txt b/source/tests/metacall_ducktype_test/CMakeLists.txt index d092bc229..c8d507e6f 100644 --- a/source/tests/metacall_ducktype_test/CMakeLists.txt +++ b/source/tests/metacall_ducktype_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_duplicated_handle_test/CMakeLists.txt b/source/tests/metacall_duplicated_handle_test/CMakeLists.txt index 977c38726..35032c7c5 100644 --- a/source/tests/metacall_duplicated_handle_test/CMakeLists.txt +++ b/source/tests/metacall_duplicated_handle_test/CMakeLists.txt @@ -110,6 +110,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_duplicated_symbols_test/CMakeLists.txt b/source/tests/metacall_duplicated_symbols_test/CMakeLists.txt index 8ad6ff0c3..c5612d965 100644 --- a/source/tests/metacall_duplicated_symbols_test/CMakeLists.txt +++ b/source/tests/metacall_duplicated_symbols_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_dynlink_path_test/CMakeLists.txt b/source/tests/metacall_dynlink_path_test/CMakeLists.txt index 70537e13e..c1c9a76c4 100644 --- a/source/tests/metacall_dynlink_path_test/CMakeLists.txt +++ b/source/tests/metacall_dynlink_path_test/CMakeLists.txt @@ -111,6 +111,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_dynlink_path_test/source/metacall_dynlink_path_test.cpp b/source/tests/metacall_dynlink_path_test/source/metacall_dynlink_path_test.cpp index ac6239501..a989448f4 100644 --- a/source/tests/metacall_dynlink_path_test/source/metacall_dynlink_path_test.cpp +++ b/source/tests/metacall_dynlink_path_test/source/metacall_dynlink_path_test.cpp @@ -33,7 +33,7 @@ TEST_F(metacall_dynlink_path_test, DefaultConstructor) { metacall_print_info(); - dynlink_library_path_str path; + dynlink_path path; const char name[] = "metacall" #if (!defined(NDEBUG) || defined(DEBUG) || defined(_DEBUG) || defined(__DEBUG) || defined(__DEBUG__)) diff --git a/source/tests/metacall_ext_test/CMakeLists.txt b/source/tests/metacall_ext_test/CMakeLists.txt index c7df0805a..3c6b98698 100644 --- a/source/tests/metacall_ext_test/CMakeLists.txt +++ b/source/tests/metacall_ext_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_file_fail_test/CMakeLists.txt b/source/tests/metacall_file_fail_test/CMakeLists.txt index fb4c65e7b..ab6236fe1 100644 --- a/source/tests/metacall_file_fail_test/CMakeLists.txt +++ b/source/tests/metacall_file_fail_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_file_glob_test/CMakeLists.txt b/source/tests/metacall_file_glob_test/CMakeLists.txt index b5479a0f3..ffc5a1c27 100644 --- a/source/tests/metacall_file_glob_test/CMakeLists.txt +++ b/source/tests/metacall_file_glob_test/CMakeLists.txt @@ -119,6 +119,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_file_test/CMakeLists.txt b/source/tests/metacall_file_test/CMakeLists.txt index 7be85a2a6..9dd2a4fb0 100644 --- a/source/tests/metacall_file_test/CMakeLists.txt +++ b/source/tests/metacall_file_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_fork_test/CMakeLists.txt b/source/tests/metacall_fork_test/CMakeLists.txt index 47d389592..90c96bdef 100644 --- a/source/tests/metacall_fork_test/CMakeLists.txt +++ b/source/tests/metacall_fork_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -128,7 +137,7 @@ add_test(NAME ${target} # add_dependencies(${target} - funchook_detour + plthook_detour ) # diff --git a/source/tests/metacall_fork_test/source/metacall_fork_test.cpp b/source/tests/metacall_fork_test/source/metacall_fork_test.cpp index 2b288b12f..0f34b6bd7 100644 --- a/source/tests/metacall_fork_test/source/metacall_fork_test.cpp +++ b/source/tests/metacall_fork_test/source/metacall_fork_test.cpp @@ -115,7 +115,7 @@ pid_t fork() } else if (result == RTL_CLONE_CHILD) { - /* fix stdio */ + /* Fix stdio */ AllocConsole(); return 0; } diff --git a/source/tests/metacall_function_test/CMakeLists.txt b/source/tests/metacall_function_test/CMakeLists.txt index 2584da52b..9ac6fe47d 100644 --- a/source/tests/metacall_function_test/CMakeLists.txt +++ b/source/tests/metacall_function_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_handle_export_test/CMakeLists.txt b/source/tests/metacall_handle_export_test/CMakeLists.txt index 762cb174b..fb1a70856 100644 --- a/source/tests/metacall_handle_export_test/CMakeLists.txt +++ b/source/tests/metacall_handle_export_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_handle_get_test/CMakeLists.txt b/source/tests/metacall_handle_get_test/CMakeLists.txt index 73178da78..c99af8c34 100644 --- a/source/tests/metacall_handle_get_test/CMakeLists.txt +++ b/source/tests/metacall_handle_get_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_init_fini_test/CMakeLists.txt b/source/tests/metacall_init_fini_test/CMakeLists.txt index bb1783bf3..c757cffb7 100644 --- a/source/tests/metacall_init_fini_test/CMakeLists.txt +++ b/source/tests/metacall_init_fini_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_initialize_destroy_multiple_node_test/CMakeLists.txt b/source/tests/metacall_initialize_destroy_multiple_node_test/CMakeLists.txt index 3d0c2ffde..9b06663fd 100644 --- a/source/tests/metacall_initialize_destroy_multiple_node_test/CMakeLists.txt +++ b/source/tests/metacall_initialize_destroy_multiple_node_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_initialize_destroy_multiple_test/CMakeLists.txt b/source/tests/metacall_initialize_destroy_multiple_test/CMakeLists.txt index 2de694d0a..3424ea881 100644 --- a/source/tests/metacall_initialize_destroy_multiple_test/CMakeLists.txt +++ b/source/tests/metacall_initialize_destroy_multiple_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_initialize_ex_test/CMakeLists.txt b/source/tests/metacall_initialize_ex_test/CMakeLists.txt index 94332f3b4..714d7ce5b 100644 --- a/source/tests/metacall_initialize_ex_test/CMakeLists.txt +++ b/source/tests/metacall_initialize_ex_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_initialize_test/CMakeLists.txt b/source/tests/metacall_initialize_test/CMakeLists.txt index f8b5b901a..e66bf472e 100644 --- a/source/tests/metacall_initialize_test/CMakeLists.txt +++ b/source/tests/metacall_initialize_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_inspect_test/CMakeLists.txt b/source/tests/metacall_inspect_test/CMakeLists.txt index ff5eaf740..8a97a0c8b 100644 --- a/source/tests/metacall_inspect_test/CMakeLists.txt +++ b/source/tests/metacall_inspect_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_integration_test/CMakeLists.txt b/source/tests/metacall_integration_test/CMakeLists.txt index 55b69ede2..bf2cc13b9 100644 --- a/source/tests/metacall_integration_test/CMakeLists.txt +++ b/source/tests/metacall_integration_test/CMakeLists.txt @@ -113,6 +113,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_invalid_loader_test/CMakeLists.txt b/source/tests/metacall_invalid_loader_test/CMakeLists.txt index 8186d9362..cef1167c5 100644 --- a/source/tests/metacall_invalid_loader_test/CMakeLists.txt +++ b/source/tests/metacall_invalid_loader_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_java_test/CMakeLists.txt b/source/tests/metacall_java_test/CMakeLists.txt index d9000eeb6..fb814afc1 100644 --- a/source/tests/metacall_java_test/CMakeLists.txt +++ b/source/tests/metacall_java_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_julia_test/CMakeLists.txt b/source/tests/metacall_julia_test/CMakeLists.txt index 32dc65a6d..0bfe22f23 100644 --- a/source/tests/metacall_julia_test/CMakeLists.txt +++ b/source/tests/metacall_julia_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_library_path_without_env_vars_test/CMakeLists.txt b/source/tests/metacall_library_path_without_env_vars_test/CMakeLists.txt index e38ecba46..33428a51b 100644 --- a/source/tests/metacall_library_path_without_env_vars_test/CMakeLists.txt +++ b/source/tests/metacall_library_path_without_env_vars_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_llvm_test/CMakeLists.txt b/source/tests/metacall_llvm_test/CMakeLists.txt index 76f79b68c..cbe63c93f 100644 --- a/source/tests/metacall_llvm_test/CMakeLists.txt +++ b/source/tests/metacall_llvm_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_load_configuration_fail_test/CMakeLists.txt b/source/tests/metacall_load_configuration_fail_test/CMakeLists.txt index 3a6293c6d..c49bf0e10 100644 --- a/source/tests/metacall_load_configuration_fail_test/CMakeLists.txt +++ b/source/tests/metacall_load_configuration_fail_test/CMakeLists.txt @@ -110,6 +110,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_load_configuration_node_python_test/CMakeLists.txt b/source/tests/metacall_load_configuration_node_python_test/CMakeLists.txt index f38f63ffb..6653f9010 100644 --- a/source/tests/metacall_load_configuration_node_python_test/CMakeLists.txt +++ b/source/tests/metacall_load_configuration_node_python_test/CMakeLists.txt @@ -115,6 +115,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_load_configuration_python_node_test/CMakeLists.txt b/source/tests/metacall_load_configuration_python_node_test/CMakeLists.txt index 5d1c09042..f8dd16c32 100644 --- a/source/tests/metacall_load_configuration_python_node_test/CMakeLists.txt +++ b/source/tests/metacall_load_configuration_python_node_test/CMakeLists.txt @@ -112,6 +112,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_load_configuration_relative_test/CMakeLists.txt b/source/tests/metacall_load_configuration_relative_test/CMakeLists.txt index 4cb9cfb73..a16c0c46f 100644 --- a/source/tests/metacall_load_configuration_relative_test/CMakeLists.txt +++ b/source/tests/metacall_load_configuration_relative_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_load_configuration_test/CMakeLists.txt b/source/tests/metacall_load_configuration_test/CMakeLists.txt index 52f0a339f..3c42adeb5 100644 --- a/source/tests/metacall_load_configuration_test/CMakeLists.txt +++ b/source/tests/metacall_load_configuration_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_load_memory_empty_test/CMakeLists.txt b/source/tests/metacall_load_memory_empty_test/CMakeLists.txt index 18371653f..b98f18bca 100644 --- a/source/tests/metacall_load_memory_empty_test/CMakeLists.txt +++ b/source/tests/metacall_load_memory_empty_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_load_memory_test/CMakeLists.txt b/source/tests/metacall_load_memory_test/CMakeLists.txt index 7e45abf25..9203a34ca 100644 --- a/source/tests/metacall_load_memory_test/CMakeLists.txt +++ b/source/tests/metacall_load_memory_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_logs_test/CMakeLists.txt b/source/tests/metacall_logs_test/CMakeLists.txt index 35386f0f7..2a56bf637 100644 --- a/source/tests/metacall_logs_test/CMakeLists.txt +++ b/source/tests/metacall_logs_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_lua_test/CMakeLists.txt b/source/tests/metacall_lua_test/CMakeLists.txt index b9b6a62c2..d356553b5 100644 --- a/source/tests/metacall_lua_test/CMakeLists.txt +++ b/source/tests/metacall_lua_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_map_await_test/CMakeLists.txt b/source/tests/metacall_map_await_test/CMakeLists.txt index b36cdee47..6b1df3e95 100644 --- a/source/tests/metacall_map_await_test/CMakeLists.txt +++ b/source/tests/metacall_map_await_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_map_test/CMakeLists.txt b/source/tests/metacall_map_test/CMakeLists.txt index 6022a8abd..b9d40bf14 100644 --- a/source/tests/metacall_map_test/CMakeLists.txt +++ b/source/tests/metacall_map_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_async_multiple_test/CMakeLists.txt b/source/tests/metacall_node_async_multiple_test/CMakeLists.txt index fe9cea8ae..77c1e4b31 100644 --- a/source/tests/metacall_node_async_multiple_test/CMakeLists.txt +++ b/source/tests/metacall_node_async_multiple_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_async_resources_test/CMakeLists.txt b/source/tests/metacall_node_async_resources_test/CMakeLists.txt index a3edb0a50..17e130e41 100644 --- a/source/tests/metacall_node_async_resources_test/CMakeLists.txt +++ b/source/tests/metacall_node_async_resources_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_async_test/CMakeLists.txt b/source/tests/metacall_node_async_test/CMakeLists.txt index 3a29a55a4..d58db6623 100644 --- a/source/tests/metacall_node_async_test/CMakeLists.txt +++ b/source/tests/metacall_node_async_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_await_chain_test/CMakeLists.txt b/source/tests/metacall_node_await_chain_test/CMakeLists.txt index 2b34facf9..52e4ab39e 100644 --- a/source/tests/metacall_node_await_chain_test/CMakeLists.txt +++ b/source/tests/metacall_node_await_chain_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_call_test/CMakeLists.txt b/source/tests/metacall_node_call_test/CMakeLists.txt index 361544791..c0a877d4d 100644 --- a/source/tests/metacall_node_call_test/CMakeLists.txt +++ b/source/tests/metacall_node_call_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_callback_test/CMakeLists.txt b/source/tests/metacall_node_callback_test/CMakeLists.txt index 2fa56024b..1ba50b637 100644 --- a/source/tests/metacall_node_callback_test/CMakeLists.txt +++ b/source/tests/metacall_node_callback_test/CMakeLists.txt @@ -108,6 +108,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_clear_mem_test/CMakeLists.txt b/source/tests/metacall_node_clear_mem_test/CMakeLists.txt index 249b9066b..d7f9e9124 100644 --- a/source/tests/metacall_node_clear_mem_test/CMakeLists.txt +++ b/source/tests/metacall_node_clear_mem_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_default_export_test/CMakeLists.txt b/source/tests/metacall_node_default_export_test/CMakeLists.txt index 56d39f320..c00958933 100644 --- a/source/tests/metacall_node_default_export_test/CMakeLists.txt +++ b/source/tests/metacall_node_default_export_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_event_loop_signal_test/CMakeLists.txt b/source/tests/metacall_node_event_loop_signal_test/CMakeLists.txt index dbb6410c1..cb3e4701c 100644 --- a/source/tests/metacall_node_event_loop_signal_test/CMakeLists.txt +++ b/source/tests/metacall_node_event_loop_signal_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_event_loop_test/CMakeLists.txt b/source/tests/metacall_node_event_loop_test/CMakeLists.txt index 805dd2a9b..d1d83d441 100644 --- a/source/tests/metacall_node_event_loop_test/CMakeLists.txt +++ b/source/tests/metacall_node_event_loop_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_exception_test/CMakeLists.txt b/source/tests/metacall_node_exception_test/CMakeLists.txt index 707e52942..1129b3145 100644 --- a/source/tests/metacall_node_exception_test/CMakeLists.txt +++ b/source/tests/metacall_node_exception_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_extension_test/CMakeLists.txt b/source/tests/metacall_node_extension_test/CMakeLists.txt index 1aac1018e..f56da937a 100644 --- a/source/tests/metacall_node_extension_test/CMakeLists.txt +++ b/source/tests/metacall_node_extension_test/CMakeLists.txt @@ -110,6 +110,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_extension_test/node_extension_test/source/node_extension_test_win32_delay_load.cpp b/source/tests/metacall_node_extension_test/node_extension_test/source/node_extension_test_win32_delay_load.cpp index a19afc563..fc968f846 100644 --- a/source/tests/metacall_node_extension_test/node_extension_test/source/node_extension_test_win32_delay_load.cpp +++ b/source/tests/metacall_node_extension_test/node_extension_test/source/node_extension_test_win32_delay_load.cpp @@ -29,6 +29,8 @@ #include #include +static const char node_library_name[] = NODEJS_LIBRARY_NAME; + static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo *info) { HMODULE m; @@ -38,7 +40,7 @@ static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo *info) return NULL; } - if (_stricmp(info->szDll, NODEJS_LIBRARY_NAME) != 0) + if (_stricmp(info->szDll, node_library_name) != 0) { return NULL; } diff --git a/source/tests/metacall_node_fail_env_var_test/CMakeLists.txt b/source/tests/metacall_node_fail_env_var_test/CMakeLists.txt index e8310a78c..ecd42051e 100644 --- a/source/tests/metacall_node_fail_env_var_test/CMakeLists.txt +++ b/source/tests/metacall_node_fail_env_var_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_fail_load_leak_test/CMakeLists.txt b/source/tests/metacall_node_fail_load_leak_test/CMakeLists.txt index aaed9e522..3b1cc5bc5 100644 --- a/source/tests/metacall_node_fail_load_leak_test/CMakeLists.txt +++ b/source/tests/metacall_node_fail_load_leak_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_fail_test/CMakeLists.txt b/source/tests/metacall_node_fail_test/CMakeLists.txt index 62fb239d4..2f46c9261 100644 --- a/source/tests/metacall_node_fail_test/CMakeLists.txt +++ b/source/tests/metacall_node_fail_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_inline_test/CMakeLists.txt b/source/tests/metacall_node_inline_test/CMakeLists.txt index af8f0c8b5..8f7c771f2 100644 --- a/source/tests/metacall_node_inline_test/CMakeLists.txt +++ b/source/tests/metacall_node_inline_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_multithread_deadlock_test/CMakeLists.txt b/source/tests/metacall_node_multithread_deadlock_test/CMakeLists.txt index 6f3f91f47..e09b97826 100644 --- a/source/tests/metacall_node_multithread_deadlock_test/CMakeLists.txt +++ b/source/tests/metacall_node_multithread_deadlock_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_native_code_test/CMakeLists.txt b/source/tests/metacall_node_native_code_test/CMakeLists.txt index 31b61509e..2f485938e 100644 --- a/source/tests/metacall_node_native_code_test/CMakeLists.txt +++ b/source/tests/metacall_node_native_code_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_port_await_test/CMakeLists.txt b/source/tests/metacall_node_port_await_test/CMakeLists.txt index c72587ba4..819a878a0 100644 --- a/source/tests/metacall_node_port_await_test/CMakeLists.txt +++ b/source/tests/metacall_node_port_await_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_port_c_lib_test/CMakeLists.txt b/source/tests/metacall_node_port_c_lib_test/CMakeLists.txt index 3c13cf6be..ab55d51e7 100644 --- a/source/tests/metacall_node_port_c_lib_test/CMakeLists.txt +++ b/source/tests/metacall_node_port_c_lib_test/CMakeLists.txt @@ -124,6 +124,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_port_rs_test/CMakeLists.txt b/source/tests/metacall_node_port_rs_test/CMakeLists.txt index 1f4f82043..57422785b 100644 --- a/source/tests/metacall_node_port_rs_test/CMakeLists.txt +++ b/source/tests/metacall_node_port_rs_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_port_test/CMakeLists.txt b/source/tests/metacall_node_port_test/CMakeLists.txt index 86dadd93d..97aa855b3 100644 --- a/source/tests/metacall_node_port_test/CMakeLists.txt +++ b/source/tests/metacall_node_port_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_python_async_after_destroy_test/CMakeLists.txt b/source/tests/metacall_node_python_async_after_destroy_test/CMakeLists.txt index 6388179f7..6c88f28d6 100644 --- a/source/tests/metacall_node_python_async_after_destroy_test/CMakeLists.txt +++ b/source/tests/metacall_node_python_async_after_destroy_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_python_await_extended_test/CMakeLists.txt b/source/tests/metacall_node_python_await_extended_test/CMakeLists.txt index e7576cb18..a82165e89 100644 --- a/source/tests/metacall_node_python_await_extended_test/CMakeLists.txt +++ b/source/tests/metacall_node_python_await_extended_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_python_await_test/CMakeLists.txt b/source/tests/metacall_node_python_await_test/CMakeLists.txt index 2edadbea7..3553dbc2c 100644 --- a/source/tests/metacall_node_python_await_test/CMakeLists.txt +++ b/source/tests/metacall_node_python_await_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_python_deadlock_test/CMakeLists.txt b/source/tests/metacall_node_python_deadlock_test/CMakeLists.txt index 4e1fb4b71..55bcbfed3 100644 --- a/source/tests/metacall_node_python_deadlock_test/CMakeLists.txt +++ b/source/tests/metacall_node_python_deadlock_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_python_exception_test/CMakeLists.txt b/source/tests/metacall_node_python_exception_test/CMakeLists.txt index f759a0b30..0d4b36869 100644 --- a/source/tests/metacall_node_python_exception_test/CMakeLists.txt +++ b/source/tests/metacall_node_python_exception_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_python_port_mock_test/CMakeLists.txt b/source/tests/metacall_node_python_port_mock_test/CMakeLists.txt index 105e401fc..cbe593374 100644 --- a/source/tests/metacall_node_python_port_mock_test/CMakeLists.txt +++ b/source/tests/metacall_node_python_port_mock_test/CMakeLists.txt @@ -112,6 +112,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_python_port_ruby_test/CMakeLists.txt b/source/tests/metacall_node_python_port_ruby_test/CMakeLists.txt index 06e1e46bb..6dfbd6c33 100644 --- a/source/tests/metacall_node_python_port_ruby_test/CMakeLists.txt +++ b/source/tests/metacall_node_python_port_ruby_test/CMakeLists.txt @@ -112,6 +112,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_python_ruby_test/CMakeLists.txt b/source/tests/metacall_node_python_ruby_test/CMakeLists.txt index a9756c091..b5e291433 100644 --- a/source/tests/metacall_node_python_ruby_test/CMakeLists.txt +++ b/source/tests/metacall_node_python_ruby_test/CMakeLists.txt @@ -118,6 +118,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_reentrant_test/CMakeLists.txt b/source/tests/metacall_node_reentrant_test/CMakeLists.txt index a4ec68f52..6dfff474f 100644 --- a/source/tests/metacall_node_reentrant_test/CMakeLists.txt +++ b/source/tests/metacall_node_reentrant_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_signal_handler_test/CMakeLists.txt b/source/tests/metacall_node_signal_handler_test/CMakeLists.txt index 16e7cbd5e..473ad45e5 100644 --- a/source/tests/metacall_node_signal_handler_test/CMakeLists.txt +++ b/source/tests/metacall_node_signal_handler_test/CMakeLists.txt @@ -115,6 +115,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_test/CMakeLists.txt b/source/tests/metacall_node_test/CMakeLists.txt index 238ccbd4c..7c08d7c10 100644 --- a/source/tests/metacall_node_test/CMakeLists.txt +++ b/source/tests/metacall_node_test/CMakeLists.txt @@ -108,6 +108,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_node_typescript_test/CMakeLists.txt b/source/tests/metacall_node_typescript_test/CMakeLists.txt index f0858d246..499baca66 100644 --- a/source/tests/metacall_node_typescript_test/CMakeLists.txt +++ b/source/tests/metacall_node_typescript_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -122,6 +131,7 @@ target_link_options(${target} add_test(NAME ${target} COMMAND $ + WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) # @@ -139,7 +149,6 @@ add_dependencies(${target} set_property(TEST ${target} PROPERTY LABELS ${target} - WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) include(TestEnvironmentVariables) diff --git a/source/tests/metacall_plugin_extension_destroy_order_test/CMakeLists.txt b/source/tests/metacall_plugin_extension_destroy_order_test/CMakeLists.txt index f11064599..0bf7f3989 100644 --- a/source/tests/metacall_plugin_extension_destroy_order_test/CMakeLists.txt +++ b/source/tests/metacall_plugin_extension_destroy_order_test/CMakeLists.txt @@ -118,6 +118,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_plugin_extension_invalid_path_test/CMakeLists.txt b/source/tests/metacall_plugin_extension_invalid_path_test/CMakeLists.txt index fc0d79660..6e5da526f 100644 --- a/source/tests/metacall_plugin_extension_invalid_path_test/CMakeLists.txt +++ b/source/tests/metacall_plugin_extension_invalid_path_test/CMakeLists.txt @@ -111,6 +111,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_plugin_extension_local_test/CMakeLists.txt b/source/tests/metacall_plugin_extension_local_test/CMakeLists.txt index 20f25e9fd..174628c0e 100644 --- a/source/tests/metacall_plugin_extension_local_test/CMakeLists.txt +++ b/source/tests/metacall_plugin_extension_local_test/CMakeLists.txt @@ -108,6 +108,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_plugin_extension_test/CMakeLists.txt b/source/tests/metacall_plugin_extension_test/CMakeLists.txt index a6eead001..ed506009f 100644 --- a/source/tests/metacall_plugin_extension_test/CMakeLists.txt +++ b/source/tests/metacall_plugin_extension_test/CMakeLists.txt @@ -108,6 +108,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_async_test/CMakeLists.txt b/source/tests/metacall_python_async_test/CMakeLists.txt index 3acc0f211..c329c7a31 100644 --- a/source/tests/metacall_python_async_test/CMakeLists.txt +++ b/source/tests/metacall_python_async_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_await_test/CMakeLists.txt b/source/tests/metacall_python_await_test/CMakeLists.txt index 767eda765..9c3403391 100644 --- a/source/tests/metacall_python_await_test/CMakeLists.txt +++ b/source/tests/metacall_python_await_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_builtins_test/CMakeLists.txt b/source/tests/metacall_python_builtins_test/CMakeLists.txt index d9ca104c3..698df7f4b 100644 --- a/source/tests/metacall_python_builtins_test/CMakeLists.txt +++ b/source/tests/metacall_python_builtins_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_callback_test/CMakeLists.txt b/source/tests/metacall_python_callback_test/CMakeLists.txt index 4f7a4e1b3..e576930fb 100644 --- a/source/tests/metacall_python_callback_test/CMakeLists.txt +++ b/source/tests/metacall_python_callback_test/CMakeLists.txt @@ -108,6 +108,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_dict_test/CMakeLists.txt b/source/tests/metacall_python_dict_test/CMakeLists.txt index 8cc1916d7..835a24fed 100644 --- a/source/tests/metacall_python_dict_test/CMakeLists.txt +++ b/source/tests/metacall_python_dict_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_exception_test/CMakeLists.txt b/source/tests/metacall_python_exception_test/CMakeLists.txt index 31109d355..e06790523 100644 --- a/source/tests/metacall_python_exception_test/CMakeLists.txt +++ b/source/tests/metacall_python_exception_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_fail_test/CMakeLists.txt b/source/tests/metacall_python_fail_test/CMakeLists.txt index fdf0097ed..d16a571d2 100644 --- a/source/tests/metacall_python_fail_test/CMakeLists.txt +++ b/source/tests/metacall_python_fail_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_gc_test/CMakeLists.txt b/source/tests/metacall_python_gc_test/CMakeLists.txt index dea0f4ae2..b72602434 100644 --- a/source/tests/metacall_python_gc_test/CMakeLists.txt +++ b/source/tests/metacall_python_gc_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_loader_port_test/CMakeLists.txt b/source/tests/metacall_python_loader_port_test/CMakeLists.txt index 82bfb7529..eed75ba06 100644 --- a/source/tests/metacall_python_loader_port_test/CMakeLists.txt +++ b/source/tests/metacall_python_loader_port_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_model_test/CMakeLists.txt b/source/tests/metacall_python_model_test/CMakeLists.txt index 59494beac..01475c8c8 100644 --- a/source/tests/metacall_python_model_test/CMakeLists.txt +++ b/source/tests/metacall_python_model_test/CMakeLists.txt @@ -118,6 +118,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_node_await_test/CMakeLists.txt b/source/tests/metacall_python_node_await_test/CMakeLists.txt index 9995c37e0..e2d89c8ff 100644 --- a/source/tests/metacall_python_node_await_test/CMakeLists.txt +++ b/source/tests/metacall_python_node_await_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_object_class_test/CMakeLists.txt b/source/tests/metacall_python_object_class_test/CMakeLists.txt index 475a515ca..f81c535ee 100644 --- a/source/tests/metacall_python_object_class_test/CMakeLists.txt +++ b/source/tests/metacall_python_object_class_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_open_test/CMakeLists.txt b/source/tests/metacall_python_open_test/CMakeLists.txt index ce067050d..32959b363 100644 --- a/source/tests/metacall_python_open_test/CMakeLists.txt +++ b/source/tests/metacall_python_open_test/CMakeLists.txt @@ -127,6 +127,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_pointer_test/CMakeLists.txt b/source/tests/metacall_python_pointer_test/CMakeLists.txt index 4beab7b92..fe6f4ee61 100644 --- a/source/tests/metacall_python_pointer_test/CMakeLists.txt +++ b/source/tests/metacall_python_pointer_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_port_callback_test/CMakeLists.txt b/source/tests/metacall_python_port_callback_test/CMakeLists.txt index 95ddf1ad7..bbf27070a 100644 --- a/source/tests/metacall_python_port_callback_test/CMakeLists.txt +++ b/source/tests/metacall_python_port_callback_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_port_https_test/CMakeLists.txt b/source/tests/metacall_python_port_https_test/CMakeLists.txt index fa4127119..1f1335666 100644 --- a/source/tests/metacall_python_port_https_test/CMakeLists.txt +++ b/source/tests/metacall_python_port_https_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_port_import_test/CMakeLists.txt b/source/tests/metacall_python_port_import_test/CMakeLists.txt index 8d1d94f1c..051f05953 100644 --- a/source/tests/metacall_python_port_import_test/CMakeLists.txt +++ b/source/tests/metacall_python_port_import_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_port_pointer_test/CMakeLists.txt b/source/tests/metacall_python_port_pointer_test/CMakeLists.txt index 463a4e5b6..2c4133672 100644 --- a/source/tests/metacall_python_port_pointer_test/CMakeLists.txt +++ b/source/tests/metacall_python_port_pointer_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_port_test/CMakeLists.txt b/source/tests/metacall_python_port_test/CMakeLists.txt index 431379d4a..a4179b7f2 100644 --- a/source/tests/metacall_python_port_test/CMakeLists.txt +++ b/source/tests/metacall_python_port_test/CMakeLists.txt @@ -109,6 +109,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_reentrant_test/CMakeLists.txt b/source/tests/metacall_python_reentrant_test/CMakeLists.txt index 8f6a82e07..ab29592ef 100644 --- a/source/tests/metacall_python_reentrant_test/CMakeLists.txt +++ b/source/tests/metacall_python_reentrant_test/CMakeLists.txt @@ -110,6 +110,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_relative_path_test/CMakeLists.txt b/source/tests/metacall_python_relative_path_test/CMakeLists.txt index 2a5ad0ff8..22cae4f28 100644 --- a/source/tests/metacall_python_relative_path_test/CMakeLists.txt +++ b/source/tests/metacall_python_relative_path_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_test/CMakeLists.txt b/source/tests/metacall_python_test/CMakeLists.txt index 5fb1bec57..6f89617e3 100644 --- a/source/tests/metacall_python_test/CMakeLists.txt +++ b/source/tests/metacall_python_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_varargs_test/CMakeLists.txt b/source/tests/metacall_python_varargs_test/CMakeLists.txt index bae80e62d..f8636d21e 100644 --- a/source/tests/metacall_python_varargs_test/CMakeLists.txt +++ b/source/tests/metacall_python_varargs_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_without_env_vars_test/CMakeLists.txt b/source/tests/metacall_python_without_env_vars_test/CMakeLists.txt index 9e871cf89..3aca8756e 100644 --- a/source/tests/metacall_python_without_env_vars_test/CMakeLists.txt +++ b/source/tests/metacall_python_without_env_vars_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_python_without_functions_test/CMakeLists.txt b/source/tests/metacall_python_without_functions_test/CMakeLists.txt index a4f92966a..e2092380e 100644 --- a/source/tests/metacall_python_without_functions_test/CMakeLists.txt +++ b/source/tests/metacall_python_without_functions_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_reinitialize_test/CMakeLists.txt b/source/tests/metacall_reinitialize_test/CMakeLists.txt index 73beda512..c1adf593e 100644 --- a/source/tests/metacall_reinitialize_test/CMakeLists.txt +++ b/source/tests/metacall_reinitialize_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_reload_functions_test/CMakeLists.txt b/source/tests/metacall_reload_functions_test/CMakeLists.txt index 4398e0a2d..8d7682d2c 100644 --- a/source/tests/metacall_reload_functions_test/CMakeLists.txt +++ b/source/tests/metacall_reload_functions_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_return_monad_test/CMakeLists.txt b/source/tests/metacall_return_monad_test/CMakeLists.txt index 54f90028d..bcf5ad5c5 100644 --- a/source/tests/metacall_return_monad_test/CMakeLists.txt +++ b/source/tests/metacall_return_monad_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_rpc_test/CMakeLists.txt b/source/tests/metacall_rpc_test/CMakeLists.txt index 091cd4196..04925f1f1 100644 --- a/source/tests/metacall_rpc_test/CMakeLists.txt +++ b/source/tests/metacall_rpc_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_rpc_test/source/test.js b/source/tests/metacall_rpc_test/source/test.js index 42c12bd33..15d5a9dac 100644 --- a/source/tests/metacall_rpc_test/source/test.js +++ b/source/tests/metacall_rpc_test/source/test.js @@ -62,7 +62,7 @@ process.on('uncaughtException', killTest); if (ready === false) { killTest('Timeout reached, server is not ready'); } - }, 10000); + }, 60000); while (ready !== true) { try { diff --git a/source/tests/metacall_ruby_fail_empty_test/CMakeLists.txt b/source/tests/metacall_ruby_fail_empty_test/CMakeLists.txt index 4503b7df1..a480292e1 100644 --- a/source/tests/metacall_ruby_fail_empty_test/CMakeLists.txt +++ b/source/tests/metacall_ruby_fail_empty_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_ruby_fail_test/CMakeLists.txt b/source/tests/metacall_ruby_fail_test/CMakeLists.txt index 7211d396e..a34d4318c 100644 --- a/source/tests/metacall_ruby_fail_test/CMakeLists.txt +++ b/source/tests/metacall_ruby_fail_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_ruby_object_class_test/CMakeLists.txt b/source/tests/metacall_ruby_object_class_test/CMakeLists.txt index 50908e439..c4d2ad9b3 100644 --- a/source/tests/metacall_ruby_object_class_test/CMakeLists.txt +++ b/source/tests/metacall_ruby_object_class_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_ruby_parser_integration_test/CMakeLists.txt b/source/tests/metacall_ruby_parser_integration_test/CMakeLists.txt index 49a899ecf..ecd892ffb 100644 --- a/source/tests/metacall_ruby_parser_integration_test/CMakeLists.txt +++ b/source/tests/metacall_ruby_parser_integration_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_ruby_rails_integration_test/CMakeLists.txt b/source/tests/metacall_ruby_rails_integration_test/CMakeLists.txt index a2afac751..6559f627a 100644 --- a/source/tests/metacall_ruby_rails_integration_test/CMakeLists.txt +++ b/source/tests/metacall_ruby_rails_integration_test/CMakeLists.txt @@ -114,6 +114,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_ruby_test/CMakeLists.txt b/source/tests/metacall_ruby_test/CMakeLists.txt index 41d084aad..163c170a6 100644 --- a/source/tests/metacall_ruby_test/CMakeLists.txt +++ b/source/tests/metacall_ruby_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_rust_class_test/CMakeLists.txt b/source/tests/metacall_rust_class_test/CMakeLists.txt index dd529756f..28a7f1dac 100644 --- a/source/tests/metacall_rust_class_test/CMakeLists.txt +++ b/source/tests/metacall_rust_class_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_rust_load_from_mem_test/CMakeLists.txt b/source/tests/metacall_rust_load_from_mem_test/CMakeLists.txt index efcfafdcb..026115ba3 100644 --- a/source/tests/metacall_rust_load_from_mem_test/CMakeLists.txt +++ b/source/tests/metacall_rust_load_from_mem_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_rust_load_from_package_class_test/CMakeLists.txt b/source/tests/metacall_rust_load_from_package_class_test/CMakeLists.txt index 33b0b2909..0f98b613a 100644 --- a/source/tests/metacall_rust_load_from_package_class_test/CMakeLists.txt +++ b/source/tests/metacall_rust_load_from_package_class_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_rust_load_from_package_dep_test/CMakeLists.txt b/source/tests/metacall_rust_load_from_package_dep_test/CMakeLists.txt index 3f9d02f86..7ac9429cf 100644 --- a/source/tests/metacall_rust_load_from_package_dep_test/CMakeLists.txt +++ b/source/tests/metacall_rust_load_from_package_dep_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_rust_load_from_package_test/CMakeLists.txt b/source/tests/metacall_rust_load_from_package_test/CMakeLists.txt index e46e552dd..a5aaabbe6 100644 --- a/source/tests/metacall_rust_load_from_package_test/CMakeLists.txt +++ b/source/tests/metacall_rust_load_from_package_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_rust_test/CMakeLists.txt b/source/tests/metacall_rust_test/CMakeLists.txt index 9b0cfc8b3..31434b1be 100644 --- a/source/tests/metacall_rust_test/CMakeLists.txt +++ b/source/tests/metacall_rust_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt b/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt index 67732e310..3a98235b1 100644 --- a/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt +++ b/source/tests/metacall_sandbox_plugin_test/CMakeLists.txt @@ -123,6 +123,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_test/CMakeLists.txt b/source/tests/metacall_test/CMakeLists.txt index 4d75fe9b7..8751e1fe0 100644 --- a/source/tests/metacall_test/CMakeLists.txt +++ b/source/tests/metacall_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_typescript_call_map_test/CMakeLists.txt b/source/tests/metacall_typescript_call_map_test/CMakeLists.txt index 46f491804..4005debcf 100644 --- a/source/tests/metacall_typescript_call_map_test/CMakeLists.txt +++ b/source/tests/metacall_typescript_call_map_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -122,6 +131,7 @@ target_link_options(${target} add_test(NAME ${target} COMMAND $ + WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) # @@ -139,7 +149,6 @@ add_dependencies(${target} set_property(TEST ${target} PROPERTY LABELS ${target} - WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) include(TestEnvironmentVariables) diff --git a/source/tests/metacall_typescript_jsx_default_test/CMakeLists.txt b/source/tests/metacall_typescript_jsx_default_test/CMakeLists.txt index a41409a5b..32674e550 100644 --- a/source/tests/metacall_typescript_jsx_default_test/CMakeLists.txt +++ b/source/tests/metacall_typescript_jsx_default_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_typescript_node_test/CMakeLists.txt b/source/tests/metacall_typescript_node_test/CMakeLists.txt index 95954f202..9dbd14de9 100644 --- a/source/tests/metacall_typescript_node_test/CMakeLists.txt +++ b/source/tests/metacall_typescript_node_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -122,6 +131,7 @@ target_link_options(${target} add_test(NAME ${target} COMMAND $ + WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) # @@ -139,7 +149,6 @@ add_dependencies(${target} set_property(TEST ${target} PROPERTY LABELS ${target} - WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) include(TestEnvironmentVariables) diff --git a/source/tests/metacall_typescript_require_test/CMakeLists.txt b/source/tests/metacall_typescript_require_test/CMakeLists.txt index 2e1e327bd..d4d51e466 100644 --- a/source/tests/metacall_typescript_require_test/CMakeLists.txt +++ b/source/tests/metacall_typescript_require_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -122,6 +131,7 @@ target_link_options(${target} add_test(NAME ${target} COMMAND $ + WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) # @@ -139,7 +149,6 @@ add_dependencies(${target} set_property(TEST ${target} PROPERTY LABELS ${target} - WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) include(TestEnvironmentVariables) diff --git a/source/tests/metacall_typescript_test/CMakeLists.txt b/source/tests/metacall_typescript_test/CMakeLists.txt index 1ad8d87d3..9af3378eb 100644 --- a/source/tests/metacall_typescript_test/CMakeLists.txt +++ b/source/tests/metacall_typescript_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -122,6 +131,7 @@ target_link_options(${target} add_test(NAME ${target} COMMAND $ + WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) # @@ -139,7 +149,6 @@ add_dependencies(${target} set_property(TEST ${target} PROPERTY LABELS ${target} - WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) include(TestEnvironmentVariables) diff --git a/source/tests/metacall_typescript_tsx_loop_fail_test/CMakeLists.txt b/source/tests/metacall_typescript_tsx_loop_fail_test/CMakeLists.txt index 59789903b..ca6465387 100644 --- a/source/tests/metacall_typescript_tsx_loop_fail_test/CMakeLists.txt +++ b/source/tests/metacall_typescript_tsx_loop_fail_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_typescript_tsx_test/CMakeLists.txt b/source/tests/metacall_typescript_tsx_test/CMakeLists.txt index b6732071c..53682fa43 100644 --- a/source/tests/metacall_typescript_tsx_test/CMakeLists.txt +++ b/source/tests/metacall_typescript_tsx_test/CMakeLists.txt @@ -107,6 +107,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_version_test/CMakeLists.txt b/source/tests/metacall_version_test/CMakeLists.txt index 8b3465541..4d93e4fec 100644 --- a/source/tests/metacall_version_test/CMakeLists.txt +++ b/source/tests/metacall_version_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_wasm_python_port_test/CMakeLists.txt b/source/tests/metacall_wasm_python_port_test/CMakeLists.txt index 09c1efe10..7233aa579 100644 --- a/source/tests/metacall_wasm_python_port_test/CMakeLists.txt +++ b/source/tests/metacall_wasm_python_port_test/CMakeLists.txt @@ -108,6 +108,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/metacall_wasm_test/CMakeLists.txt b/source/tests/metacall_wasm_test/CMakeLists.txt index 5aeb8ca0a..6ceca6692 100644 --- a/source/tests/metacall_wasm_test/CMakeLists.txt +++ b/source/tests/metacall_wasm_test/CMakeLists.txt @@ -106,6 +106,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/portability_path_test/CMakeLists.txt b/source/tests/portability_path_test/CMakeLists.txt index 37274fd9e..b95e32718 100644 --- a/source/tests/portability_path_test/CMakeLists.txt +++ b/source/tests/portability_path_test/CMakeLists.txt @@ -101,6 +101,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/portability_path_test/source/portability_path_test.cpp b/source/tests/portability_path_test/source/portability_path_test.cpp index c8b4dccc5..15534b235 100644 --- a/source/tests/portability_path_test/source/portability_path_test.cpp +++ b/source/tests/portability_path_test/source/portability_path_test.cpp @@ -33,7 +33,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_module_name) size_t size = portability_path_get_module_name(base, sizeof(base), extension, sizeof(extension), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -48,7 +48,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_module_name_without size_t size = portability_path_get_module_name(base, sizeof(base), extension, sizeof(extension), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -63,7 +63,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_module_name_with_ra size_t size = portability_path_get_module_name(base, sizeof(base), extension, sizeof(extension), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -77,7 +77,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_name) size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -91,7 +91,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_end_dot) size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -105,7 +105,21 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_without_dot) size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); + EXPECT_EQ((size_t)size, (size_t)sizeof(result)); + EXPECT_EQ((char)'\0', (char)result[size - 1]); +} + +TEST_F(portability_path_test, portability_path_test_path_get_name_only_separator_dot) +{ + static const char base[] = "/."; + static const char result[] = ""; + + string_name name; + + size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); + + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -119,7 +133,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_only_dot) size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -133,7 +147,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_two_dots) size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -147,7 +161,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_three_dots) size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -161,7 +175,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_only_extension size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -175,7 +189,7 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_double_extensi size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -189,7 +203,21 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_triple_extensi size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); - EXPECT_EQ((int)0, (int)strcmp(name, result)); + EXPECT_STREQ(name, result); + EXPECT_EQ((size_t)size, (size_t)sizeof(result)); + EXPECT_EQ((char)'\0', (char)result[size - 1]); +} + +TEST_F(portability_path_test, portability_path_test_path_get_name_nullchar) +{ + static const char base[] = "/home/yeet/.nvm/versions/node/v18.20.3/bin/node"; + static const char result[] = "node"; + + string_name name; + + size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); + + EXPECT_STREQ(name, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -203,7 +231,7 @@ TEST_F(portability_path_test, portability_path_test_get_path_of_path) size_t size = portability_path_get_directory(base, sizeof(base), path, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(path, result)); + EXPECT_STREQ(path, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -217,7 +245,7 @@ TEST_F(portability_path_test, portability_path_test_get_path_of_filepath) size_t size = portability_path_get_directory(base, sizeof(base), path, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(path, result)); + EXPECT_STREQ(path, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -232,7 +260,7 @@ TEST_F(portability_path_test, portability_path_test_get_relative) size_t size = portability_path_get_relative(base, sizeof(base), path, sizeof(path), relative, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(relative, result)); + EXPECT_STREQ(relative, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -247,7 +275,7 @@ TEST_F(portability_path_test, portability_path_test_get_relative_fail) size_t size = portability_path_get_relative(base, sizeof(base), path, sizeof(path), relative, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(relative, result)); + EXPECT_STREQ(relative, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -262,7 +290,7 @@ TEST_F(portability_path_test, portability_path_test_join_none_slash) size_t size = portability_path_join(left, sizeof(left), right, sizeof(right), join, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(join, result)); + EXPECT_STREQ(join, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -277,7 +305,7 @@ TEST_F(portability_path_test, portability_path_test_join_left_slash) size_t size = portability_path_join(left, sizeof(left), right, sizeof(right), join, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(join, result)); + EXPECT_STREQ(join, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -292,7 +320,7 @@ TEST_F(portability_path_test, portability_path_test_join_right_slash) size_t size = portability_path_join(left, sizeof(left), right, sizeof(right), join, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(join, result)); + EXPECT_STREQ(join, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -307,7 +335,7 @@ TEST_F(portability_path_test, portability_path_test_join_both_slash) size_t size = portability_path_join(left, sizeof(left), right, sizeof(right), join, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(join, result)); + EXPECT_STREQ(join, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -322,7 +350,7 @@ TEST_F(portability_path_test, portability_path_test_join_left_empty) size_t size = portability_path_join(left, sizeof(left), right, sizeof(right), join, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(join, result)); + EXPECT_STREQ(join, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -337,7 +365,7 @@ TEST_F(portability_path_test, portability_path_test_join_right_empty) size_t size = portability_path_join(left, sizeof(left), right, sizeof(right), join, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(join, result)); + EXPECT_STREQ(join, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -352,7 +380,7 @@ TEST_F(portability_path_test, portability_path_test_join_right_empty_non_slash) size_t size = portability_path_join(left, sizeof(left), right, sizeof(right), join, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(join, result)); + EXPECT_STREQ(join, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -367,7 +395,7 @@ TEST_F(portability_path_test, portability_path_test_join_both_empty) size_t size = portability_path_join(left, sizeof(left), right, sizeof(right), join, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(join, result)); + EXPECT_STREQ(join, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -381,7 +409,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_begin_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -395,7 +423,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_begin_double_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -409,7 +437,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_begin_many_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -423,7 +451,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_begin_many_double_ size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -437,7 +465,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_begin_dot_non_slas size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -451,7 +479,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_begin_many_dot_non size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -465,7 +493,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_begin_invalid) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -479,7 +507,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_middle_double_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -493,7 +521,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_middle_double_dot_ size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -507,7 +535,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_middle_double_dot_ size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -521,7 +549,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_middle_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -535,7 +563,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_middle_mixed_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -549,7 +577,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_end_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -563,7 +591,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_end_double_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -577,7 +605,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_end_mixed_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -591,7 +619,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_absolute_end_mixed size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -605,7 +633,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_absolute_end_dot) size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -619,7 +647,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_relative_begin_end size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } @@ -633,7 +661,7 @@ TEST_F(portability_path_test, portability_path_test_canonical_absolute_end_many_ size_t size = portability_path_canonical(path, sizeof(path), canonical, PATH_SIZE); - EXPECT_EQ((int)0, (int)strcmp(canonical, result)); + EXPECT_STREQ(canonical, result); EXPECT_EQ((size_t)size, (size_t)sizeof(result)); EXPECT_EQ((char)'\0', (char)result[size - 1]); } diff --git a/source/tests/preprocessor_test/CMakeLists.txt b/source/tests/preprocessor_test/CMakeLists.txt index 68470eab2..b96a63903 100644 --- a/source/tests/preprocessor_test/CMakeLists.txt +++ b/source/tests/preprocessor_test/CMakeLists.txt @@ -102,6 +102,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/rb_loader_parser_test/CMakeLists.txt b/source/tests/rb_loader_parser_test/CMakeLists.txt index 4e6162aa5..dac449a56 100644 --- a/source/tests/rb_loader_parser_test/CMakeLists.txt +++ b/source/tests/rb_loader_parser_test/CMakeLists.txt @@ -121,6 +121,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/reflect_function_test/CMakeLists.txt b/source/tests/reflect_function_test/CMakeLists.txt index 9beb3781a..fd1875cd3 100644 --- a/source/tests/reflect_function_test/CMakeLists.txt +++ b/source/tests/reflect_function_test/CMakeLists.txt @@ -115,6 +115,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/reflect_metadata_test/CMakeLists.txt b/source/tests/reflect_metadata_test/CMakeLists.txt index 37e635bc6..33497b513 100644 --- a/source/tests/reflect_metadata_test/CMakeLists.txt +++ b/source/tests/reflect_metadata_test/CMakeLists.txt @@ -115,6 +115,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/reflect_object_class_test/CMakeLists.txt b/source/tests/reflect_object_class_test/CMakeLists.txt index 77f837183..3a74590dc 100644 --- a/source/tests/reflect_object_class_test/CMakeLists.txt +++ b/source/tests/reflect_object_class_test/CMakeLists.txt @@ -115,6 +115,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/reflect_scope_test/CMakeLists.txt b/source/tests/reflect_scope_test/CMakeLists.txt index 0a4bd718c..83990f235 100644 --- a/source/tests/reflect_scope_test/CMakeLists.txt +++ b/source/tests/reflect_scope_test/CMakeLists.txt @@ -115,6 +115,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/reflect_value_cast_test/CMakeLists.txt b/source/tests/reflect_value_cast_test/CMakeLists.txt index 46e51f3ae..4b28d3a1a 100644 --- a/source/tests/reflect_value_cast_test/CMakeLists.txt +++ b/source/tests/reflect_value_cast_test/CMakeLists.txt @@ -121,6 +121,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/tests/serial_test/CMakeLists.txt b/source/tests/serial_test/CMakeLists.txt index 8b32df06a..12356bc11 100644 --- a/source/tests/serial_test/CMakeLists.txt +++ b/source/tests/serial_test/CMakeLists.txt @@ -120,6 +120,15 @@ target_compile_options(${target} ${DEFAULT_COMPILE_OPTIONS} ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # diff --git a/source/threading/include/threading/threading_atomic_ref_count.h b/source/threading/include/threading/threading_atomic_ref_count.h index 165ef565c..8a1dc1cc4 100644 --- a/source/threading/include/threading/threading_atomic_ref_count.h +++ b/source/threading/include/threading/threading_atomic_ref_count.h @@ -46,7 +46,7 @@ extern "C" { /* -- Member Data -- */ -struct threading_atomic_ref_count_type +typedef struct { #if defined(__THREAD_SANITIZER__) uintmax_t count; @@ -54,11 +54,11 @@ struct threading_atomic_ref_count_type #else atomic_uintmax_t count; #endif -}; +} threading_atomic_ref_count_type; /* -- Type Definitions -- */ -typedef struct threading_atomic_ref_count_type *threading_atomic_ref_count; +typedef threading_atomic_ref_count_type *threading_atomic_ref_count; /* -- Methods -- */ diff --git a/tools/metacall-configure.sh b/tools/metacall-configure.sh index 0360f472f..7847a0d34 100755 --- a/tools/metacall-configure.sh +++ b/tools/metacall-configure.sh @@ -29,6 +29,7 @@ BUILD_NETCORE=0 BUILD_NETCORE2=0 BUILD_NETCORE5=0 BUILD_NETCORE7=0 +BUILD_NETCORE8=0 BUILD_V8=0 BUILD_NODEJS=0 BUILD_TYPESCRIPT=0 @@ -112,6 +113,10 @@ sub_options() { echo "Build with netcore 7 support" BUILD_NETCORE7=1 fi + if [ "$option" = 'netcore8' ]; then + echo "Build with netcore 8 support" + BUILD_NETCORE8=1 + fi if [ "$option" = 'v8' ]; then echo "Build with v8 support" BUILD_V8=1 @@ -318,6 +323,21 @@ sub_configure() { fi fi + # NetCore 8 + if [ $BUILD_NETCORE8 = 1 ]; then + BUILD_STRING="$BUILD_STRING \ + -DOPTION_BUILD_LOADERS_CS=On \ + -DDOTNET_CORE_PATH=`sub_find_dotnet_runtime 8`" + + if [ $BUILD_SCRIPTS = 1 ]; then + BUILD_STRING="$BUILD_STRING -DOPTION_BUILD_SCRIPTS_CS=On" + fi + + if [ $BUILD_PORTS = 1 ]; then + BUILD_STRING="$BUILD_STRING -DOPTION_BUILD_PORTS_CS=On" + fi + fi + # V8 if [ $BUILD_V8 = 1 ]; then BUILD_STRING="$BUILD_STRING -DOPTION_BUILD_LOADERS_JS=On" @@ -545,6 +565,7 @@ sub_help() { echo " netcore2: build with netcore 2 support" echo " netcore5: build with netcore 5 support" echo " netcore7: build with netcore 7 support" + echo " netcore8: build with netcore 8 support" echo " v8: build with v8 support" echo " nodejs: build with nodejs support" echo " typescript: build with typescript support" diff --git a/tools/metacall-environment.ps1 b/tools/metacall-environment.ps1 index 8d60574a7..72ce3659b 100755 --- a/tools/metacall-environment.ps1 +++ b/tools/metacall-environment.ps1 @@ -310,9 +310,6 @@ function Configure { if ("$var" -eq 'rapidjson') { Write-Output "rapidjson selected" } - if ("$var" -eq 'funchook') { - Write-Output "funchook selected" - } if (("$var" -eq 'v8') -or ("$var" -eq 'v8rep54')) { Write-Output "v8 selected" } @@ -387,7 +384,6 @@ function Help { Write-Output " netcore2" Write-Output " netcore5" Write-Output " rapidjson" - Write-Output " funchook" Write-Output " v8" Write-Output " v8rep51" Write-Output " v8rep54" diff --git a/tools/metacall-environment.sh b/tools/metacall-environment.sh index 5735bc28a..b24476443 100755 --- a/tools/metacall-environment.sh +++ b/tools/metacall-environment.sh @@ -30,11 +30,11 @@ INSTALL_BASE=1 INSTALL_PYTHON=0 INSTALL_RUBY=0 INSTALL_RAPIDJSON=0 -INSTALL_FUNCHOOK=0 INSTALL_NETCORE=0 INSTALL_NETCORE2=0 INSTALL_NETCORE5=0 INSTALL_NETCORE7=0 +INSTALL_NETCORE8=0 INSTALL_V8=0 INSTALL_V8REPO=0 INSTALL_V8REPO58=0 @@ -250,9 +250,9 @@ sub_rapidjson(){ cd $ROOT_DIR if [ "${OPERATIVE_SYSTEM}" = "Linux" ]; then - git clone https://github.com/miloyip/rapidjson.git + git clone https://github.com/Tencent/rapidjson.git cd rapidjson - git checkout ab1842a2dae061284c0a62dca1cc6d5e7e37e346 + git checkout 24b5e7a8b27f42fa16b96fc70aade9106cf7102f mkdir build cd build cmake -DRAPIDJSON_BUILD_DOC=Off -DRAPIDJSON_BUILD_EXAMPLES=Off -DRAPIDJSON_BUILD_TESTS=Off .. @@ -262,12 +262,6 @@ sub_rapidjson(){ fi } -# FuncHook -sub_funchook(){ - echo "configure funchook" - -} - # NetCore sub_netcore(){ echo "configure netcore" @@ -394,6 +388,20 @@ sub_netcore7(){ fi } +# NetCore 8 +sub_netcore8(){ + echo "configure netcore 8" + cd $ROOT_DIR + + if [ "${OPERATIVE_SYSTEM}" = "Linux" ]; then + if [ "${LINUX_DISTRO}" = "debian" ] || [ "${LINUX_DISTRO}" = "ubuntu" ]; then + wget -O - https://dot.net/v1/dotnet-install.sh | $SUDO_CMD bash -s -- --version 8.0.408 --install-dir /usr/local/bin + elif [ "${LINUX_DISTRO}" = "alpine" ]; then + $SUDO_CMD apk add --no-cache dotnet8-sdk + fi + fi +} + # V8 Repository sub_v8repo(){ echo "configure v8 from repository" @@ -917,9 +925,6 @@ sub_install(){ if [ $INSTALL_RAPIDJSON = 1 ]; then sub_rapidjson fi - if [ $INSTALL_FUNCHOOK = 1 ]; then - sub_funchook - fi if [ $INSTALL_NETCORE = 1 ]; then sub_netcore fi @@ -932,6 +937,9 @@ sub_install(){ if [ $INSTALL_NETCORE7 = 1 ]; then sub_netcore7 fi + if [ $INSTALL_NETCORE8 = 1 ]; then + sub_netcore8 + fi if [ $INSTALL_V8 = 1 ]; then sub_v8 fi @@ -1035,14 +1043,14 @@ sub_options(){ echo "netcore 7 selected" INSTALL_NETCORE7=1 fi + if [ "$option" = 'netcore8' ]; then + echo "netcore 8 selected" + INSTALL_NETCORE8=1 + fi if [ "$option" = 'rapidjson' ]; then echo "rapidjson selected" INSTALL_RAPIDJSON=1 fi - if [ "$option" = 'funchook' ]; then - echo "funchook selected" - INSTALL_FUNCHOOK=1 - fi if [ "$option" = 'v8' ] || [ "$option" = 'v8rep54' ]; then echo "v8 selected" INSTALL_V8REPO=1 @@ -1148,8 +1156,8 @@ sub_help() { echo " netcore2" echo " netcore5" echo " netcore7" + echo " netcore8" echo " rapidjson" - echo " funchook" echo " v8" echo " v8rep51" echo " v8rep54" diff --git a/tools/metacall-runtime.sh b/tools/metacall-runtime.sh index aea5bab16..9ef4afba2 100755 --- a/tools/metacall-runtime.sh +++ b/tools/metacall-runtime.sh @@ -170,6 +170,15 @@ sub_netcore7(){ sub_apt_install_hold dotnet-runtime-7.0=7.0.5-1 } +# NetCore 8 +sub_netcore8(){ + echo "configure netcore 8" + cd $ROOT_DIR + + # Install NET Core Runtime 8.x + wget -O - https://dot.net/v1/dotnet-install.sh | $SUDO_CMD bash -s -- --version 8.0.408 --install-dir /usr/local/bin --runtime dotnet +} + # V8 sub_v8(){ echo "configure v8" diff --git a/tools/metacall-sanitizer.sh b/tools/metacall-sanitizer.sh index 49677c734..9e0856a50 100755 --- a/tools/metacall-sanitizer.sh +++ b/tools/metacall-sanitizer.sh @@ -23,7 +23,7 @@ set -euxo pipefail BUILD_SANITIZER=${1:-address-sanitizer} BUILD_LANGUAGES=( - python ruby netcore7 nodejs typescript file rpc wasm java c cobol rust + python ruby netcore8 nodejs typescript file rpc wasm java c cobol rust ) SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) ROOT_DIR=$(dirname "$SCRIPT_DIR") @@ -35,7 +35,7 @@ if [ "${BUILD_SANITIZER}" != "address-sanitizer" ] && [ "${BUILD_SANITIZER}" != fi # Install -"${SCRIPT_DIR}/metacall-environment.sh" base ${BUILD_LANGUAGES[@]} rapidjson funchook swig pack backtrace +"${SCRIPT_DIR}/metacall-environment.sh" base ${BUILD_LANGUAGES[@]} rapidjson swig pack backtrace # Configure and Build export NODE_PATH="/usr/lib/node_modules"