diff --git a/.clang-tidy b/.clang-tidy index 67cd167fc..b5f3da69d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,16 +1,49 @@ # refer to https://clang.llvm.org/extra/clang-tidy/checks/list.html +# +# Configure clang-tidy for this project. + +# Here is an explanation for why some of the checks are disabled: +# + +Checks: > + -*, + bugprone-*, + cert-*, + clang-analyzer-*, + concurrency-*, + misc-*, + modernize-*, + performance-*, + portability-*, + readability-*, + -bugprone-easily-swappable-parameters, + -bugprone-macro-parentheses, + -misc-no-recursion, + -misc-unused-parameters, + -readability-braces-around-statements, + -readability-else-after-return, + -readability-function-cognitive-complexity, + -readability-identifier-length, + -readability-isolate-declaration, + -readability-magic-numbers, + -readability-named-parameter, + -readability-non-const-parameter, + -readability-redundant-preprocessor, + -readability-suspicious-call-argument, + -readability-uppercase-literal-suffix + + +# Turn all the warnings from the checks above into errors. +WarningsAsErrors: "*" + +# headers in the following directories will be checked: +# - core/iwasm/ +# - core/shared/ +HeaderFilterRegex: '(core/iwasm/|core/shared/).*\\.h$' + +# goto .clang-format at root directory to see the format style +FormatStyle: file -Checks: '-*, readability-identifier-naming, clang-analyzer-core.*,' -WarningsAsErrors: '-*' -HeaderFilterRegex: '' -FormatStyle: file -InheritParentConfig: false -AnalyzeTemporaryDtors: false -User: wamr CheckOptions: - - key: readability-identifier-naming.VariableCase - value: lower_case - - key: readability-identifier-naming.ParameterCase - value: lower_case - - key: readability-identifier-naming.MacroDefinitionCase - value: UPPER_CASE + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } + - { key: readability-function-cognitive-complexity.Threshold, value: 100 } diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 1587a7ddc..b81561a56 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,150 +1,42 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/cpp/.devcontainer/base.Dockerfile -# [Choice] Debian / Ubuntu version (use Debian 12/11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-12, debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 +# hadolint global ignore=DL3008,DL3009 + ARG VARIANT=debian-12 -FROM mcr.microsoft.com/vscode/devcontainers/cpp:${VARIANT} +FROM mcr.microsoft.com/devcontainers/cpp:${VARIANT} ARG DEBIAN_FRONTEND=noninteractive -ENV TZ=Asian/Shanghai +ENV TZ=Asia/Shanghai + +RUN apt-get update \ + && apt-get upgrade -y -# hadolint ignore=DL3008 RUN apt-get update \ - && apt-get upgrade -y \ && apt-get install -y apt-transport-https apt-utils build-essential \ - ca-certificates ccache cmake curl g++-multilib git gnupg \ - libgcc-12-dev lib32gcc-12-dev lsb-release \ - ninja-build ocaml ocamlbuild \ - software-properties-common tree tzdata \ - unzip valgrind vim wget zip --no-install-recommends \ - && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* + ca-certificates ccache clang-format-14 curl file g++-multilib git gnupg \ + libgcc-12-dev lib32gcc-12-dev libzstd-dev lsb-release \ + ninja-build ocaml ocamlbuild opam \ + python3-venv python3-pip \ + software-properties-common tree tzdata \ + unzip valgrind vim wget zip --no-install-recommends -# -# binaryen -ARG BINARYEN_VER=114 WORKDIR /opt -RUN wget -c --progress=dot:giga https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VER}/binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \ - && tar xf binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \ - && ln -sf /opt/binaryen-version_${BINARYEN_VER} /opt/binaryen \ - && rm binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz -# -# CMAKE (https://apt.kitware.com/) -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -# hadolint ignore=DL3008 -ARG CMAKE_VER=3.27.0 -RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh \ - -q -O /tmp/cmake-install.sh \ - && chmod u+x /tmp/cmake-install.sh \ - && mkdir /opt/cmake-${CMAKE_VER} \ - && /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-${CMAKE_VER} \ - && rm /tmp/cmake-install.sh \ - && ln -s /opt/cmake-${CMAKE_VER}/bin/* /usr/local/bin +ARG WASI_SDK_VER=25 +RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-x86_64-linux.tar.gz -P /tmp \ + && tar xf /tmp/wasi-sdk-${WASI_SDK_VER}.0-x86_64-linux.tar.gz -C /opt \ + && ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0-x86_64-linux /opt/wasi-sdk -# -# install emsdk -WORKDIR /opt -RUN git clone https://github.com/emscripten-core/emsdk.git - -ARG EMSDK_VER=3.1.43 -WORKDIR /opt/emsdk -RUN git pull \ - && ./emsdk install ${EMSDK_VER} \ - && ./emsdk activate ${EMSDK_VER} \ - && echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc - -# -# install wasi-sdk -ARG WASI_SDK_VER=20 -RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \ - && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \ - && ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \ - && rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz - -# -#install wabt -ARG WABT_VER=1.0.33 -RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \ - && tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \ - && ln -sf /opt/wabt-${WABT_VER} /opt/wabt \ - && rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz - -# -# install bazelisk -ARG BAZELISK_VER=1.17.0 -RUN mkdir /opt/bazelisk \ - && wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \ - && chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \ - && ln -fs /opt/bazelisk/bazelisk-linux-amd64 /opt/bazelisk/bazel - -# -# install clang+llvm -ARG LLVM_VER=16 -RUN apt-get purge -y clang-14 llvm-14 && apt-get autoremove -y -WORKDIR /etc/apt/apt.conf.d -RUN touch 99verfiy-peer.conf \ - && echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf - -WORKDIR /tmp -#RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \ -# && chmod a+x ./llvm.sh \ -# && ./llvm.sh ${LLVM_VER} all - -# Workaround due to https://github.com/llvm/llvm-project/issues/62475 -# hadolint ignore=DL3008 -RUN set -ex \ - && echo "deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${LLVM_VER} main" > /etc/apt/sources.list.d/apt.llvm.org.list \ - && wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc \ - && apt-get update \ - && apt-get install -y \ - clang-${LLVM_VER} lldb-${LLVM_VER} lld-${LLVM_VER} clangd-${LLVM_VER} clang-tidy-${LLVM_VER} clang-format-${LLVM_VER} clang-tools-${LLVM_VER} \ - llvm-${LLVM_VER}-dev lld-${LLVM_VER} lldb-${LLVM_VER} llvm-${LLVM_VER}-tools libomp-${LLVM_VER}-dev libc++-${LLVM_VER}-dev libc++abi-${LLVM_VER}-dev \ - libclang-common-${LLVM_VER}-dev libclang-${LLVM_VER}-dev libclang-cpp${LLVM_VER}-dev libunwind-${LLVM_VER}-dev \ - libclang-rt-${LLVM_VER}-dev libpolly-${LLVM_VER}-dev --no-install-recommends \ - && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* - -# -# [Optional] - -# -# Install pip -# hadolint ignore=DL3008 -RUN apt-get update \ - && apt-get install -y --reinstall python3-venv python3-pip --no-install-recommends \ - && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* - -# -# Install required python packages -# hadolint ignore=DL3013 -RUN python3 -m pip install --no-cache-dir --break-system-packages --upgrade pip \ - && pip3 install --no-cache-dir --break-system-packages black nose pycparser pylint - -# -# Install github-cli. It doens't work as a feature of devcontainer.json -ARG GH_CLI_VER=2.32.0 -WORKDIR /tmp -RUN wget -q https://github.com/cli/cli/releases/download/v${GH_CLI_VER}/gh_${GH_CLI_VER}_linux_amd64.deb \ - && dpkg -i gh_${GH_CLI_VER}_linux_amd64.deb - -# -# Install NodeJS -RUN wget -qO- https://deb.nodesource.com/setup_20.x | bash - -# hadolint ignore=DL3008 -RUN apt-get install -y nodejs --no-install-recommends +ARG WABT_VER=1.0.37 +RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu-20.04.tar.gz -P /tmp \ + && tar xf /tmp/wabt-${WABT_VER}-ubuntu-20.04.tar.gz -C /opt \ + && ln -sf /opt/wabt-${WABT_VER} /opt/wabt # set path -ENV PATH="/opt/bazelisk:/usr/lib/llvm-${LLVM_VER}/bin:${PATH}" -ENV CC=/usr/lib/llvm-${LLVM_VER}/bin/clang CXX=/usr/lib/llvm-${LLVM_VER}/bin/clang++ -RUN printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \ - && apt-get autoremove -y \ + +# clean up +RUN apt-get autoremove -y \ && apt-get clean -y \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /tmp/* - -# set workdir when container run -VOLUME /workspaces -WORKDIR /workspaces diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5feb17564..b36c06309 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,23 +1,11 @@ -// Copyright (C) 2019 Intel Corporation. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/cpp { "name": "WAMR-Dev", "build": { "dockerfile": "Dockerfile", - // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-12, debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 - // Use Debian 12, Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon "args": { - "BINARYEN_VER": "114", - "BAZELISK_VER": "1.17.0", - "CMAKE_VER": "3.27.0", - "EMSDK_VER": "3.1.43", - "GH_CLI_VER": "2.32.0", - "LLVM_VER": "16", "VARIANT": "debian-12", - "WASI_SDK_VER": "20", - "WABT_VER": "1.0.33" + "WASI_SDK_VER": "25", + "WABT_VER": "1.0.37" } }, "runArgs": [ @@ -25,26 +13,17 @@ "--security-opt", "seccomp=unconfined" ], - // Configure tool-specific properties. "customizations": { - // Configure properties specific to VS Code. "vscode": { - // Set *default* container specific settings.json values on container create. "settings": {}, - // Add the IDs of extensions you want installed when the container is created. "extensions": [ "dtsvet.vscode-wasm", - "llvm-vs-code-extensions.vscode-clangd", "ms-python.python", "ms-python.vscode-pylance", "ms-vscode.cmake-tools" ] } }, - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "curl https://sh.rustup.rs -sSf | bash -s -- -y", - // Comment out this line to run as root instead. + "postCreateCommand": "bash .devcontainer/finalize.sh", "remoteUser": "vscode" } \ No newline at end of file diff --git a/.devcontainer/finalize.sh b/.devcontainer/finalize.sh new file mode 100644 index 000000000..a7d877b82 --- /dev/null +++ b/.devcontainer/finalize.sh @@ -0,0 +1,18 @@ +echo "Running finalize script..." + +# +# Python Package Installation +# +echo "--- Installing Python Dependencies\n" + +# Upgrade pip first +python3 -m pip install --no-cache-dir --break-system-packages --upgrade pip +# Install required packages +pip3 install --no-cache-dir --break-system-packages -r .devcontainer/requirements.txt + +echo "--- Installing Ocaml stuff\n" +opam init --yes --shell-setup +eval $(opam env --switch=default) +opam install --yes dune menhir + +echo "Finalize script completed. ✅" diff --git a/.devcontainer/requirements.txt b/.devcontainer/requirements.txt new file mode 100644 index 000000000..a8ed4b65d --- /dev/null +++ b/.devcontainer/requirements.txt @@ -0,0 +1,5 @@ +black +nose +pycparser +pylint +requests diff --git a/.github/actions/install-wasi-sdk-wabt/action.yml b/.github/actions/install-wasi-sdk-wabt/action.yml index 6b79087c2..31d22c18d 100644 --- a/.github/actions/install-wasi-sdk-wabt/action.yml +++ b/.github/actions/install-wasi-sdk-wabt/action.yml @@ -50,18 +50,18 @@ runs: echo "::notice::wasi-sdk-25 and wabt-1.0.37 installed on ubuntu" working-directory: /opt - - name: Set up wasi-sdk and wabt on macOS-13 (intel) - if: ${{ inputs.os == 'macos-13' }} + - name: Set up wasi-sdk and wabt on macOS on Intel + if: ${{ inputs.os == 'macos-15-intel' }} shell: bash run: | - echo "Downloading wasi-sdk for macOS-13..." + echo "Downloading wasi-sdk for macOS on Intel..." sudo wget -O wasi-sdk.tar.gz --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-macos.tar.gz echo "Extracting wasi-sdk..." sudo tar -xf wasi-sdk.tar.gz sudo ln -sf wasi-sdk-25.0-x86_64-macos wasi-sdk - echo "Downloading wabt for macOS-13..." + echo "Downloading wabt for macOS on Intel..." sudo wget -O wabt.tar.gz --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/1.0.36/wabt-1.0.36-macos-12.tar.gz echo "Extracting wabt..." @@ -71,21 +71,21 @@ runs: /opt/wasi-sdk/bin/clang --version /opt/wabt/bin/wasm-interp --version - echo "::notice::wasi-sdk-25 and wabt-1.0.36 installed on macos-13" + echo "::notice::wasi-sdk-25 and wabt-1.0.36 installed on ${{ inputs.os }}" working-directory: /opt - - name: Set up wasi-sdk and wabt on macOS-14 (arm64) - if: ${{ inputs.os == 'macos-14' }} + - name: Set up wasi-sdk and wabt on macOS on ARM + if: ${{ inputs.os == 'macos-15' }} shell: bash run: | - echo "Downloading wasi-sdk for macOS-14..." + echo "Downloading wasi-sdk for macOS on ARM..." sudo wget -O wasi-sdk.tar.gz --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-arm64-macos.tar.gz echo "Extracting wasi-sdk..." sudo tar -xf wasi-sdk.tar.gz sudo ln -sf wasi-sdk-25.0-arm64-macos wasi-sdk - echo "Downloading wabt for macOS-14..." + echo "Downloading wabt for macOS on ARM..." sudo wget -O wabt.tar.gz --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/1.0.37/wabt-1.0.37-macos-14.tar.gz echo "Extracting wabt..." @@ -95,7 +95,7 @@ runs: /opt/wasi-sdk/bin/clang --version /opt/wabt/bin/wasm-interp --version - echo "::notice::wasi-sdk-25 and wabt-1.0.37 installed on macos-14" + echo "::notice::wasi-sdk-25 and wabt-1.0.37 installed on ${{ inputs.os }}" working-directory: /opt - name: Set up wasi-sdk and wabt on Windows diff --git a/.github/scripts/codeql_buildscript.sh b/.github/scripts/codeql_buildscript.sh index 706ff5b78..99060af8f 100755 --- a/.github/scripts/codeql_buildscript.sh +++ b/.github/scripts/codeql_buildscript.sh @@ -78,26 +78,30 @@ iwasm_options_list=( #default "" # +classic interp - "-DWAMR_BUILD_FAST_INTERP=0" - # +llvm jit + fast jit - "-DWAMR_BUILD_JIT=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1" + "-DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_SIMD=0" + # fast jit + "-DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1 -DWAMR_BUILD_SIMD=0" + # +llvm jit + "-DWAMR_BUILD_JIT=1" # "-DWAMR_BUILD_TARGET=X86_32" # # libraries "-DWAMR_BUILD_LIBC_BUILTIN=0 -DWAMR_BUILD_LIBC_UVWASI=1 -DWAMR_BUILD_LIBC_EMCC=1" - "-DWAMR_BUILD_THREAD_MGR=1 -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_SHARED_MEMORY=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1" - "-DWAMR_BUILD_THREAD_MGR=1 -DWAMR_BUILD_LIB_WASI_THREADS=1 -DWAMR_BUILD_SHARED_MEMORY=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1" + "-DWAMR_BUILD_THREAD_MGR=1 -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1" + "-DWAMR_BUILD_THREAD_MGR=1 -DWAMR_BUILD_LIB_WASI_THREADS=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1" "-DWAMR_BUILD_WASI_NN=1 -DWAMR_BUILD_WASI_NN_LLAMACPP=1" # # Wasm specs - "-DWAMR_BUILD_GC=1 -DWAMR_BUILD_EXCE_HANDLING=1 -DWAMR_BUILD_STRINGREF=1 -DWAMR_STRINGREF_IMPL_SOURCE=STUB" - "-DWAMR_BUILD_MEMORY64=1 -DWAMR_BUILD_MULTI_MEMORY=1" + "-DWAMR_BUILD_GC=1 -DWAMR_BUILD_STRINGREF=1 -DWAMR_STRINGREF_IMPL_SOURCE=STUB" + "-DWAMR_BUILD_EXCE_HANDLING=1 -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_SIMD=0" + "-DWAMR_BUILD_MEMORY64=1 -DWAMR_BUILD_MULTI_MEMORY=1 -DWAMR_BUILD_SHARED_MEMORY=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_SIMD=0 -DWAMR_BUILD_AOT=0" # # WARM features "-DWAMR_BUILD_MULTI_MODULE=1 -DWAMR_BUILD_MINI_LOADER=1 -DWAMR_BUILD_SHARED_HEAP=1" "-DWAMR_DISABLE_HW_BOUND_CHECK=1" "-DWAMR_CONFIGURABLE_BOUNDS_CHECKS=1" + "-DWAMR_BUILD_EXTENDED_CONST_EXPR=1" # - Debug "-DWAMR_BUILD_DEBUG_INTERP=1 -DWAMR_BUILD_DEBUG_AOT=1 -DWAMR_BUILD_DYNAMIC_AOT_DEBUG=1" # - developer options diff --git a/.github/workflows/build_docker_images.yml b/.github/workflows/build_docker_images.yml index f158b075d..9c4371b4e 100644 --- a/.github/workflows/build_docker_images.yml +++ b/.github/workflows/build_docker_images.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Build and save Docker image(wasm-debug-server:${{ inputs.ver_num }}) to tar file run: | diff --git a/.github/workflows/build_iwasm_release.yml b/.github/workflows/build_iwasm_release.yml index a612d9773..ab84c4f43 100644 --- a/.github/workflows/build_iwasm_release.yml +++ b/.github/workflows/build_iwasm_release.yml @@ -104,11 +104,11 @@ jobs: contents: write # for uploading release artifacts steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 - name: get cached LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/build_llvm_libraries.yml b/.github/workflows/build_llvm_libraries.yml index cc9b3068c..b661131f2 100644 --- a/.github/workflows/build_llvm_libraries.yml +++ b/.github/workflows/build_llvm_libraries.yml @@ -45,16 +45,16 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - - name: install dependencies for non macos-14 - if: inputs.os != 'macos-14' + - name: install dependencies for non macos + if: ${{ !startsWith(inputs.os, 'macos') }} shell: bash run: /usr/bin/env python3 -m pip install -r requirements.txt working-directory: build-scripts - - name: install dependencies for macos-14 - if: inputs.os == 'macos-14' + - name: install dependencies for macos + if: startsWith(inputs.os, 'macos') run: /usr/bin/env python3 -m pip install -r requirements.txt --break-system-packages working-directory: build-scripts @@ -79,7 +79,7 @@ jobs: - name: Cache LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -89,7 +89,7 @@ jobs: ./core/deps/llvm/build/share key: ${{ steps.create_lib_cache_key.outputs.key}} - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: ~/.cache/ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} @@ -101,7 +101,7 @@ jobs: - run: sudo apt install -y ccache ninja-build if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'ubuntu') && inputs.container_image == '' - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: ~/Library/Caches/ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} @@ -112,7 +112,7 @@ jobs: - run: brew install ccache ninja if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'macos') - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: ~/.cache/ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} diff --git a/.github/workflows/build_wamr_lldb.yml b/.github/workflows/build_wamr_lldb.yml index c73cff4db..98a15e653 100644 --- a/.github/workflows/build_wamr_lldb.yml +++ b/.github/workflows/build_wamr_lldb.yml @@ -55,7 +55,7 @@ jobs: contents: write # for uploading release artifacts steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 - name: download and install wasi-sdk run: | @@ -68,7 +68,7 @@ jobs: - name: Cache build id: lldb_build_cache - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm-project/build/bin diff --git a/.github/workflows/build_wamr_sdk.yml b/.github/workflows/build_wamr_sdk.yml index 17be8dd30..df1f26c74 100644 --- a/.github/workflows/build_wamr_sdk.yml +++ b/.github/workflows/build_wamr_sdk.yml @@ -45,7 +45,7 @@ jobs: contents: write # for uploading release artifacts steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 - name: download wamr-app-framework run: | diff --git a/.github/workflows/build_wamr_vscode_ext.yml b/.github/workflows/build_wamr_vscode_ext.yml index f723d344c..7410fd095 100644 --- a/.github/workflows/build_wamr_vscode_ext.yml +++ b/.github/workflows/build_wamr_vscode_ext.yml @@ -24,7 +24,7 @@ jobs: contents: write # for uploading release artifacts steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 - name: Use Node.js 18.x uses: actions/setup-node@v6 diff --git a/.github/workflows/build_wamr_wasi_extensions.yml b/.github/workflows/build_wamr_wasi_extensions.yml index e045f035f..21a07a1cc 100644 --- a/.github/workflows/build_wamr_wasi_extensions.yml +++ b/.github/workflows/build_wamr_wasi_extensions.yml @@ -28,7 +28,7 @@ jobs: os: [ubuntu-22.04] steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: install-wasi-sdk-wabt uses: ./.github/actions/install-wasi-sdk-wabt diff --git a/.github/workflows/build_wamrc.yml b/.github/workflows/build_wamrc.yml index cf09156a8..9fbe38c0a 100644 --- a/.github/workflows/build_wamrc.yml +++ b/.github/workflows/build_wamrc.yml @@ -41,11 +41,11 @@ jobs: contents: write # for uploading release artifacts steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 - name: get cached LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/check_version_h.yml b/.github/workflows/check_version_h.yml index 1623f6306..4ea4c1105 100644 --- a/.github/workflows/check_version_h.yml +++ b/.github/workflows/check_version_h.yml @@ -14,7 +14,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: cmake execute to generate version.h run: cmake -B build_version -S . diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e159e270f..45f9f67c4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -43,13 +43,13 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: submodules: recursive # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v4.31.7 + uses: github/codeql-action/init@v4.33.0 with: languages: ${{ matrix.language }} # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs @@ -58,10 +58,10 @@ jobs: config-file: ./.github/codeql/codeql_config.yml - run: | - ./.github/scripts/codeql_buildscript.sh + ./.github/scripts/codeql_buildscript.sh || exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4.31.7 + uses: github/codeql-action/analyze@v4.33.0 with: category: "/language:${{matrix.language}}" upload: false @@ -102,7 +102,7 @@ jobs: -**:cpp/unused-local-variable -**:cpp/unused-static-function -**:cpp/unused-static-variable - -**:cpp/use-of-goto + -**:cpp/use-of-goto ## Exclude rules 2. Related to special usage of APIs -**:cpp/alloca-in-loop -**:cpp/command-line-injection @@ -114,14 +114,13 @@ jobs: output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif - name: Upload CodeQL results to code scanning - uses: github/codeql-action/upload-sarif@v4.31.7 + uses: github/codeql-action/upload-sarif@v4.33.0 with: sarif_file: ${{ steps.step1.outputs.sarif-output }} category: "/language:${{matrix.language}}" - name: Upload CodeQL results as an artifact - if: success() || failure() - uses: actions/upload-artifact@v5.0.0 + uses: actions/upload-artifact@v7.0.0 with: name: codeql-results path: ${{ steps.step1.outputs.sarif-output }} diff --git a/.github/workflows/coding_guidelines.yml b/.github/workflows/coding_guidelines.yml index bdc13372e..402c455d8 100644 --- a/.github/workflows/coding_guidelines.yml +++ b/.github/workflows/coding_guidelines.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: fetch-depth: 0 diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 070014347..1ac9bd5b4 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -100,13 +100,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 # since jobs.id can't contain the dot character # it is hard to use `format` to assemble the cache key - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -271,13 +271,13 @@ jobs: extra_options: "-DWAMR_BUILD_SIMD=0" steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -322,11 +322,11 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -379,11 +379,11 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -444,12 +444,12 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get LLVM libraries id: retrieve_llvm_libs if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -501,11 +501,11 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -667,7 +667,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Set-up OCaml uses: ocaml/setup-ocaml@v3 @@ -701,7 +701,7 @@ jobs: - name: Get LLVM libraries if: env.USE_LLVM == 'true' id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index f1fab64c8..643caa80e 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -65,7 +65,7 @@ jobs: actions: write uses: ./.github/workflows/build_llvm_libraries.yml with: - os: "macos-13" + os: "macos-15-intel" arch: "X86" build_llvm_libraries_on_arm_macos: permissions: @@ -73,24 +73,27 @@ jobs: actions: write uses: ./.github/workflows/build_llvm_libraries.yml with: - os: "macos-14" + os: "macos-15" arch: "AArch64 ARM" build_wamrc: - needs: [build_llvm_libraries_on_intel_macos] + needs: [build_llvm_libraries_on_intel_macos, build_llvm_libraries_on_arm_macos] runs-on: ${{ matrix.os }} strategy: matrix: + os: [macos-15, macos-15-intel] include: - - os: macos-13 + - os: macos-15-intel llvm_cache_key: ${{ needs.build_llvm_libraries_on_intel_macos.outputs.cache_key }} + - os: macos-15 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_arm_macos.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -112,7 +115,7 @@ jobs: working-directory: wamr-compiler build_iwasm: - needs: [build_llvm_libraries_on_intel_macos] + needs: [build_llvm_libraries_on_intel_macos, build_llvm_libraries_on_arm_macos] runs-on: ${{ matrix.os }} strategy: matrix: @@ -142,7 +145,7 @@ jobs: "-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_BUILD_EXTENDED_CONST_EXPR=1", ] - os: [macos-13] + os: [macos-15, macos-15-intel] platform: [darwin] exclude: # incompatible feature and platform @@ -179,20 +182,22 @@ jobs: - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" include: - - os: macos-13 + - os: macos-15 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_arm_macos.outputs.cache_key }} + - os: macos-15-intel llvm_cache_key: ${{ needs.build_llvm_libraries_on_intel_macos.outputs.cache_key }} # classic interp doesn't support SIMD - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS extra_options: "-DWAMR_BUILD_SIMD=0" steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -218,6 +223,7 @@ jobs: [ build_iwasm, build_llvm_libraries_on_intel_macos, + build_llvm_libraries_on_arm_macos, build_wamrc, ] runs-on: ${{ matrix.os }} @@ -227,24 +233,18 @@ jobs: $AOT_BUILD_OPTIONS, $CLASSIC_INTERP_BUILD_OPTIONS, $FAST_INTERP_BUILD_OPTIONS, - $FAST_JIT_BUILD_OPTIONS, $LLVM_LAZY_JIT_BUILD_OPTIONS, $LLVM_EAGER_JIT_BUILD_OPTIONS, - $MULTI_TIER_JIT_BUILD_OPTIONS, ] - os: [macos-13] + os: [macos-15, macos-15-intel] include: - - os: macos-13 + - os: macos-15 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_arm_macos.outputs.cache_key }} + - os: macos-15-intel llvm_cache_key: ${{ needs.build_llvm_libraries_on_intel_macos.outputs.cache_key }} # classic interp doesn't support SIMD - make_options: $CLASSIC_INTERP_BUILD_OPTIONS extra_options: "-DWAMR_BUILD_SIMD=0" - # fast jit doesn't support Multi-module and SIMD - - make_options: $FAST_JIT_BUILD_OPTIONS - extra_options: "-DWAMR_BUILD_SIMD=0 -DWAMR_BUILD_MULTI_MODULE=0" - # multi-tier jit doesn't support Multi-module and SIMD - - make_options: $MULTI_TIER_JIT_BUILD_OPTIONS - extra_options: "-DWAMR_BUILD_SIMD=0 -DWAMR_BUILD_MULTI_MODULE=0" # LLVM JIT doesn't support Multi-module - make_options: $LLVM_LAZY_JIT_BUILD_OPTIONS extra_options: "-DWAMR_BUILD_MULTI_MODULE=0" @@ -253,12 +253,12 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get LLVM libraries id: retrieve_llvm_libs if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -303,15 +303,15 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13, macos-14] + os: [macos-15-intel, macos-15] include: - - os: macos-13 + - os: macos-15-intel llvm_cache_key: ${{ needs.build_llvm_libraries_on_intel_macos.outputs.cache_key }} - - os: macos-14 + - os: macos-15 llvm_cache_key: ${{ needs.build_llvm_libraries_on_arm_macos.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: install-wasi-sdk-wabt uses: ./.github/actions/install-wasi-sdk-wabt @@ -366,7 +366,7 @@ jobs: - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -440,3 +440,13 @@ jobs: cmake .. cmake --build . --config Release --parallel 4 ./import-func-callback + + - name: Test x18 register reservation (macOS ARM64 only) + if: matrix.os == 'macos-15' + run: | + cd product-mini/platforms/darwin + mkdir -p build && cd build + cmake .. -DWAMR_BUILD_AOT=1 + cmake --build . --config Release --parallel 4 + cd ../../../../tests/standalone/test-aot-x18-reserve + ./run.sh --aot diff --git a/.github/workflows/compilation_on_nuttx.yml b/.github/workflows/compilation_on_nuttx.yml index 4795c43d4..1ad28f3bb 100644 --- a/.github/workflows/compilation_on_nuttx.yml +++ b/.github/workflows/compilation_on_nuttx.yml @@ -87,21 +87,21 @@ jobs: steps: - name: Checkout NuttX - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: repository: apache/nuttx ref: 09a71ec7c16c43398d5acbdcbeee7b08736c3170 path: nuttx - name: Checkout NuttX Apps - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: repository: apache/nuttx-apps ref: 6bd593459c4af3cef325c3d22bccd5537a8ed755 path: apps - name: Checkout WAMR - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: repository: ${{ github.repository }} path: apps/interpreters/wamr/wamr @@ -126,7 +126,7 @@ jobs: run: make -j$(nproc) EXTRAFLAGS=-Werror - name: Checkout Bloaty - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: repository: google/bloaty submodules: recursive diff --git a/.github/workflows/compilation_on_sgx.yml b/.github/workflows/compilation_on_sgx.yml index 16502c20e..6791d31aa 100644 --- a/.github/workflows/compilation_on_sgx.yml +++ b/.github/workflows/compilation_on_sgx.yml @@ -123,7 +123,7 @@ jobs: make_options_feature: "-DWAMR_BUILD_SIMD=0" steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: install SGX SDK and necessary libraries uses: ./.github/actions/install-linux-sgx @@ -166,7 +166,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: install-wasi-sdk-wabt uses: ./.github/actions/install-wasi-sdk-wabt @@ -190,7 +190,7 @@ jobs: - name: Get LLVM libraries if: matrix.iwasm_make_options_run_mode == '$AOT_BUILD_OPTIONS' id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -262,12 +262,12 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get LLVM libraries if: matrix.running_mode == 'aot' id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml index d69dc1c29..56adbe7ef 100644 --- a/.github/workflows/compilation_on_windows.yml +++ b/.github/workflows/compilation_on_windows.yml @@ -84,7 +84,7 @@ jobs: "-DWAMR_BUILD_LIBC_UVWASI=0 -DWAMR_BUILD_LIBC_WASI=1", ] steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 - name: clone uvwasi library if: ${{ !contains(matrix.build_options, '-DWAMR_BUILD_LIBC_UVWASI=0') }} @@ -108,13 +108,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_windows.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 # since jobs.id can't contain the dot character # it is hard to use `format` to assemble the cache key - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -150,7 +150,7 @@ jobs: ] steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: download and install wasi-sdk if: matrix.test_option == '$WASI_TEST_OPTIONS' diff --git a/.github/workflows/compilation_on_zephyr.yml b/.github/workflows/compilation_on_zephyr.yml index e19824068..ad712deb8 100644 --- a/.github/workflows/compilation_on_zephyr.yml +++ b/.github/workflows/compilation_on_zephyr.yml @@ -78,7 +78,7 @@ jobs: # └─── application/ --> DUMMY. keep west_lite.yml here - name: Checkout code - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: path: modules/wasm-micro-runtime diff --git a/.github/workflows/create_tag.yml b/.github/workflows/create_tag.yml index f1a082fae..2ca4e8283 100644 --- a/.github/workflows/create_tag.yml +++ b/.github/workflows/create_tag.yml @@ -29,7 +29,7 @@ jobs: contents: write # create and push tags steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 # Full git history is needed to get a proper list of commits and tags with: fetch-depth: 0 diff --git a/.github/workflows/hadolint_dockerfiles.yml b/.github/workflows/hadolint_dockerfiles.yml index 4647a5c51..8f4051f86 100644 --- a/.github/workflows/hadolint_dockerfiles.yml +++ b/.github/workflows/hadolint_dockerfiles.yml @@ -37,7 +37,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 # on default, hadolint will fail on warnings and errors - name: Run hadolint on dockerfiles diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index b99931891..6bc090afd 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -67,13 +67,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 # since jobs.id can't contain the dot character # it is hard to use `format` to assemble the cache key - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -235,13 +235,13 @@ jobs: steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -346,9 +346,6 @@ jobs: # fast jit doesn't support SIMD - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS extra_options: "-DWAMR_BUILD_SIMD=0" - # multi-tier jit doesn't support SIMD - - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS - extra_options: "-DWAMR_BUILD_SIMD=0" steps: - name: Install dependencies run: | @@ -392,10 +389,6 @@ jobs: include: - os: ubuntu-22.04 llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu.outputs.cache_key }} - exclude: - - make_options: $MULTI_TIER_JIT_BUILD_OPTIONS - sanitizer: asan - include: # classic interp doesn't support SIMD - make_options: $CLASSIC_INTERP_BUILD_OPTIONS extra_options: "-DWAMR_BUILD_SIMD=0" @@ -410,15 +403,18 @@ jobs: extra_options: "-DWAMR_BUILD_MULTI_MODULE=0" - make_options: $LLVM_EAGER_JIT_BUILD_OPTIONS extra_options: "-DWAMR_BUILD_MULTI_MODULE=0" + exclude: + - make_options: $MULTI_TIER_JIT_BUILD_OPTIONS + sanitizer: asan steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: Get LLVM libraries id: retrieve_llvm_libs if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -466,7 +462,7 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: install-wasi-sdk-wabt uses: ./.github/actions/install-wasi-sdk-wabt @@ -475,7 +471,7 @@ jobs: - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -660,7 +656,7 @@ jobs: sanitizer: ubsan steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: install-wasi-sdk-wabt if: matrix.test_option == '$WASI_TEST_OPTIONS' @@ -689,7 +685,7 @@ jobs: - name: Get LLVM libraries if: env.USE_LLVM == 'true' id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/release_process.yml b/.github/workflows/release_process.yml index b911631f7..b7eebd1c5 100644 --- a/.github/workflows/release_process.yml +++ b/.github/workflows/release_process.yml @@ -55,7 +55,7 @@ jobs: outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 - name: prepare the release note run: | @@ -88,6 +88,7 @@ jobs: os: "ubuntu-22.04" arch: "AArch64 ARM Mips RISCV X86" + #CLARIFY: Require to build LLVM libraries on ARM macOS? build_llvm_libraries_on_macos: permissions: contents: read @@ -95,7 +96,7 @@ jobs: needs: [create_tag, create_release] uses: ./.github/workflows/build_llvm_libraries.yml with: - os: "macos-13" + os: "macos-15-intel" arch: "AArch64 ARM Mips RISCV X86" build_llvm_libraries_on_windows: @@ -122,6 +123,7 @@ jobs: upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver }} + #CLARIFY: Require to release wamrc on ARM macOS? release_wamrc_on_ubuntu_macos: permissions: contents: write # upload release artifact @@ -130,7 +132,7 @@ jobs: with: llvm_cache_key: ${{ needs.build_llvm_libraries_on_macos.outputs.cache_key }} release: true - runner: macos-13 + runner: macos-15-intel upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver }} @@ -160,6 +162,7 @@ jobs: upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver}} + #CLARIFY: Require to release iwasm on ARM macOS? release_iwasm_on_macos: permissions: contents: write # upload release artifact @@ -168,7 +171,7 @@ jobs: with: cwd: product-mini/platforms/darwin llvm_cache_key: ${{ needs.build_llvm_libraries_on_macos.outputs.cache_key }} - runner: macos-13 + runner: macos-15-intel upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver}} @@ -200,6 +203,7 @@ jobs: wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz wamr_app_framework_url: https://github.com/bytecodealliance/wamr-app-framework.git + #CLARIFY: Require to release WAMR SDK on ARM macOS? release_wamr_sdk_on_macos: permissions: contents: write # upload release artifact @@ -208,7 +212,7 @@ jobs: uses: ./.github/workflows/build_wamr_sdk.yml with: config_file: wamr_config_macos_release.cmake - runner: macos-13 + runner: macos-15-intel upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver}} wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz @@ -251,6 +255,7 @@ jobs: upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver}} + #CLARIFY: Require to release WAMR LLDB on ARM macOS? release_wamr_lldb_on_macos_universal: permissions: contents: write # upload release artifact @@ -258,7 +263,7 @@ jobs: if: ${{ inputs.release_wamr_lldb }} uses: ./.github/workflows/build_wamr_lldb.yml with: - runner: macos-13 + runner: macos-15-intel arch: universal upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver}} diff --git a/.github/workflows/reuse_latest_release_binaries.yml b/.github/workflows/reuse_latest_release_binaries.yml index 63546b97c..3bbd4ac9b 100644 --- a/.github/workflows/reuse_latest_release_binaries.yml +++ b/.github/workflows/reuse_latest_release_binaries.yml @@ -34,7 +34,7 @@ jobs: contents: write # for creating realease and uploading release artifacts steps: - - uses: actions/checkout@v6.0.1 + - uses: actions/checkout@v6.0.2 # Full git history is needed to get a proper list of commits and tags with: fetch-depth: 0 diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 16b611c35..f93bb71ee 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -143,21 +143,21 @@ jobs: # Note: we use an unreleased version nuttx for xtensa because # 12.4 doesn't contain necessary esp32s3 changes. - name: Checkout NuttX - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: repository: apache/nuttx ref: ${{ matrix.target_config.target == 'xtensa' && '985d395b025cf2012b22f6bb4461959fa6d87645' || '09a71ec7c16c43398d5acbdcbeee7b08736c3170' }} path: nuttx - name: Checkout NuttX Apps - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: repository: apache/nuttx-apps ref: ${{ matrix.target_config.target == 'xtensa' && '2ef3eb25c0cec944b13792185f7e5d5a05990d5f' || '6bd593459c4af3cef325c3d22bccd5537a8ed755' }} path: apps - name: Checkout WAMR - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 with: repository: ${{ github.repository }} path: apps/interpreters/wamr/wamr @@ -165,7 +165,7 @@ jobs: - name: Get LLVM libraries if: contains(matrix.wamr_test_option.mode, 'aot') id: retrieve_llvm_libs - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ./core/deps/llvm/build/bin @@ -329,7 +329,7 @@ jobs: - name: upload the log if: always() - uses: actions/upload-artifact@v5.0.0 + uses: actions/upload-artifact@v7.0.0 with: name: spec-test-log-${{ github.run_id }}-${{ strategy.job-index }}-${{ matrix.target_config.target }} path: log diff --git a/.github/workflows/supply_chain.yml b/.github/workflows/supply_chain.yml index 0e19f8a2c..ad536cc82 100644 --- a/.github/workflows/supply_chain.yml +++ b/.github/workflows/supply_chain.yml @@ -34,7 +34,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v3.1.0 + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v3.1.0 with: persist-credentials: false @@ -52,7 +52,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v3.1.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v3.1.0 with: name: SARIF file path: results.sarif @@ -60,6 +60,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@149d184a5153ea45e6fbcef5588ac7b8c7af9835 + uses: github/codeql-action/upload-sarif@7dd76e6bf79d24133aa649887a6ee01d8b063816 with: sarif_file: results.sarif diff --git a/.github/workflows/wamr_wasi_extensions.yml b/.github/workflows/wamr_wasi_extensions.yml index a44f0597b..dd52730dc 100644 --- a/.github/workflows/wamr_wasi_extensions.yml +++ b/.github/workflows/wamr_wasi_extensions.yml @@ -27,10 +27,10 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-22.04, macos-13, macos-14] + os: [ubuntu-22.04, macos-15-intel, macos-15] steps: - name: checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6.0.2 - name: install-wasi-sdk-wabt uses: ./.github/actions/install-wasi-sdk-wabt @@ -48,9 +48,10 @@ jobs: ./build_samples.sh $(pwd)/dist/wamr-wasi-extensions working-directory: wamr-wasi-extensions + #CLARIFY: Require to upload artifact on ARM macOS? - name: Upload artifacts - if: matrix.os == 'macos-14' - uses: actions/upload-artifact@v5.0.0 + if: matrix.os == 'macos-15' + uses: actions/upload-artifact@v7.0.0 with: name: wamr-wasi-extensions path: wamr-wasi-extensions/dist diff --git a/.gitignore b/.gitignore index baf11c891..1d14dff9a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ + .cache .clangd .vs @@ -21,9 +22,9 @@ core/iwasm/libraries/lib-wasi-threads/test/*.wasm core/iwasm/libraries/lib-socket/test/*.wasm product-mini/app-samples/hello-world/test.wasm -product-mini/platforms/linux-sgx/enclave-sample/App/ -product-mini/platforms/linux-sgx/enclave-sample/Enclave/ -product-mini/platforms/linux-sgx/enclave-sample/iwasm +product-mini/platforms/linux-sgx/enclave-sample/ +!product-mini/platforms/linux-sgx/enclave-sample/App/App.* +!product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.* build_out tests/wamr-test-suites/workspace @@ -40,3 +41,6 @@ samples/workload/include/** !samples/workload/include/.gitkeep # core/iwasm/libraries/wasi-threads + +tests/unit/runtime-common/wasm-apps/main.aot +tests/unit/aot-stack-frame/wasm-apps/test_aot.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c33b211e6..3872b2c9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,12 +131,6 @@ if (NOT WIN32) string (REGEX REPLACE " *" " " CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) endif() -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () -endif () - # The following flags are to enhance security, but it may impact performance, # we disable them by default. #if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") diff --git a/CODEOWNERS b/CODEOWNERS index 990dcfce2..b5103711c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -22,8 +22,21 @@ # If none of the later patterns match, assign to anyone. This team is the # parent of all the other teams and automatically includes everyone on those # teams. -* @loganek @lum1n0us @no1wudi @TianlongLiang @wenyongh @xujuntwt95329 @yamt +* @lum1n0us @TianlongLiang @yamt # Some parts of the project require more specialized knowledge. In those areas # we designate smaller groups who are more likely to be aware of who's working # in specific areas. + +/core/iwasm/core @loganek @lum1n0us @no1wudi @TianlongLiang @yamt +/core/iwasm/interpreter @loganek @lum1n0us @no1wudi @TianlongLiang @yamt +/core/iwasm/libraries/lib-socket @loganek @srberard +/core/iwasm/libraries/wasi-nn @lum1n0us @yamt +/core/iwasm @lum1n0us @no1wudi @TianlongLiang @yamt + +/docs/ @loganek @lum1n0us @no1wudi @TianlongLiang @yamt + +/product-mini/platforms/darwin/ @yamt +/product-mini/platforms/nuttx/ @no1wudi +/product-mini/platforms/windows/ @loganek +/product-mini/platforms/zephyr/ @srberard diff --git a/build-scripts/build_llvm.py b/build-scripts/build_llvm.py index 3d241355b..68ef640e3 100755 --- a/build-scripts/build_llvm.py +++ b/build-scripts/build_llvm.py @@ -304,7 +304,7 @@ def main(): "default": { "repo": "https://github.com/llvm/llvm-project.git", "repo_ssh": "git@github.com:llvm/llvm-project.git", - "branch": "release/18.x", + "branch": "llvmorg-18.1.8", }, } diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index cb15b8b01..cd6b08d5c 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -79,8 +79,14 @@ if (WAMR_BUILD_TARGET MATCHES "ARM.*") elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb") set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-mthumb") +elseif (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (CMAKE_C_COMPILER_ID MATCHES ".*GNU") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mindirect-branch-register") + endif () endif () + include (${CMAKE_CURRENT_LIST_DIR}/warnings.cmake) if (NOT WAMR_BUILD_INTERP EQUAL 1) @@ -117,7 +123,7 @@ if (WAMR_BUILD_JIT EQUAL 1) set (LLVM_DIR ${LLVM_BUILD_ROOT}/lib/cmake/llvm) endif () find_package(LLVM REQUIRED CONFIG) - include_directories(${LLVM_INCLUDE_DIRS}) + include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") @@ -190,7 +196,11 @@ if (NOT WAMR_BUILD_SANITIZER STREQUAL "") message(FATAL_ERROR "Unsupported sanitizers: ${INVALID_SANITIZERS}") endif() # common flags for all sanitizers - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fno-omit-frame-pointer -fno-sanitize-recover=all") + # clang: warning: the object size sanitizer has no effect at -O0, but is explicitly enabled ... [-Winvalid-command-line-argument] + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O1 -fno-omit-frame-pointer -fno-sanitize-recover=all -fno-sanitize=alignment") + if(CMAKE_C_COMPILER_ID MATCHES ".*Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=unsigned-integer-overflow") + endif() if(SANITIZER_FLAGS) string(REPLACE ";" "," SANITIZER_FLAGS_STR "${SANITIZER_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${SANITIZER_FLAGS_STR}") @@ -765,6 +775,11 @@ endif () if (WAMR_BUILD_LIME1 EQUAL 1) message (" Lime1 enabled") endif () +if (WAMR_BUILD_BRANCH_HINTS EQUAL 1) + message (" Branch hints enabled") + add_definitions(-DWASM_ENABLE_BRANCH_HINTS=1) +endif () + ######################################## # Show Phase4 Wasm proposals status. ######################################## @@ -777,8 +792,8 @@ message ( " \"Non-trapping float-to-int Conversions\"\n" " \"Sign-extension Operators\"\n" " \"WebAssembly C and C++ API\"\n" -" \"Branch Hinting\"\n" " Configurable. 0 is OFF. 1 is ON:\n" +" \"Branch Hinting\" via WAMR_BUILD_BRANCH_HINTS: ${WAMR_BUILD_BRANCH_HINTS}\n" " \"Bulk Memory Operation\" via WAMR_BUILD_BULK_MEMORY: ${WAMR_BUILD_BULK_MEMORY}\n" " \"Bulk-memory-opt\" via WAMR_BUILD_BULK_MEMORY_OPT: ${WAMR_BUILD_BULK_MEMORY_OPT}\n" " \"Call-indirect-overlong\" via WAMR_BUILD_CALL_INDIRECT_OVERLONG: ${WAMR_BUILD_CALL_INDIRECT_OVERLONG}\n" diff --git a/build-scripts/unsupported_combination.cmake b/build-scripts/unsupported_combination.cmake index 635a20a05..4284be32b 100644 --- a/build-scripts/unsupported_combination.cmake +++ b/build-scripts/unsupported_combination.cmake @@ -61,7 +61,6 @@ endfunction() # Below are the unsupported combinations checks # Please keep this list in sync with tests/unit/unsupported-features/CMakeLists.txt # and tests/wamr-test-suites/test_wamr.sh -#cmake_print_variables(WAMR_BUILD_INTERP WAMR_BUILD_FAST_INTERP WAMR_BUILD_JIT) if(WAMR_BUILD_EXCE_HANDLING EQUAL 1) check_aot_mode_error("Unsupported build configuration: EXCE_HANDLING + AOT") @@ -81,10 +80,10 @@ if(WAMR_BUILD_MEMORY64 EQUAL 1) endif() if(WAMR_BUILD_MULTI_MEMORY EQUAL 1) - check_aot_mode_error("Unsupported build configuration: EXCE_HANDLING + AOT") - check_fast_interp_error("Unsupported build configuration: EXCE_HANDLING + FAST_INTERP") - check_fast_jit_error("Unsupported build configuration: EXCE_HANDLING + FAST_JIT") - check_llvm_jit_error("Unsupported build configuration: EXCE_HANDLING + JIT") + check_aot_mode_error("Unsupported build configuration: MULTI_MEMORY + AOT") + check_fast_interp_error("Unsupported build configuration: MULTI_MEMORY + FAST_INTERP") + check_fast_jit_error("Unsupported build configuration: MULTI_MEMORY + FAST_JIT") + check_llvm_jit_error("Unsupported build configuration: MULTI_MEMORY + JIT") endif() if(WAMR_BUILD_MULTI_MODULE EQUAL 1) diff --git a/ci/coding_guidelines_check.py b/ci/coding_guidelines_check.py index 131bca5b6..be1002c00 100644 --- a/ci/coding_guidelines_check.py +++ b/ci/coding_guidelines_check.py @@ -159,7 +159,7 @@ def run_clang_format_diff(root: Path, commits: str) -> bool: found = True else: return not found - except subprocess.subprocess.CalledProcessError: + except subprocess.CalledProcessError: return False @@ -183,12 +183,14 @@ def check_file_name(path: Path) -> bool: - docker-compose - package-lock - vite-env.d + - .clang-tidy (standard config file for Clang-Tidy) """ if path.stem in [ "docker-compose", "package-lock", "vite-env.d", "osv-scanner", + ".clang-tidy", ]: return True diff --git a/ci/install_sgx_for_applicaiton_developer.sh b/ci/install_sgx_for_applicaiton_developer.sh new file mode 100755 index 000000000..f119f0438 --- /dev/null +++ b/ci/install_sgx_for_applicaiton_developer.sh @@ -0,0 +1,400 @@ +#!/bin/bash + +# Reference: +# https://cc-enabling.trustedservices.intel.com/intel-sgx-sw-installation-guide-linux/02/installation_instructions/#intel-sgx-application-developer + +#TODO: +# report error when curl fails to download files, e.g. due to network issues or incorrect URLs + +set -euo pipefail +if [ "${DEBUG:-0}" -eq 1 ]; then + set -o xtrace +fi + +# Error trap handler - logs failure details and calls cleanup before exit +error_handler() { + local exit_code=$? + local line_number=${1:-$LINENO} + local bash_lineno=${2:-$BASH_LINENO} + local last_command=${3:-$BASH_COMMAND} + local function_stack=${4:-${FUNCNAME[*]}} + + # Log error context to file + { + echo "=== ERROR OCCURRED ===" + echo "Exit Code: $exit_code" + echo "Line Number: $line_number" + echo "Bash Line: $bash_lineno" + echo "Failed Command: $last_command" + echo "Function Stack: $function_stack" + echo "Timestamp: $(date '+%Y-%m-%d %H:%M:%S')" + echo "======================" + } >> "${LOG_FILE:-/tmp/install_sgx.log}" 2>/dev/null || true + + # Print concise error to stderr + echo "ERROR: Script failed at line $line_number with exit code $exit_code" >&2 + echo "Failed command: $last_command" >&2 + echo "Check log file: ${LOG_FILE:-/tmp/install_sgx.log}" >&2 + + # Call cleanup function if it exists + if type cleanup >/dev/null 2>&1; then + cleanup || true + fi + + exit $exit_code +} + +# Set up error trap +trap 'error_handler $LINENO $BASH_LINENO "$BASH_COMMAND" "${FUNCNAME[*]}"' ERR + +# Platform will be detected dynamically by platform_detect() function +# Supported platforms: Debian12, Debian11, Ubuntu22.04-server, Ubuntu20.04-server +PLATFORM="" + +# Logging infrastructure +LOG_FILE="/tmp/install_sgx.log" + +# Initialize log file with timestamp +init_log() { + echo "=== Intel SGX Installation Log - $(date) ===" > "${LOG_FILE}" + echo "Platform: ${PLATFORM}" >> "${LOG_FILE}" + echo "Script: $0" >> "${LOG_FILE}" + echo "Started at: $(date '+%Y-%m-%d %H:%M:%S')" >> "${LOG_FILE}" + echo "" >> "${LOG_FILE}" +} + +# Log message with timestamp +log_info() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "${LOG_FILE}" +} + +# Execute command with output redirected to log +log_exec() { + log_info "Executing: $*" + "$@" >>"$LOG_FILE" 2>&1 +} + +# Print environment sourcing instructions +print_env_instructions() { + log_info "Printing environment setup instructions" + + echo "========================================================================" + echo " IMPORTANT: Before building or running SGX applications, you must run:" + echo " source /opt/intel/sgxsdk/environment" + echo " in your current shell to activate SGX SDK environment variables." + echo "========================================================================" + + log_info "Environment setup instructions displayed to user" +} + +check_sgx_packages() { + log_info "Checking for existing SGX packages..." + + local packages=("libsgx-quote-ex" "libsgx-dcap-ql" "libsgx-enclave-common-dev" "libsgx-dcap-ql-dev" "libsgx-dcap-default-qpl-dev" "tee-appraisal-tool") + local missing_packages=() + + for package in "${packages[@]}"; do + if ! dpkg -l "$package" >> "${LOG_FILE}" 2>&1; then + missing_packages+=("$package") + log_info "Package $package not installed" + else + log_info "Package $package already installed" + fi + done + + if [ ${#missing_packages[@]} -eq 0 ]; then + log_info "All SGX packages are already installed" + return 0 + else + log_info "Missing SGX packages: ${missing_packages[*]}" + return 1 + fi +} + +check_sgx_sdk() { + log_info "Checking for existing SGX SDK..." + + if [ -d "/opt/intel/sgxsdk" ] && [ -f "/opt/intel/sgxsdk/environment" ]; then + log_info "SGX SDK already installed at /opt/intel/sgxsdk" + + # Validate SDK installation by checking key components + if [ -f "/opt/intel/sgxsdk/bin/sgx-gdb" ] && [ -d "/opt/intel/sgxsdk/include" ]; then + log_info "SGX SDK installation appears complete" + return 0 + else + log_info "SGX SDK installation incomplete - missing key components" + return 1 + fi + else + log_info "SGX SDK not found" + return 1 + fi +} + +check_sgx_repo() { + log_info "Checking for existing SGX local repository..." + + if [ -d "/opt/intel/sgx_debian_local_repo" ] && [ -f "/etc/apt/sources.list.d/sgx_debian_local_repo.list" ]; then + log_info "SGX local repository already configured" + return 0 + else + log_info "SGX local repository not configured" + return 1 + fi +} + +# Modular installation functions + +# Platform detection and configuration +platform_detect() { + log_info "Entering platform_detect() function" + + if [ ! -f "/etc/os-release" ]; then + log_info "ERROR: /etc/os-release not found - cannot detect OS" + echo "ERROR: Cannot detect operating system. /etc/os-release not found." >&2 + log_info "Exiting platform_detect() function" + return 1 + fi + + # Parse OS information from /etc/os-release + local os_id=$(grep '^ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"') + local version_id=$(grep '^VERSION_ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"') + + log_info "Raw OS detection: ID=${os_id}, VERSION_ID=${version_id}" + + # Determine platform string based on OS and version + case "${os_id}" in + "ubuntu") + case "${version_id}" in + "20.04") + PLATFORM="Ubuntu20.04-server" + ;; + "22.04") + PLATFORM="Ubuntu22.04-server" + ;; + *) + log_info "ERROR: Unsupported Ubuntu version ${version_id}. Supported: 20.04, 22.04" + echo "ERROR: Unsupported Ubuntu version ${version_id}. This script supports Ubuntu 20.04 and 22.04 only." >&2 + log_info "Exiting platform_detect() function" + return 1 + ;; + esac + ;; + "debian") + case "${version_id}" in + "11") + PLATFORM="Debian11" + ;; + "12") + PLATFORM="Debian12" + ;; + *) + log_info "ERROR: Unsupported Debian version ${version_id}. Supported: 11, 12" + echo "ERROR: Unsupported Debian version ${version_id}. This script supports Debian 11 and 12 only." >&2 + log_info "Exiting platform_detect() function" + return 1 + ;; + esac + ;; + *) + log_info "ERROR: Unsupported OS ${os_id}. Supported: ubuntu, debian" + echo "ERROR: Unsupported operating system '${os_id}'. This script supports Ubuntu and Debian only." >&2 + log_info "Exiting platform_detect() function" + return 1 + ;; + esac + + log_info "Successfully detected platform: ${PLATFORM}" + echo "Detected platform: ${PLATFORM}" + + log_info "Exiting platform_detect() function" + return 0 +} + +# Install SGX packages and SDK +install_packages() { + log_info "Entering install_packages() function" + + # Skip repo setup if already configured + if ! check_sgx_repo; then + log_info "Setting up SGX local repository..." + + pushd /tmp >> "${LOG_FILE}" 2>&1 + log_exec curl -fsSLO \ + https://download.01.org/intel-sgx/latest/linux-latest/distro/${PLATFORM}/sgx_debian_local_repo.tgz + + local_sum=$(sha256sum sgx_debian_local_repo.tgz | awk '{print $1}') + remote_sum=$(curl -s https://download.01.org/intel-sgx/latest/dcap-latest/linux/SHA256SUM_dcap_1.24.cfg | grep "distro/${PLATFORM}/sgx_debian_local_repo.tgz" | awk '{print $1}') + if [[ "$local_sum" == "$remote_sum" ]]; then + log_info "Checksum matches" + else + log_info "Checksum mismatch!" + fi + + log_exec sudo mkdir -p /opt/intel + log_exec sudo tar xzf sgx_debian_local_repo.tgz -C /opt/intel + + echo 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64] file:///opt/intel/sgx_debian_local_repo bookworm main' \ + | sudo tee /etc/apt/sources.list.d/sgx_debian_local_repo.list | tee -a "${LOG_FILE}" > /dev/null + + log_exec sudo cp /opt/intel/sgx_debian_local_repo/keys/intel-sgx.key /etc/apt/keyrings/intel-sgx-keyring.asc + popd >> "${LOG_FILE}" 2>&1 + else + log_info "SGX repository already configured, skipping setup" + fi + + # Install SGX packages only if missing + if ! check_sgx_packages; then + log_info "Installing missing SGX packages..." + log_exec sudo apt-get update + log_exec sudo apt-get install -y libsgx-quote-ex libsgx-dcap-ql + else + log_info "SGX packages already installed, skipping" + fi + + # Install build dependencies + log_exec sudo apt-get update --quiet + log_exec sudo apt-get install --quiet -y build-essential python3 + log_exec sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 + + # Install Intel SGX SDK only if missing + if ! check_sgx_sdk; then + log_info "Installing Intel SGX SDK for Application Developer..." + + pushd /opt/intel >> "${LOG_FILE}" 2>&1 + log_exec sudo curl -fsSLo sgx_linux_x64_sdk.bin \ + https://download.01.org/intel-sgx/latest/linux-latest/distro/${PLATFORM}/sgx_linux_x64_sdk_2.27.100.1.bin + log_exec sudo chmod +x sgx_linux_x64_sdk.bin + log_exec sudo ./sgx_linux_x64_sdk.bin --prefix /opt/intel + + # Log environment setup instructions for user + log_info "SGX SDK installation completed successfully." + log_info "IMPORTANT: To use the SGX SDK in your development session:" + log_info " 1. Run: source /opt/intel/sgxsdk/environment" + log_info " 2. This must be done in each shell session where you use SGX" + log_info " 3. Environment variables are session-specific and cannot be exported by this script" + log_info " 4. Consider adding 'source /opt/intel/sgxsdk/environment' to your ~/.bashrc for automatic setup" + popd >> "${LOG_FILE}" 2>&1 + else + log_info "SGX SDK already installed, skipping" + fi + + # Install Developer packages for Intel SGX only if missing + if ! check_sgx_packages; then + log_info "Installing Intel SGX Developer packages..." + + log_exec sudo apt-get install -y libsgx-enclave-common-dev \ + libsgx-dcap-ql-dev \ + libsgx-dcap-default-qpl-dev \ + tee-appraisal-tool + else + log_info "SGX Developer packages already installed, skipping" + fi + + log_info "Exiting install_packages() function" + return 0 +} + +# Validate the installation was successful +validate_installation() { + log_info "Entering validate_installation() function" + + local validation_failed=0 + + # Re-check all components after installation + if ! check_sgx_packages; then + log_info "VALIDATION FAILED: SGX packages not properly installed" + validation_failed=1 + fi + + if ! check_sgx_sdk; then + log_info "VALIDATION FAILED: SGX SDK not properly installed" + validation_failed=1 + fi + + if ! check_sgx_repo; then + log_info "VALIDATION FAILED: SGX repository not properly configured" + validation_failed=1 + fi + + if [ $validation_failed -eq 0 ]; then + log_info "VALIDATION SUCCESS: All SGX components properly installed" + else + log_info "VALIDATION FAILED: Some SGX components failed installation" + log_info "Exiting validate_installation() function" + return 1 + fi + + log_info "Exiting validate_installation() function" + return 0 +} + +# Clean up temporary files +cleanup() { + log_info "Entering cleanup() function" + + # Clean up any temporary files in /tmp related to SGX installation + if [ -f "/tmp/sgx_debian_local_repo.tgz" ]; then + log_info "Removing temporary SGX repository archive" + rm -f /tmp/sgx_debian_local_repo.tgz + fi + + # Additional cleanup can be added here as needed + log_info "Temporary file cleanup completed" + + log_info "Exiting cleanup() function" + return 0 +} + +# Initialize logging +init_log + +log_info "Starting idempotency checks..." + +# Check if everything is already installed +if check_sgx_packages && check_sgx_sdk && check_sgx_repo; then + log_info "Complete SGX installation detected - no action needed" + echo "Intel SGX for Application Developer is already installed and configured." + print_env_instructions + exit 0 +fi + +log_info "Partial or missing SGX installation detected - proceeding with installation" + +# Main installation flow using modular functions + +log_info "Starting Intel SGX for Application Developer installation..." + +# Execute installation steps in modular fashion +platform_detect +if [ $? -ne 0 ]; then + log_info "Platform detection failed" + exit 1 +fi + +install_packages +if [ $? -ne 0 ]; then + log_info "Package installation failed" + exit 1 +fi + +validate_installation +if [ $? -ne 0 ]; then + log_info "Installation validation failed" + exit 1 +fi + +cleanup +if [ $? -ne 0 ]; then + log_info "Cleanup failed" + exit 1 +fi + +cleanup +if [ $? -ne 0 ]; then + log_info "Cleanup failed" + exit 1 +fi + +echo "Intel SGX for Application Developer installation completed." +print_env_instructions diff --git a/core/config.h b/core/config.h index cb5db1d0c..31404deb9 100644 --- a/core/config.h +++ b/core/config.h @@ -84,7 +84,7 @@ #endif #define AOT_MAGIC_NUMBER 0x746f6100 -#define AOT_CURRENT_VERSION 5 +#define AOT_CURRENT_VERSION 6 #ifndef WASM_ENABLE_JIT #define WASM_ENABLE_JIT 0 diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 2f7e6c9f2..19985444d 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -307,7 +307,8 @@ loader_mmap(uint32 size, bool prot_exec, char *error_buf, uint32 error_buf_size) #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ || defined(BUILD_TARGET_RISCV64_LP64D) \ || defined(BUILD_TARGET_RISCV64_LP64) -#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) +#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) \ + && !defined(BH_PLATFORM_NUTTX) /* The mmapped AOT data and code in 64-bit targets had better be in range 0 to 2G, or aot loader may fail to apply some relocations, e.g., R_X86_64_32/R_X86_64_32S/R_X86_64_PC32/R_RISCV_32. @@ -981,7 +982,7 @@ destroy_init_expr(InitializerExpression *expr) #endif #if WASM_ENABLE_EXTENDED_CONST_EXPR != 0 - // free left expr and right expr for binary oprand + /* free left expr and right expr for binary operand */ if (!is_expr_binary_op(expr->init_expr_type)) { return; } @@ -3227,7 +3228,7 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group, if (!strncmp(symbol, AOT_FUNC_PREFIX, strlen(AOT_FUNC_PREFIX))) { p = symbol + strlen(AOT_FUNC_PREFIX); if (*p == '\0' - || (func_index = (uint32)atoi(p)) > module->func_count) { + || (func_index = (uint32)atoi(p)) >= module->func_count) { set_error_buf_v(error_buf, error_buf_size, "invalid import symbol %s", symbol); goto check_symbol_fail; @@ -3261,7 +3262,7 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group, strlen("_" AOT_FUNC_PREFIX))) { p = symbol + strlen("_" AOT_FUNC_PREFIX); if (*p == '\0' - || (func_index = (uint32)atoi(p)) > module->func_count) { + || (func_index = (uint32)atoi(p)) >= module->func_count) { set_error_buf_v(error_buf, error_buf_size, "invalid symbol %s", symbol); goto check_symbol_fail; @@ -3272,7 +3273,7 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group, strlen("_" AOT_FUNC_INTERNAL_PREFIX))) { p = symbol + strlen("_" AOT_FUNC_INTERNAL_PREFIX); if (*p == '\0' - || (func_index = (uint32)atoi(p)) > module->func_count) { + || (func_index = (uint32)atoi(p)) >= module->func_count) { set_error_buf_v(error_buf, error_buf_size, "invalid symbol %s", symbol); goto check_symbol_fail; @@ -3462,7 +3463,7 @@ do_data_relocation(AOTModule *module, AOTRelocationGroup *group, char *p = symbol + strlen(AOT_FUNC_PREFIX); uint32 func_index; if (*p == '\0' - || (func_index = (uint32)atoi(p)) > module->func_count) { + || (func_index = (uint32)atoi(p)) >= module->func_count) { set_error_buf_v(error_buf, error_buf_size, "invalid relocation symbol %s", symbol); return false; @@ -3871,7 +3872,7 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, read_uint32(buf, buf_end, offset32); relocation->relocation_offset = (uint64)offset32; read_uint32(buf, buf_end, addend32); - relocation->relocation_addend = (uint64)addend32; + relocation->relocation_addend = (int64)(int32)addend32; } read_uint32(buf, buf_end, relocation->relocation_type); read_uint32(buf, buf_end, symbol_index); diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 4368886a2..7f57b1adf 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1963,6 +1963,12 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, module_inst->e = (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset); extra = (AOTModuleInstanceExtra *)module_inst->e; +#if WASM_ENABLE_THREAD_MGR != 0 + if (os_mutex_init(&extra->common.exception_lock) != 0) { + wasm_runtime_free(module_inst); + return NULL; + } +#endif #if WASM_ENABLE_GC != 0 /* Initialize gc heap first since it may be used when initializing @@ -2353,6 +2359,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton); } +#if WASM_ENABLE_THREAD_MGR != 0 + os_mutex_destroy(&extra->common.exception_lock); +#endif + #if WASM_ENABLE_PERF_PROFILING != 0 if (module_inst->func_perf_profilings) wasm_runtime_free(module_inst->func_perf_profilings); @@ -2485,6 +2495,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, native stack to run the following codes before actually calling the aot function in invokeNative function. */ if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { + wasm_runtime_set_exec_env_tls(NULL); return false; } @@ -3256,6 +3267,12 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, bool ret = false; bh_assert(func_idx < aot_module->import_func_count); +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#include + __msan_unpoison(argv, (sizeof(uint32) * argc)); +#endif +#endif import_func = aot_module->import_funcs + func_idx; if (import_func->call_conv_wasm_c_api) func_ptr = @@ -4175,7 +4192,8 @@ aot_alloc_tiny_frame(WASMExecEnv *exec_env, uint32 func_index) { AOTTinyFrame *new_frame = (AOTTinyFrame *)exec_env->wasm_stack.top; - if ((uint8 *)new_frame > exec_env->wasm_stack.top_boundary) { + if ((uint8 *)new_frame + sizeof(AOTTinyFrame) + > exec_env->wasm_stack.top_boundary) { aot_set_exception((WASMModuleInstance *)exec_env->module_inst, "wasm operand stack overflow"); return false; @@ -4331,6 +4349,7 @@ aot_copy_callstack_tiny_frame(WASMExecEnv *exec_env, WASMCApiFrame *buffer, AOTTinyFrame *frame = (AOTTinyFrame *)(top - sizeof(AOTTinyFrame)); WASMCApiFrame record_frame; + memset(&record_frame, 0, sizeof(WASMCApiFrame)); while (frame && (uint8_t *)frame >= bottom && count < (skip_n + length)) { if (count < skip_n) { ++count; @@ -4373,6 +4392,7 @@ aot_copy_callstack_standard_frame(WASMExecEnv *exec_env, WASMCApiFrame *buffer, uint32 frame_size = (uint32)offsetof(AOTFrame, lp); WASMCApiFrame record_frame; + memset(&record_frame, 0, sizeof(WASMCApiFrame)); while (cur_frame && (uint8_t *)cur_frame >= bottom && (uint8_t *)cur_frame + frame_size <= top_boundary && count < (skip_n + length)) { @@ -4698,7 +4718,7 @@ static bool cmpxchg_ptr(void **ptr, void *old_val, void *new_val) { #if defined(os_atomic_cmpxchg) - return os_atomic_cmpxchg(ptr, &old_val, new_val); + return os_atomic_cmpxchg((_Atomic(void *) *)ptr, &old_val, new_val); #else /* TODO: add lock when thread-manager is enabled */ void *read = *ptr; diff --git a/core/iwasm/aot/iwasm_aot.cmake b/core/iwasm/aot/iwasm_aot.cmake index e6d56c43f..1084681ac 100644 --- a/core/iwasm/aot/iwasm_aot.cmake +++ b/core/iwasm/aot/iwasm_aot.cmake @@ -71,8 +71,8 @@ if ((WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") if (NOT zycore_POPULATED) message ("-- Fetching zycore ..") FetchContent_Populate(zycore) - include_directories("${zycore_SOURCE_DIR}/include") - include_directories("${zycore_BINARY_DIR}") + include_directories(SYSTEM "${zycore_SOURCE_DIR}/include") + include_directories(SYSTEM "${zycore_BINARY_DIR}") add_definitions(-DZYCORE_STATIC_BUILD=1) add_subdirectory(${zycore_SOURCE_DIR} ${zycore_BINARY_DIR} EXCLUDE_FROM_ALL) file (GLOB_RECURSE c_source_zycore ${zycore_SOURCE_DIR}/src/*.c) @@ -92,9 +92,9 @@ if ((WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") option(ZYDIS_BUILD_EXAMPLES "" OFF) option(ZYDIS_BUILD_MAN "" OFF) option(ZYDIS_BUILD_DOXYGEN "" OFF) - include_directories("${zydis_BINARY_DIR}") - include_directories("${zydis_SOURCE_DIR}/include") - include_directories("${zydis_SOURCE_DIR}/src") + include_directories(SYSTEM "${zydis_BINARY_DIR}") + include_directories(SYSTEM "${zydis_SOURCE_DIR}/include") + include_directories(SYSTEM "${zydis_SOURCE_DIR}/src") add_definitions(-DZYDIS_STATIC_BUILD=1) add_subdirectory(${zydis_SOURCE_DIR} ${zydis_BINARY_DIR} EXCLUDE_FROM_ALL) file (GLOB_RECURSE c_source_zydis ${zydis_SOURCE_DIR}/src/*.c) diff --git a/core/iwasm/common/gc/gc_common.c b/core/iwasm/common/gc/gc_common.c index 5cc869a65..7c2c15433 100644 --- a/core/iwasm/common/gc/gc_common.c +++ b/core/iwasm/common/gc/gc_common.c @@ -352,7 +352,15 @@ wasm_ref_type_set_heap_type(wasm_ref_type_t *ref_type, bool nullable, { bool ret; - bh_assert(heap_type <= HEAP_TYPE_FUNC && heap_type >= HEAP_TYPE_NONE); + bh_assert((heap_type >= HEAP_TYPE_ARRAY && heap_type <= HEAP_TYPE_NOFUNC) +#if WASM_ENABLE_STRINGREF != 0 + || heap_type == HEAP_TYPE_STRINGREF + || heap_type == HEAP_TYPE_STRINGVIEWWTF8 + || heap_type == HEAP_TYPE_STRINGVIEWWTF16 + || heap_type == HEAP_TYPE_STRINGVIEWITER +#endif + ); + ref_type->value_type = nullable ? VALUE_TYPE_HT_NULLABLE_REF : VALUE_TYPE_HT_NON_NULLABLE_REF; ref_type->nullable = nullable; diff --git a/core/iwasm/common/gc/gc_type.h b/core/iwasm/common/gc/gc_type.h index 919c8e501..29b171e5a 100644 --- a/core/iwasm/common/gc/gc_type.h +++ b/core/iwasm/common/gc/gc_type.h @@ -269,18 +269,20 @@ wasm_is_refheaptype_typeidx(const RefHeapType_Common *ref_heap_type) return ref_heap_type->heap_type >= 0 ? true : false; } -/* Whether a ref heap type is a common type: func/any/eq/i31/data, - not (type i) or (rtt n i) or (rtt i) */ +/* Whether a ref heap type is a common type: + func/any/eq/i31/data/nofunc/noextern, not (type i) or (rtt n i) or (rtt i) */ inline static bool wasm_is_refheaptype_common(const RefHeapType_Common *ref_heap_type) { return ((ref_heap_type->heap_type >= (int32)HEAP_TYPE_ARRAY - && ref_heap_type->heap_type <= (int32)HEAP_TYPE_NONE) + && ref_heap_type->heap_type <= (int32)HEAP_TYPE_NOFUNC) #if WASM_ENABLE_STRINGREF != 0 - || (ref_heap_type->heap_type >= (int32)HEAP_TYPE_STRINGVIEWITER - && ref_heap_type->heap_type <= (int32)HEAP_TYPE_I31) + || ref_heap_type->heap_type == (int32)HEAP_TYPE_STRINGREF + || ref_heap_type->heap_type == (int32)HEAP_TYPE_STRINGVIEWWTF8 + || ref_heap_type->heap_type == (int32)HEAP_TYPE_STRINGVIEWWTF16 + || ref_heap_type->heap_type == (int32)HEAP_TYPE_STRINGVIEWITER #endif - ) + ) ? true : false; } diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 269ec5776..f44b967b1 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -3459,9 +3459,16 @@ failed: wasm_runtime_free(argv); #if WASM_ENABLE_DUMP_CALL_STACK != 0 && WASM_ENABLE_THREAD_MGR != 0 - WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); - cluster_frames = &cluster->exception_frames; - wasm_cluster_traverse_lock(exec_env); + WASMCluster *cluster = NULL; + if (exec_env) { + cluster = wasm_exec_env_get_cluster(exec_env); + } + if (cluster) { + cluster_frames = &cluster->exception_frames; + } + if (cluster_frames) { + wasm_cluster_traverse_lock(exec_env); + } #endif wasm_trap_t *trap = wasm_trap_new_internal( @@ -3469,7 +3476,9 @@ failed: wasm_runtime_get_exception(func->inst_comm_rt), cluster_frames); #if WASM_ENABLE_DUMP_CALL_STACK != 0 && WASM_ENABLE_THREAD_MGR != 0 - wasm_cluster_traverse_unlock(exec_env); + if (cluster_frames) { + wasm_cluster_traverse_unlock(exec_env); + } #endif return trap; } diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 10c651bc9..628a03237 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -162,10 +162,73 @@ runtime_malloc(uint64 size) return mem; } +static void +destroy_runtime_managed_shared_heap(WASMSharedHeap *heap) +{ + uint64 map_size; + + mem_allocator_destroy(heap->heap_handle); + wasm_runtime_free(heap->heap_handle); + heap->heap_handle = NULL; + +#ifndef OS_ENABLE_HW_BOUND_CHECK + map_size = heap->size; +#else + map_size = 8 * (uint64)BH_GB; +#endif + wasm_munmap_linear_memory(heap->base_addr, heap->size, map_size); + heap->base_addr = NULL; +} + +static bool +create_runtime_managed_shared_heap(WASMSharedHeap *heap, + uint64 heap_struct_size) +{ + uint64 map_size; + + heap->heap_handle = runtime_malloc(mem_allocator_get_heap_struct_size()); + if (!heap->heap_handle) { + heap->base_addr = NULL; + return false; + } + +#ifndef OS_ENABLE_HW_BOUND_CHECK + map_size = heap->size; +#else + /* Totally 8G is mapped, the opcode load/store address range is 0 to 8G: + * ea = i + memarg.offset + * both i and memarg.offset are u32 in range 0 to 4G + * so the range of ea is 0 to 8G + */ + map_size = 8 * (uint64)BH_GB; +#endif + + if (!(heap->base_addr = wasm_mmap_linear_memory(map_size, heap->size))) { + goto fail1; + } + if (!mem_allocator_create_with_struct_and_pool( + heap->heap_handle, heap_struct_size, heap->base_addr, heap->size)) { + LOG_WARNING("init share heap failed"); + goto fail2; + } + + LOG_VERBOSE("Create runtime managed shared heap %p with size %u", + heap->base_addr, (uint32)heap->size); + return true; + +fail2: + wasm_munmap_linear_memory(heap->base_addr, heap->size, map_size); +fail1: + wasm_runtime_free(heap->heap_handle); + heap->heap_handle = NULL; + heap->base_addr = NULL; + return false; +} + WASMSharedHeap * wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args) { - uint64 heap_struct_size = sizeof(WASMSharedHeap), map_size; + uint64 heap_struct_size = sizeof(WASMSharedHeap); uint32 size = init_args->size; WASMSharedHeap *heap; @@ -178,6 +241,11 @@ wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args) } size = align_uint(size, os_getpagesize()); + if (size != init_args->size) { + LOG_WARNING("Shared heap size aligned from %u to %u", init_args->size, + size); + } + if (size > APP_HEAP_SIZE_MAX || size < APP_HEAP_SIZE_MIN) { LOG_WARNING("Invalid size of shared heap"); goto fail2; @@ -203,32 +271,9 @@ wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args) heap->base_addr, size); } else { - if (!(heap->heap_handle = - runtime_malloc(mem_allocator_get_heap_struct_size()))) { + if (!create_runtime_managed_shared_heap(heap, heap_struct_size)) { goto fail2; } - -#ifndef OS_ENABLE_HW_BOUND_CHECK - map_size = size; -#else - /* Totally 8G is mapped, the opcode load/store address range is 0 to 8G: - * ea = i + memarg.offset - * both i and memarg.offset are u32 in range 0 to 4G - * so the range of ea is 0 to 8G - */ - map_size = 8 * (uint64)BH_GB; -#endif - - if (!(heap->base_addr = wasm_mmap_linear_memory(map_size, size))) { - goto fail3; - } - if (!mem_allocator_create_with_struct_and_pool( - heap->heap_handle, heap_struct_size, heap->base_addr, size)) { - LOG_WARNING("init share heap failed"); - goto fail4; - } - LOG_VERBOSE("Create pool shared heap %p with size %u", heap->base_addr, - size); } os_mutex_lock(&shared_heap_list_lock); @@ -242,10 +287,6 @@ wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args) os_mutex_unlock(&shared_heap_list_lock); return heap; -fail4: - wasm_munmap_linear_memory(heap->base_addr, size, map_size); -fail3: - wasm_runtime_free(heap->heap_handle); fail2: wasm_runtime_free(heap); fail1: @@ -339,6 +380,40 @@ wasm_runtime_unchain_shared_heaps(WASMSharedHeap *head, bool entire_chain) return cur; } +bool +wasm_runtime_reset_shared_heap_chain(WASMSharedHeap *shared_heap) +{ + uint64 heap_struct_size = sizeof(WASMSharedHeap); + WASMSharedHeap *cur; + + if (!shared_heap) { + return false; + } + + os_mutex_lock(&shared_heap_list_lock); + if (shared_heap->attached_count != 0) { + os_mutex_unlock(&shared_heap_list_lock); + return false; + } + + for (cur = shared_heap; cur; cur = cur->chain_next) { + if (cur->heap_handle) { + destroy_runtime_managed_shared_heap(cur); + + if (!create_runtime_managed_shared_heap(cur, heap_struct_size)) { + os_mutex_unlock(&shared_heap_list_lock); + return false; + } + } + else { + memset(cur->base_addr, 0, (size_t)cur->size); + } + } + + os_mutex_unlock(&shared_heap_list_lock); + return true; +} + static uint8 * get_last_used_shared_heap_base_addr_adj(WASMModuleInstanceCommon *module_inst) { @@ -726,10 +801,9 @@ wasm_runtime_shared_heap_malloc(WASMModuleInstanceCommon *module_inst, *p_native_addr = native_addr; } - return memory->is_memory64 - ? shared_heap->start_off_mem64 - : shared_heap->start_off_mem32 - + ((uint8 *)native_addr - shared_heap->base_addr); + return (memory->is_memory64 ? shared_heap->start_off_mem64 + : shared_heap->start_off_mem32) + + (uintptr_t)((uint8 *)native_addr - shared_heap->base_addr); } void @@ -830,14 +904,7 @@ destroy_shared_heaps() cur = heap; heap = heap->next; if (cur->heap_handle) { - mem_allocator_destroy(cur->heap_handle); - wasm_runtime_free(cur->heap_handle); -#ifndef OS_ENABLE_HW_BOUND_CHECK - map_size = cur->size; -#else - map_size = 8 * (uint64)BH_GB; -#endif - wasm_munmap_linear_memory(cur->base_addr, cur->size, map_size); + destroy_runtime_managed_shared_heap(cur); } wasm_runtime_free(cur); } diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index b79ed4a6c..a96e25040 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -95,6 +95,9 @@ wasm_runtime_chain_shared_heaps(WASMSharedHeap *head, WASMSharedHeap *body); WASMSharedHeap * wasm_runtime_unchain_shared_heaps(WASMSharedHeap *head, bool entire_chain); +bool +wasm_runtime_reset_shared_heap_chain(WASMSharedHeap *shared_heap); + bool wasm_runtime_attach_shared_heap(WASMModuleInstanceCommon *module_inst, WASMSharedHeap *shared_heap); diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 2b49c052e..f33fbfa7e 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -703,39 +703,44 @@ wasm_native_destroy() #if WASM_ENABLE_QUICK_AOT_ENTRY != 0 static void -invoke_no_args_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_no_args_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *) = func_ptr; native_code(exec_env); + (void)argv; + (void)argv_ret; } static void -invoke_no_args_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_no_args_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *) = func_ptr; - argv_ret[0] = native_code(exec_env); + argv_ret[0] = (uint32)native_code(exec_env); + (void)argv; } static void -invoke_no_args_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_no_args_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *) = func_ptr; int64 ret = native_code(exec_env); PUT_I64_TO_ADDR(argv_ret, ret); + (void)argv; } static void -invoke_i_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_i_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32) = func_ptr; native_code(exec_env, argv[0]); + (void)argv_ret; } static void -invoke_i_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_i_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0]); } static void -invoke_i_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_i_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32) = func_ptr; int64 ret = native_code(exec_env, argv[0]); @@ -743,19 +748,20 @@ invoke_i_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_I_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_I_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv)); + (void)argv_ret; } static void -invoke_I_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_I_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv)); } static void -invoke_I_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_I_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv)); @@ -763,19 +769,20 @@ invoke_I_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_ii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_ii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int32) = func_ptr; native_code(exec_env, argv[0], argv[1]); + (void)argv_ret; } static void -invoke_ii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_ii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1]); } static void -invoke_ii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_ii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int32) = func_ptr; int64 ret = native_code(exec_env, argv[0], argv[1]); @@ -783,20 +790,21 @@ invoke_ii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iI_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int64) = func_ptr; native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1)); + (void)argv_ret; } static void -invoke_iI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iI_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int64) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1)); } static void -invoke_iI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iI_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int64) = func_ptr; int64 ret = @@ -805,20 +813,21 @@ invoke_iI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_Ii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Ii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int32) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2]); + (void)argv_ret; } static void -invoke_Ii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Ii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int32) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2]); } static void -invoke_Ii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Ii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int32) = func_ptr; int64 ret = @@ -827,21 +836,22 @@ invoke_Ii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_II_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_II_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int64) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2)); + (void)argv_ret; } static void -invoke_II_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_II_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int64) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2)); } static void -invoke_II_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_II_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int64) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -850,19 +860,20 @@ invoke_II_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int32, int32) = func_ptr; native_code(exec_env, argv[0], argv[1], argv[2]); + (void)argv_ret; } static void -invoke_iii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int32, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2]); } static void -invoke_iii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int32, int32) = func_ptr; int64 ret = native_code(exec_env, argv[0], argv[1], argv[2]); @@ -870,21 +881,22 @@ invoke_iii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiI_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int32, int64) = func_ptr; native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR((uint32 *)argv + 2)); + (void)argv_ret; } static void -invoke_iiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiI_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int32, int64) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR((uint32 *)argv + 2)); } static void -invoke_iiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiI_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int32, int64) = func_ptr; int64 ret = native_code(exec_env, argv[0], argv[1], @@ -893,21 +905,22 @@ invoke_iiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIi_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int64, int32) = func_ptr; native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), argv[3]); + (void)argv_ret; } static void -invoke_iIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIi_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int64, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), argv[3]); } static void -invoke_iIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIi_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int64, int32) = func_ptr; int64 ret = native_code(exec_env, argv[0], @@ -916,14 +929,15 @@ invoke_iIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iII_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int64, int64) = func_ptr; native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), GET_I64_FROM_ADDR((uint32 *)argv + 3)); + (void)argv_ret; } static void -invoke_iII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iII_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int64, int64) = func_ptr; argv_ret[0] = @@ -931,7 +945,7 @@ invoke_iII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 3)); } static void -invoke_iII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iII_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int64, int64) = func_ptr; int64 ret = @@ -941,20 +955,21 @@ invoke_iII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_Iii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Iii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int32, int32) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], argv[3]); + (void)argv_ret; } static void -invoke_Iii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Iii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int32, int32) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], argv[3]); } static void -invoke_Iii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Iii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int32, int32) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -963,21 +978,22 @@ invoke_Iii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiI_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int32, int64) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3)); + (void)argv_ret; } static void -invoke_IiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiI_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int32, int64) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3)); } static void -invoke_IiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiI_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int32, int64) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -986,21 +1002,22 @@ invoke_IiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIi_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int64, int32) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); + (void)argv_ret; } static void -invoke_IIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIi_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int64, int32) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); } static void -invoke_IIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIi_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int64, int32) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1009,15 +1026,16 @@ invoke_IIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_III_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_III_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int64, int64) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2), GET_I64_FROM_ADDR((uint32 *)argv + 4)); + (void)argv_ret; } static void -invoke_III_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_III_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int64, int64) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1025,7 +1043,7 @@ invoke_III_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 4)); } static void -invoke_III_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_III_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int64, int64) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1035,19 +1053,20 @@ invoke_III_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iiii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int32, int32, int32) = func_ptr; native_code(exec_env, argv[0], argv[1], argv[2], argv[3]); + (void)argv_ret; } static void -invoke_iiii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int32, int32, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2], argv[3]); } static void -invoke_iiii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int32, int32, int32) = func_ptr; int64 ret = native_code(exec_env, argv[0], argv[1], argv[2], argv[3]); @@ -1055,21 +1074,22 @@ invoke_iiii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iiiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiiI_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int32, int32, int64) = func_ptr; native_code(exec_env, argv[0], argv[1], argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3)); + (void)argv_ret; } static void -invoke_iiiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiiI_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int32, int32, int64) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3)); } static void -invoke_iiiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiiI_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int32, int32, int64) = func_ptr; int64 ret = native_code(exec_env, argv[0], argv[1], argv[2], @@ -1078,21 +1098,22 @@ invoke_iiiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iiIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiIi_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int32, int64, int32) = func_ptr; native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); + (void)argv_ret; } static void -invoke_iiIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiIi_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int32, int64, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); } static void -invoke_iiIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiIi_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int32, int64, int32) = func_ptr; int64 ret = native_code(exec_env, argv[0], argv[1], @@ -1101,15 +1122,16 @@ invoke_iiIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iiII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiII_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int32, int64, int64) = func_ptr; native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR((uint32 *)argv + 2), GET_I64_FROM_ADDR((uint32 *)argv + 4)); + (void)argv_ret; } static void -invoke_iiII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiII_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int32, int64, int64) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], @@ -1117,7 +1139,7 @@ invoke_iiII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 4)); } static void -invoke_iiII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiII_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int32, int64, int64) = func_ptr; int64 ret = native_code(exec_env, argv[0], argv[1], @@ -1127,14 +1149,15 @@ invoke_iiII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iIii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int64, int32, int32) = func_ptr; native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), argv[3], argv[4]); + (void)argv_ret; } static void -invoke_iIii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int64, int32, int32) = func_ptr; argv_ret[0] = @@ -1142,7 +1165,7 @@ invoke_iIii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) argv[3], argv[4]); } static void -invoke_iIii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int64, int32, int32) = func_ptr; int64 ret = @@ -1152,14 +1175,15 @@ invoke_iIii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iIiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIiI_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int64, int32, int64) = func_ptr; native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), argv[3], GET_I64_FROM_ADDR((uint32 *)argv + 4)); + (void)argv_ret; } static void -invoke_iIiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIiI_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int64, int32, int64) = func_ptr; argv_ret[0] = @@ -1167,7 +1191,7 @@ invoke_iIiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) argv[3], GET_I64_FROM_ADDR((uint32 *)argv + 4)); } static void -invoke_iIiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIiI_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int64, int32, int64) = func_ptr; int64 ret = @@ -1177,14 +1201,15 @@ invoke_iIiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iIIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIIi_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int64, int64, int32) = func_ptr; native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); + (void)argv_ret; } static void -invoke_iIIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIIi_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int64, int64, int32) = func_ptr; argv_ret[0] = @@ -1192,7 +1217,7 @@ invoke_iIIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); } static void -invoke_iIIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIIi_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int64, int64, int32) = func_ptr; int64 ret = @@ -1202,15 +1227,16 @@ invoke_iIIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iIII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIII_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int64, int64, int64) = func_ptr; native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), GET_I64_FROM_ADDR((uint32 *)argv + 3), GET_I64_FROM_ADDR((uint32 *)argv + 5)); + (void)argv_ret; } static void -invoke_iIII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIII_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int64, int64, int64) = func_ptr; argv_ret[0] = @@ -1219,7 +1245,7 @@ invoke_iIII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 5)); } static void -invoke_iIII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iIII_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int64, int64, int64) = func_ptr; int64 ret = @@ -1230,21 +1256,22 @@ invoke_iIII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_Iiii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Iiii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int32, int32, int32) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], argv[3], argv[4]); + (void)argv_ret; } static void -invoke_Iiii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Iiii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int32, int32, int32) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], argv[3], argv[4]); } static void -invoke_Iiii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_Iiii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int32, int32, int32) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1253,15 +1280,16 @@ invoke_Iiii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IiiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiiI_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int32, int32, int64) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], argv[3], GET_I64_FROM_ADDR((uint32 *)argv + 4)); + (void)argv_ret; } static void -invoke_IiiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiiI_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int32, int32, int64) = func_ptr; argv_ret[0] = @@ -1270,7 +1298,7 @@ invoke_IiiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IiiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiiI_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int32, int32, int64) = func_ptr; int64 ret = @@ -1280,14 +1308,15 @@ invoke_IiiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IiIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiIi_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int32, int64, int32) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); + (void)argv_ret; } static void -invoke_IiIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiIi_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int32, int64, int32) = func_ptr; argv_ret[0] = @@ -1295,7 +1324,7 @@ invoke_IiIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); } static void -invoke_IiIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiIi_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int32, int64, int32) = func_ptr; int64 ret = @@ -1305,15 +1334,16 @@ invoke_IiIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IiII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiII_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int32, int64, int64) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3), GET_I64_FROM_ADDR((uint32 *)argv + 5)); + (void)argv_ret; } static void -invoke_IiII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiII_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int32, int64, int64) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1321,7 +1351,7 @@ invoke_IiII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 5)); } static void -invoke_IiII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IiII_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int32, int64, int64) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1331,14 +1361,15 @@ invoke_IiII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IIii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int64, int32, int32) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], argv[5]); + (void)argv_ret; } static void -invoke_IIii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int64, int32, int32) = func_ptr; argv_ret[0] = @@ -1346,7 +1377,7 @@ invoke_IIii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], argv[5]); } static void -invoke_IIii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int64, int32, int32) = func_ptr; int64 ret = @@ -1356,15 +1387,16 @@ invoke_IIii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IIiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIiI_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int64, int32, int64) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], GET_I64_FROM_ADDR((uint32 *)argv + 5)); + (void)argv_ret; } static void -invoke_IIiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIiI_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int64, int32, int64) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1372,7 +1404,7 @@ invoke_IIiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 5)); } static void -invoke_IIiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIiI_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int64, int32, int64) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1382,15 +1414,16 @@ invoke_IIiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IIIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIIi_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int64, int64, int32) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2), GET_I64_FROM_ADDR((uint32 *)argv + 4), argv[6]); + (void)argv_ret; } static void -invoke_IIIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIIi_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int64, int64, int32) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1398,7 +1431,7 @@ invoke_IIIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 4), argv[6]); } static void -invoke_IIIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIIi_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int64, int64, int32) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1408,16 +1441,17 @@ invoke_IIIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_IIII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIII_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int64, int64, int64, int64) = func_ptr; native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), GET_I64_FROM_ADDR((uint32 *)argv + 2), GET_I64_FROM_ADDR((uint32 *)argv + 4), GET_I64_FROM_ADDR((uint32 *)argv + 6)); + (void)argv_ret; } static void -invoke_IIII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIII_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int64, int64, int64, int64) = func_ptr; argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1426,7 +1460,7 @@ invoke_IIII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) GET_I64_FROM_ADDR((uint32 *)argv + 6)); } static void -invoke_IIII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_IIII_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int64, int64, int64, int64) = func_ptr; int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), @@ -1437,14 +1471,15 @@ invoke_IIII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) } static void -invoke_iiiii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiiii_v(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { void (*native_code)(WASMExecEnv *, int32, int32, int32, int32, int32) = func_ptr; native_code(exec_env, argv[0], argv[1], argv[2], argv[3], argv[4]); + (void)argv_ret; } static void -invoke_iiiii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiiii_i(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int32 (*native_code)(WASMExecEnv *, int32, int32, int32, int32, int32) = func_ptr; @@ -1452,7 +1487,7 @@ invoke_iiiii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) native_code(exec_env, argv[0], argv[1], argv[2], argv[3], argv[4]); } static void -invoke_iiiii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +invoke_iiiii_I(void *func_ptr, void *exec_env, uint32 *argv, uint32 *argv_ret) { int64 (*native_code)(WASMExecEnv *, int32, int32, int32, int32, int32) = func_ptr; diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 61b8e7796..8d3522d9a 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -415,19 +415,39 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) } #endif /* end of BH_PLATFORM_WINDOWS */ +#ifdef BH_PLATFORM_WINDOWS +static PVOID runtime_exception_handler_handle = NULL; +static int32 runtime_exception_handler_ref_count = 0; +static korp_mutex runtime_exception_handler_lock = NULL; +#endif + static bool runtime_signal_init() { #ifndef BH_PLATFORM_WINDOWS return os_thread_signal_init(runtime_signal_handler) == 0 ? true : false; #else - if (os_thread_signal_init() != 0) - return false; + os_mutex_lock(&runtime_exception_handler_lock); - if (!AddVectoredExceptionHandler(1, runtime_exception_handler)) { - os_thread_signal_destroy(); + if (os_thread_signal_init() != 0) { + os_mutex_unlock(&runtime_exception_handler_lock); return false; } + + if (runtime_exception_handler_ref_count == 0) { + runtime_exception_handler_handle = + AddVectoredExceptionHandler(1, runtime_exception_handler); + } + + if (!runtime_exception_handler_handle) { + os_thread_signal_destroy(); + os_mutex_unlock(&runtime_exception_handler_lock); + return false; + } + + runtime_exception_handler_ref_count++; + + os_mutex_unlock(&runtime_exception_handler_lock); #endif return true; } @@ -436,7 +456,25 @@ static void runtime_signal_destroy() { #ifdef BH_PLATFORM_WINDOWS - RemoveVectoredExceptionHandler(runtime_exception_handler); + os_mutex_lock(&runtime_exception_handler_lock); + + if (runtime_exception_handler_ref_count > 0) { + runtime_exception_handler_ref_count--; + } + + if (runtime_exception_handler_ref_count == 0 + && runtime_exception_handler_handle) { + if (RemoveVectoredExceptionHandler(runtime_exception_handler_handle)) { + runtime_exception_handler_handle = NULL; + } + else { + /* Keep the handle so future init/destroy cycles can retry remove. + * Clearing it here may leave a live callback registered forever. */ + runtime_exception_handler_ref_count = 1; + } + } + + os_mutex_unlock(&runtime_exception_handler_lock); #endif os_thread_signal_destroy(); } @@ -4001,7 +4039,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, /* addr_pool(textual) -> apool */ for (i = 0; i < addr_pool_size; i++) { - char *cp, *address, *mask; + char *cp, *address, *mask, *nextptr, *endptr; + long mask_val; bool ret = false; cp = bh_strdup(addr_pool[i]); @@ -4011,18 +4050,35 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, goto fail; } - address = strtok(cp, "/"); - mask = strtok(NULL, "/"); + address = bh_strtok_r(cp, "/", &nextptr); + mask = bh_strtok_r(NULL, "/", &nextptr); if (!mask) { snprintf(error_buf, error_buf_size, "Invalid address pool entry: %s, must be in the format of " "ADDRESS/MASK", addr_pool[i]); + wasm_runtime_free(cp); goto fail; } - ret = addr_pool_insert(apool, address, (uint8)atoi(mask)); + errno = 0; + mask_val = strtol(mask, &endptr, 10); + + if (mask == endptr || *endptr != '\0') { + snprintf(error_buf, error_buf_size, + "Invalid address pool entry: mask must be a number"); + wasm_runtime_free(cp); + goto fail; + } + if (errno != 0 || mask_val < 0) { + snprintf(error_buf, error_buf_size, + "Init wasi environment failed: invalid mask number"); + wasm_runtime_free(cp); + goto fail; + } + + ret = addr_pool_insert(apool, address, (uint8)mask_val); wasm_runtime_free(cp); if (!ret) { set_error_buf(error_buf, error_buf_size, @@ -8183,3 +8239,18 @@ wasm_runtime_check_and_update_last_used_shared_heap( return false; } #endif + +WASMModuleInstanceExtraCommon * +GetModuleInstanceExtraCommon(WASMModuleInstance *module_inst) +{ +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + return &((AOTModuleInstanceExtra *)module_inst->e)->common; + } + else { + return &module_inst->e->common; + } +#else + return &module_inst->e->common; +#endif +} diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 64f026255..df675b0bf 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -1472,6 +1472,8 @@ WASM_RUNTIME_API_EXTERN void wasm_runtime_set_wasi_nn_registry(WASMModuleInstanceCommon *module_inst_comm, WASINNRegistry *wasi_nn_ctx); #endif +struct WASMModuleInstanceExtraCommon * +GetModuleInstanceExtraCommon(struct WASMModuleInstance *module_inst); #ifdef __cplusplus } diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index f5bd859df..420096c64 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -676,7 +676,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, *alignp = max_align; } else { - unsigned int align = 1 << (shift - 1); + unsigned int align = 1U << (shift - 1); if (align > max_align) { align = max_align; } diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index ab351e6d4..4e8fd2cf5 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -3005,6 +3005,10 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) else vendor_sys = "-pc-windows-"; } + else if (!strcmp(abi, "darwin") || !strcmp(abi, "macho")) { + /* macOS/Darwin: x18 is reserved by Apple */ + vendor_sys = "-apple-"; + } else { if (is_baremetal_target(arch, cpu, abi)) vendor_sys = "-unknown-none-"; @@ -3050,6 +3054,14 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) if (!abi) abi = "gnu"; } + else if (strstr(default_triple, "darwin") + || strstr(default_triple, "apple")) { + /* macOS/Darwin: x18 is reserved by Apple, must use correct + * triple to prevent LLVM from using it */ + vendor_sys = "-apple-darwin"; + if (!abi) + abi = ""; + } else { vendor_sys = "-pc-linux-"; if (!abi) @@ -3139,6 +3151,30 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) if (!features) features = ""; +#if (defined(__APPLE__) || defined(__MACH__)) && defined(BUILD_TARGET_AARCH64) + /* On macOS ARM64, x18 is reserved by Apple for TLS. Even though we're + * generating ELF (Linux-style) AOT files, we must tell LLVM to not + * use x18, otherwise the AOT code will crash when running on macOS. */ + { + bool is_aarch64 = false; + if (arch && !strncmp(arch, "aarch64", 7)) + is_aarch64 = true; + else if (triple_norm && strstr(triple_norm, "aarch64")) + is_aarch64 = true; + + if (is_aarch64) { + if (features[0] != '\0') { + snprintf(features_buf, sizeof(features_buf), + "%s,+reserve-x18", features); + features = features_buf; + } + else { + features = "+reserve-x18"; + } + } + } +#endif + /* Get target with triple, note that LLVMGetTargetFromTriple() return 0 when success, but not true. */ if (LLVMGetTargetFromTriple(triple_norm, &target, &err) != 0) { diff --git a/core/iwasm/compilation/aot_orc_extra2.cpp b/core/iwasm/compilation/aot_orc_extra2.cpp index 180e54050..2979737e7 100644 --- a/core/iwasm/compilation/aot_orc_extra2.cpp +++ b/core/iwasm/compilation/aot_orc_extra2.cpp @@ -85,6 +85,7 @@ MyPassManager::add(llvm::Pass *P) // a hack to avoid having a copy of the whole addPassesToEmitMC. // we want to add PrintStackSizes before FreeMachineFunctionPass. if (P->getPassName() == "Free MachineFunction") { + delete P; return; } llvm::legacy::PassManager::add(P); @@ -123,7 +124,7 @@ MyCompiler::operator()(llvm::Module &M) M.getModuleIdentifier() + "-jitted-objectbuffer"); #endif - return std::move(ObjBuffer); + return ObjBuffer; } DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::orc::LLLazyJITBuilder, diff --git a/core/iwasm/fast-jit/iwasm_fast_jit.cmake b/core/iwasm/fast-jit/iwasm_fast_jit.cmake index 676258075..619866598 100644 --- a/core/iwasm/fast-jit/iwasm_fast_jit.cmake +++ b/core/iwasm/fast-jit/iwasm_fast_jit.cmake @@ -49,7 +49,7 @@ if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") add_definitions(-DASMJIT_NO_INTRINSICS) add_definitions(-DASMJIT_NO_AARCH64) add_definitions(-DASMJIT_NO_AARCH32) - include_directories("${asmjit_SOURCE_DIR}/src") + include_directories(SYSTEM "${asmjit_SOURCE_DIR}/src") add_subdirectory(${asmjit_SOURCE_DIR} ${asmjit_BINARY_DIR} EXCLUDE_FROM_ALL) file (GLOB_RECURSE cpp_source_asmjit ${asmjit_SOURCE_DIR}/src/asmjit/core/*.cpp @@ -67,8 +67,8 @@ if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") FetchContent_Populate(zycore) option(ZYDIS_BUILD_TOOLS "" OFF) option(ZYDIS_BUILD_EXAMPLES "" OFF) - include_directories("${zycore_SOURCE_DIR}/include") - include_directories("${zycore_BINARY_DIR}") + include_directories(SYSTEM "${zycore_SOURCE_DIR}/include") + include_directories(SYSTEM "${zycore_BINARY_DIR}") add_subdirectory(${zycore_SOURCE_DIR} ${zycore_BINARY_DIR} EXCLUDE_FROM_ALL) file (GLOB_RECURSE c_source_zycore ${zycore_SOURCE_DIR}/src/*.c) endif () @@ -83,9 +83,9 @@ if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") FetchContent_Populate(zydis) option(ZYDIS_BUILD_TOOLS "" OFF) option(ZYDIS_BUILD_EXAMPLES "" OFF) - include_directories("${zydis_BINARY_DIR}") - include_directories("${zydis_SOURCE_DIR}/include") - include_directories("${zydis_SOURCE_DIR}/src") + include_directories(SYSTEM "${zydis_BINARY_DIR}") + include_directories(SYSTEM "${zydis_SOURCE_DIR}/include") + include_directories(SYSTEM "${zydis_SOURCE_DIR}/src") add_subdirectory(${zydis_SOURCE_DIR} ${zydis_BINARY_DIR} EXCLUDE_FROM_ALL) file (GLOB_RECURSE c_source_zydis ${zydis_SOURCE_DIR}/src/*.c) endif () diff --git a/core/iwasm/include/gc_export.h b/core/iwasm/include/gc_export.h index f7426f41d..bf2c36d60 100644 --- a/core/iwasm/include/gc_export.h +++ b/core/iwasm/include/gc_export.h @@ -51,16 +51,21 @@ typedef enum wasm_value_type_enum { typedef int32_t wasm_heap_type_t; typedef enum wasm_heap_type_enum { + HEAP_TYPE_NOFUNC = -0x0D, + HEAP_TYPE_NOEXTERN = -0x0E, + HEAP_TYPE_NONE = -0x0F, HEAP_TYPE_FUNC = -0x10, HEAP_TYPE_EXTERN = -0x11, HEAP_TYPE_ANY = -0x12, HEAP_TYPE_EQ = -0x13, - HEAP_TYPE_I31 = -0x16, - HEAP_TYPE_NOFUNC = -0x17, - HEAP_TYPE_NOEXTERN = -0x18, - HEAP_TYPE_STRUCT = -0x19, - HEAP_TYPE_ARRAY = -0x1A, - HEAP_TYPE_NONE = -0x1B + HEAP_TYPE_I31 = -0x14, + HEAP_TYPE_STRUCT = -0x15, + HEAP_TYPE_ARRAY = -0x16, + /* Stringref Types */ + HEAP_TYPE_STRINGREF = -0x19, + HEAP_TYPE_STRINGVIEWWTF8 = -0x1A, + HEAP_TYPE_STRINGVIEWWTF16 = -0x1E, + HEAP_TYPE_STRINGVIEWITER = -0x1F } wasm_heap_type_enum; struct WASMObject; diff --git a/core/iwasm/include/wasm_c_api.h b/core/iwasm/include/wasm_c_api.h index 241a0eec8..00920adcb 100644 --- a/core/iwasm/include/wasm_c_api.h +++ b/core/iwasm/include/wasm_c_api.h @@ -22,6 +22,8 @@ #else #define WASM_API_EXTERN __declspec(dllimport) #endif +#elif defined(__GNUC__) || defined(__clang__) +#define WASM_API_EXTERN __attribute__((visibility("default"))) #else #define WASM_API_EXTERN #endif diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 4b9ddea98..844a56e18 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -2456,6 +2456,17 @@ wasm_runtime_chain_shared_heaps(wasm_shared_heap_t head, wasm_shared_heap_t wasm_runtime_unchain_shared_heaps(wasm_shared_heap_t head, bool entire_chain); +/** + * Reset shared heap chain. For each shared heap in the chain, if it is a + * pre-allocated shared heap, its memory region will be zeroed. For a + * WAMR-managed shared heap, it will be destroyed and reinitialized. + * + * @param shared_heap The head of the shared heap chain. + * @return true if success, false otherwise. + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_reset_shared_heap_chain(wasm_shared_heap_t shared_heap); + /** * Attach a shared heap, it can be the head of shared heap chain, in that case, * attach the shared heap chain, to a module instance diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index f2a33437a..abde189eb 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1715,11 +1715,24 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, exception_tag_index = *((uint32 *)tgtframe_sp); tgtframe_sp++; - /* get tag type */ - uint8 tag_type_index = - module->module->tags[exception_tag_index]->type; - uint32 cell_num_to_copy = - wasm_types[tag_type_index]->param_cell_num; + uint32 cell_num_to_copy = 0; + + if (IS_INVALID_TAGINDEX(exception_tag_index)) { + /* + * Cross-module exception with unknown tag. + * No parameters to copy - just re-throw with + * the invalid tag index so find_a_catch_handler + * routes it to CATCH_ALL. + */ + cell_num_to_copy = 0; + } + else { + /* get tag type */ + uint8 tag_type_index = + module->module->tags[exception_tag_index]->type; + cell_num_to_copy = + wasm_types[tag_type_index]->param_cell_num; + } /* move exception parameters (if there are any) onto top * of stack */ diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index fec9734ed..1368cf038 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -442,7 +442,7 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame) opnd_off = *(int16 *)(frame_ip + off); \ addr_tmp = frame_lp + opnd_off; \ PUT_REF_TO_ADDR(addr_tmp, value); \ - SET_FRAME_REF(ond_off); \ + SET_FRAME_REF(opnd_off); \ } while (0) #define SET_OPERAND(op_type, off, value) SET_OPERAND_##op_type(off, value) @@ -999,9 +999,9 @@ fail: } \ } \ else if (cells[0] == 2) { \ - PUT_I64_TO_ADDR( \ - frame_lp + dst_offsets[0], \ - GET_I64_FROM_ADDR(frame_lp + src_offsets[0])); \ + int64 tmp_i64 = \ + GET_I64_FROM_ADDR(frame_lp + src_offsets[0]); \ + PUT_I64_TO_ADDR(frame_lp + dst_offsets[0], tmp_i64); \ /* Ignore constants because they are not reference */ \ if (src_offsets[0] >= 0) { \ CLEAR_FRAME_REF((unsigned)src_offsets[0]); \ @@ -1011,9 +1011,9 @@ fail: } \ } \ else if (cells[0] == 4) { \ - PUT_V128_TO_ADDR( \ - frame_lp + dst_offsets[0], \ - GET_V128_FROM_ADDR(frame_lp + src_offsets[0])); \ + V128 tmp_v128 = \ + GET_V128_FROM_ADDR(frame_lp + src_offsets[0]); \ + PUT_V128_TO_ADDR(frame_lp + dst_offsets[0], tmp_v128); \ /* Ignore constants because they are not reference */ \ if (src_offsets[0] >= 0) { \ CLEAR_FRAME_REF((unsigned)src_offsets[0]); \ @@ -1062,14 +1062,14 @@ fail: if (cells[0] == 1) \ frame_lp[dst_offsets[0]] = frame_lp[src_offsets[0]]; \ else if (cells[0] == 2) { \ - PUT_I64_TO_ADDR( \ - frame_lp + dst_offsets[0], \ - GET_I64_FROM_ADDR(frame_lp + src_offsets[0])); \ + int64 tmp_i64 = \ + GET_I64_FROM_ADDR(frame_lp + src_offsets[0]); \ + PUT_I64_TO_ADDR(frame_lp + dst_offsets[0], tmp_i64); \ } \ else if (cells[0] == 4) { \ - PUT_V128_TO_ADDR( \ - frame_lp + dst_offsets[0], \ - GET_V128_FROM_ADDR(frame_lp + src_offsets[0])); \ + V128 tmp_v128 = \ + GET_V128_FROM_ADDR(frame_lp + src_offsets[0]); \ + PUT_V128_TO_ADDR(frame_lp + dst_offsets[0], tmp_v128); \ } \ } \ else { \ diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 7280201fb..a2c67bea2 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -701,7 +701,7 @@ destroy_init_expr(WASMModule *module, InitializerExpression *expr) #endif #if WASM_ENABLE_EXTENDED_CONST_EXPR != 0 - // free left expr and right exprs for binary oprand + /* free left expr and right exprs for binary operand */ if (!is_expr_binary_op(expr->init_expr_type)) { return; } @@ -1920,6 +1920,11 @@ resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end, if (need_ref_type_map) ref_type_map_count++; + if (wasm_is_reftype_anyref(ref_type.ref_type)) { + LOG_ERROR("Not support using anyref in struct fields"); + return false; + } + if (wasm_is_type_reftype(ref_type.ref_type)) ref_field_count++; @@ -2039,6 +2044,11 @@ resolve_array_type(const uint8 **p_buf, const uint8 *buf_end, return false; } + if (wasm_is_reftype_anyref(ref_type.ref_type)) { + LOG_ERROR("Not support using anyref in array element type"); + return false; + } + CHECK_BUF(p, p_end, 1); mutable = read_uint8(p); if (!check_mutability(mutable, error_buf, error_buf_size)) { @@ -5567,6 +5577,27 @@ fail: #endif #if WASM_ENABLE_BRANCH_HINTS != 0 +/** + * Count the number of branch instructions for the specified function. + */ +static uint32 +calculate_num_branch_instructions(const WASMFunction *func) +{ + const uint8 *code = func->code; + const uint8 *code_end = code + func->code_size; + uint32 max_hints = 0; + + while (code < code_end) { + uint8 opcode = *code++; + + if (opcode == WASM_OP_IF || opcode == WASM_OP_BR_IF) { + max_hints++; + } + } + + return max_hints; +} + static bool handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, char *error_buf, @@ -5601,22 +5632,52 @@ handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end, uint32 num_hints; read_leb_uint32(buf, buf_end, num_hints); + + /* Ensure that num_hints doesn't exceed the actual number of branch + * instructions */ + WASMFunction *func = + module->functions[func_idx - module->import_function_count]; + uint32 max_branch_instructions = + calculate_num_branch_instructions(func); + if (num_hints > max_branch_instructions) { + set_error_buf_v( + error_buf, error_buf_size, + "invalid number of branch hints: expected at most %u, got %u", + max_branch_instructions, num_hints); + goto fail; + } + struct WASMCompilationHintBranchHint *new_hints = loader_malloc( sizeof(struct WASMCompilationHintBranchHint) * num_hints, error_buf, error_buf_size); + if (!new_hints) { + goto fail; + } for (uint32 j = 0; j < num_hints; ++j) { struct WASMCompilationHintBranchHint *new_hint = &new_hints[j]; new_hint->next = NULL; new_hint->type = WASM_COMPILATION_BRANCH_HINT; read_leb_uint32(buf, buf_end, new_hint->offset); + /* Validate offset is within the function's code bounds */ + if (new_hint->offset >= func->code_size) { + set_error_buf_v( + error_buf, error_buf_size, + "invalid branch hint offset: %u exceeds function " + "code size %u", + new_hint->offset, func->code_size); + goto fail; + } + uint32 size; read_leb_uint32(buf, buf_end, size); if (size != 1) { set_error_buf_v(error_buf, error_buf_size, "invalid branch hint size, expected 1, got %d.", size); - wasm_runtime_free(new_hint); + /* Do not free new_hints here - any hints already linked into + * the module structure will be freed during module cleanup. + * Freeing here would cause a double-free. */ goto fail; } @@ -5629,7 +5690,9 @@ handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end, set_error_buf_v(error_buf, error_buf_size, "invalid branch hint, expected 0 or 1, got %d", data); - wasm_runtime_free(new_hint); + /* Do not free new_hints here - any hints already linked into + * the module structure will be freed during module cleanup. + * Freeing here would cause a double-free. */ goto fail; } @@ -5710,7 +5773,7 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, #else if (name_len == 25 && memcmp((const char *)p, "metadata.code.branch_hint", 25) == 0) { - LOG_VERBOSE("Found branch hint section, but branch hints are disabled " + LOG_WARNING("Found branch hint section, but branch hints are disabled " "in this build, skipping."); } #endif @@ -8545,8 +8608,7 @@ check_offset_pop(WASMLoaderContext *ctx, uint32 cells) static bool check_dynamic_offset_pop(WASMLoaderContext *ctx, uint32 cells) { - if (ctx->dynamic_offset < 0 - || (ctx->dynamic_offset > 0 && (uint32)ctx->dynamic_offset < cells)) + if (ctx->dynamic_offset < 0 || (uint32)ctx->dynamic_offset < cells) return false; return true; } diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index ec1e25cdb..1e2aa08c6 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -375,8 +375,8 @@ destroy_const_expr_stack(ConstExprContext *ctx, bool free_exprs) static void destroy_init_expr(InitializerExpression *expr) { - // free left expr and right exprs for binary oprand - if (is_expr_binary_op(expr->init_expr_type)) { + /* free left expr and right exprs for binary operand */ + if (!is_expr_binary_op(expr->init_expr_type)) { return; } if (expr->u.binary.l_expr) { @@ -4345,8 +4345,7 @@ check_offset_pop(WASMLoaderContext *ctx, uint32 cells) static bool check_dynamic_offset_pop(WASMLoaderContext *ctx, uint32 cells) { - if (ctx->dynamic_offset < 0 - || (ctx->dynamic_offset > 0 && (uint32)ctx->dynamic_offset < cells)) + if (ctx->dynamic_offset < 0 || (uint32)ctx->dynamic_offset < cells) return false; return true; } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index a59bc9257..e41cb4d8e 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2512,6 +2512,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, module_inst->module = module; module_inst->e = (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset); +#if WASM_ENABLE_THREAD_MGR != 0 + if (os_mutex_init(&module_inst->e->common.exception_lock) != 0) { + wasm_runtime_free(module_inst); + return NULL; + } +#endif #if WASM_ENABLE_MULTI_MODULE != 0 module_inst->e->sub_module_inst_list = @@ -3501,6 +3507,9 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) bh_bitmap_delete(module_inst->e->common.elem_dropped); #endif +#if WASM_ENABLE_THREAD_MGR != 0 + os_mutex_destroy(&module_inst->e->common.exception_lock); +#endif wasm_runtime_free(module_inst); } @@ -3618,6 +3627,7 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, native stack to run the following codes before actually calling the aot function in invokeNative function. */ if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { + wasm_runtime_set_exec_env_tls(NULL); return; } diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 0ba2049af..98913e9fe 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -334,6 +334,9 @@ typedef struct WASMModuleInstanceExtraCommon { /* The gc heap created */ void *gc_heap_handle; #endif +#if WASM_ENABLE_THREAD_MGR != 0 + korp_mutex exception_lock; +#endif } WASMModuleInstanceExtraCommon; /* Extra info of WASM module instance for interpreter/jit mode */ diff --git a/core/iwasm/libraries/lib-rats/lib_rats.cmake b/core/iwasm/libraries/lib-rats/lib_rats.cmake index 36bad1c51..d9c63b6df 100644 --- a/core/iwasm/libraries/lib-rats/lib_rats.cmake +++ b/core/iwasm/libraries/lib-rats/lib_rats.cmake @@ -23,7 +23,7 @@ endif() add_definitions (-DWASM_ENABLE_LIB_RATS=1) -include_directories(${LIB_RATS_DIR} ${SGX_SSL_DIR}/include) +include_directories(SYSTEM ${LIB_RATS_DIR} ${SGX_SSL_DIR}/include) include(FetchContent) @@ -41,7 +41,7 @@ FetchContent_GetProperties(librats) if (NOT librats_POPULATED) message("-- Fetching librats ..") FetchContent_Populate(librats) - include_directories("${librats_SOURCE_DIR}/include") + include_directories(SYSTEM "${librats_SOURCE_DIR}/include") # Prevent the propagation of the CMAKE_C_FLAGS of WAMR into librats set(SAVED_CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) diff --git a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c index dc2d4f1bc..d7f6c7454 100644 --- a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c +++ b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c @@ -8,7 +8,10 @@ #include "bh_log.h" bh_static_assert(TID_MIN <= TID_MAX); +/* Some platforms, like Zephyr, have already defined MIN at this point */ +#ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif bool tid_allocator_init(TidAllocator *tid_allocator) diff --git a/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c b/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c index 3bb6bc6b7..89ffeaaa4 100644 --- a/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c +++ b/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c @@ -245,14 +245,21 @@ mmap_wrapper(wasm_exec_env_t exec_env, void *addr, int length, int prot, if (buf_offset == 0) return -1; - if (fd <= 0) + if (fd <= 0) { + module_free((uint64)buf_offset); return -1; + } - if (lseek(fd, offset, SEEK_SET) == -1) + if (lseek(fd, offset, SEEK_SET) == -1) { + module_free((uint64)buf_offset); return -1; + } size_read = read(fd, buf, length); - (void)size_read; + if (size_read < 0) { + module_free((uint64)buf_offset); + return -1; + } return buf_offset; } diff --git a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake index f197b21d6..bbcb84d39 100644 --- a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake +++ b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake @@ -22,7 +22,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") ## libuv find_package(LIBUV QUIET) if (LIBUV_FOUND) - include_directories(${LIBUV_INCLUDE_DIR}) + include_directories(SYSTEM ${LIBUV_INCLUDE_DIR}) else() FetchContent_Declare( libuv @@ -30,7 +30,7 @@ else() GIT_TAG ${LIBUV_VERSION} ) FetchContent_MakeAvailable(libuv) - include_directories("${libuv_SOURCE_DIR}/include") + include_directories(SYSTEM "${libuv_SOURCE_DIR}/include") set (LIBUV_LIBRARIES uv_a) set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() @@ -38,7 +38,7 @@ endif() ## uvwasi find_package(UVWASI QUIET) if (UVWASI_FOUND) - include_directories(${UVWASI_INCLUDE_DIR}) + include_directories(SYSTEM ${UVWASI_INCLUDE_DIR}) else() FetchContent_Declare( uvwasi @@ -46,7 +46,7 @@ else() GIT_TAG 392e1f1c1c8a2d2102c9f2e0b9f35959a149d133 ) FetchContent_MakeAvailable(uvwasi) - include_directories("${uvwasi_SOURCE_DIR}/include") + include_directories(SYSTEM "${uvwasi_SOURCE_DIR}/include") set (UVWASI_LIBRARIES uvwasi_a) set_target_properties(uvwasi_a PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 3d90811bc..7b087e44c 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -430,7 +430,9 @@ fd_table_attach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object *fo, __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting) REQUIRES_EXCLUSIVE(ft->lock) CONSUMES(fo->refcount) { - bh_assert(ft->size > fd && "File descriptor table too small"); + bh_assert(ft->size <= INT_MAX + && "Unsigned value is out of signed int range"); + bh_assert((int32_t)ft->size > fd && "File descriptor table too small"); struct fd_entry *fe = &ft->entries[fd]; bh_assert(fe->object == NULL && "Attempted to overwrite an existing descriptor"); @@ -446,7 +448,9 @@ static void fd_table_detach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object **fo) REQUIRES_EXCLUSIVE(ft->lock) PRODUCES((*fo)->refcount) { - bh_assert(ft->size > fd && "File descriptor table too small"); + bh_assert(ft->size <= INT_MAX + && "Unsigned value is out of signed int range"); + bh_assert((int32_t)ft->size > fd && "File descriptor table too small"); struct fd_entry *fe = &ft->entries[fd]; *fo = fe->object; bh_assert(*fo != NULL && "Attempted to detach nonexistent descriptor"); @@ -2585,7 +2589,7 @@ wasi_ssp_sock_connect(wasm_exec_env_t exec_env, struct fd_table *curfds, return __WASI_EACCES; } - error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0); + error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_CONNECT, 0); if (error != __WASI_ESUCCESS) { return error; } @@ -3105,7 +3109,6 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask) } next->next = NULL; - next->mask = mask; if (os_socket_inet_network(true, addr, &target) != BHT_OK) { // If parsing IPv4 fails, try IPv6 @@ -3116,10 +3119,20 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask) next->type = IPv6; bh_memcpy_s(next->addr.ip6, sizeof(next->addr.ip6), target.ipv6, sizeof(target.ipv6)); + if (mask > 128) { + wasm_runtime_free(next); + return false; + } + next->mask = mask; } else { next->type = IPv4; next->addr.ip4 = target.ipv4; + if (mask > 32) { + wasm_runtime_free(next); + return false; + } + next->mask = mask; } /* attach with */ diff --git a/core/iwasm/libraries/simde/simde.cmake b/core/iwasm/libraries/simde/simde.cmake index 60fd6d975..e9844dd87 100644 --- a/core/iwasm/libraries/simde/simde.cmake +++ b/core/iwasm/libraries/simde/simde.cmake @@ -25,4 +25,4 @@ FetchContent_Declare( message("-- Fetching simde ..") FetchContent_MakeAvailable(simde) -include_directories("${simde_SOURCE_DIR}") +include_directories(SYSTEM "${simde_SOURCE_DIR}") diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 5a647a9b6..563a9098e 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -29,8 +29,6 @@ static bh_list cluster_list_head; static bh_list *const cluster_list = &cluster_list_head; static korp_mutex cluster_list_lock; -static korp_mutex _exception_lock; - typedef void (*list_visitor)(void *, void *); static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM; @@ -51,10 +49,6 @@ thread_manager_init() return false; if (os_mutex_init(&cluster_list_lock) != 0) return false; - if (os_mutex_init(&_exception_lock) != 0) { - os_mutex_destroy(&cluster_list_lock); - return false; - } return true; } @@ -69,7 +63,6 @@ thread_manager_destroy() cluster = next; } wasm_cluster_cancel_all_callbacks(); - os_mutex_destroy(&_exception_lock); os_mutex_destroy(&cluster_list_lock); } @@ -1540,19 +1533,13 @@ wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env) void exception_lock(WASMModuleInstance *module_inst) { - /* - * Note: this lock could be per module instance if desirable. - * We can revisit on AOT version bump. - * It probably doesn't matter though because the exception handling - * logic should not be executed too frequently anyway. - */ - os_mutex_lock(&_exception_lock); + os_mutex_lock(&GetModuleInstanceExtraCommon(module_inst)->exception_lock); } void exception_unlock(WASMModuleInstance *module_inst) { - os_mutex_unlock(&_exception_lock); + os_mutex_unlock(&GetModuleInstanceExtraCommon(module_inst)->exception_lock); } void diff --git a/core/iwasm/libraries/wasi-nn/cmake/iwasm_helper.cmake b/core/iwasm/libraries/wasi-nn/cmake/iwasm_helper.cmake index 670988e1d..45518de59 100644 --- a/core/iwasm/libraries/wasi-nn/cmake/iwasm_helper.cmake +++ b/core/iwasm/libraries/wasi-nn/cmake/iwasm_helper.cmake @@ -28,12 +28,6 @@ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -W set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wno-unused") -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () -endif () - set (WAMR_BUILD_INTERP 1) set (WAMR_BUILD_AOT 1) set (WAMR_BUILD_JIT 0) diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_llamacpp.c b/core/iwasm/libraries/wasi-nn/src/wasi_nn_llamacpp.c index cef1479af..791d615db 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_llamacpp.c +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_llamacpp.c @@ -624,8 +624,15 @@ get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index, printf("%s\n", output_metadata); } - memcpy(output_tensor->buf, output_metadata, strlen(output_metadata)); - *output_tensor_size = strlen(output_metadata); + size_t metadata_len = strlen(output_metadata); + if (metadata_len > output_tensor->size) { + NN_ERR_PRINTF("Output buffer too small for metadata: " + "need %zu, got %zu", + metadata_len, output_tensor->size); + return too_large; + } + memcpy(output_tensor->buf, output_metadata, metadata_len); + *output_tensor_size = metadata_len; return success; } @@ -644,8 +651,15 @@ get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index, printf("%s", buf); } - memcpy(output_tensor->buf + end_pos, buf, strlen(buf)); - end_pos += strlen(buf); + size_t piece_len = strlen(buf); + if (end_pos + piece_len > output_tensor->size) { + NN_ERR_PRINTF("Output buffer too small: need at least %zu," + " got %zu", + end_pos + piece_len, output_tensor->size); + return too_large; + } + memcpy(output_tensor->buf + end_pos, buf, piece_len); + end_pos += piece_len; } if (backend_ctx->config.stream_stdout) { diff --git a/core/shared/mem-alloc/ems/ems_gc.c b/core/shared/mem-alloc/ems/ems_gc.c index e97a07bba..bc0488968 100644 --- a/core/shared/mem-alloc/ems/ems_gc.c +++ b/core/shared/mem-alloc/ems/ems_gc.c @@ -308,8 +308,12 @@ reclaim_instance_heap(gc_heap_t *heap) return GC_SUCCESS; ret = gct_vm_begin_rootset_enumeration(heap->cluster, heap); #endif - if (!ret) + if (!ret) { + if (heap->root_set) { + rollback_mark(heap); + } return GC_ERROR; + } #if BH_ENABLE_GC_VERIFY != 0 /* no matter whether the enumeration is successful or not, the data diff --git a/core/shared/mem-alloc/ems/ems_kfc.c b/core/shared/mem-alloc/ems/ems_kfc.c index 2d5a4b13e..ac2b127ca 100644 --- a/core/shared/mem-alloc/ems/ems_kfc.c +++ b/core/shared/mem-alloc/ems/ems_kfc.c @@ -286,13 +286,13 @@ gc_migrate(gc_handle_t handle, char *pool_buf_new, gc_size_t pool_buf_size) while (cur < end) { size = hmu_get_size(cur); -#if BH_ENABLE_GC_CORRUPTION_CHECK != 0 if (size <= 0 || size > (uint32)((uint8 *)end - (uint8 *)cur)) { LOG_ERROR("[GC_ERROR]Heap is corrupted, heap migrate failed.\n"); +#if BH_ENABLE_GC_CORRUPTION_CHECK != 0 heap->is_heap_corrupted = true; +#endif return GC_ERROR; } -#endif if (hmu_get_ut(cur) == HMU_FC && !HMU_IS_FC_NORMAL(size)) { tree_node = (hmu_tree_node_t *)cur; @@ -315,15 +315,13 @@ gc_migrate(gc_handle_t handle, char *pool_buf_new, gc_size_t pool_buf_size) cur = (hmu_t *)((char *)cur + size); } -#if BH_ENABLE_GC_CORRUPTION_CHECK != 0 if (cur != end) { LOG_ERROR("[GC_ERROR]Heap is corrupted, heap migrate failed.\n"); +#if BH_ENABLE_GC_CORRUPTION_CHECK != 0 heap->is_heap_corrupted = true; +#endif return GC_ERROR; } -#else - bh_assert(cur == end); -#endif return 0; } diff --git a/core/shared/platform/include/platform_wasi_types.h b/core/shared/platform/include/platform_wasi_types.h index 56ea7514e..980d3f84e 100644 --- a/core/shared/platform/include/platform_wasi_types.h +++ b/core/shared/platform/include/platform_wasi_types.h @@ -29,6 +29,9 @@ #endif /* _Alignof */ extern "C" { +#elif defined(_MSC_VER) && !_CRT_HAS_C11 +#define _Static_assert static_assert +#define _Alignof __alignof #endif /* There is no need to check the WASI layout if we're using uvwasi or libc-wasi @@ -530,19 +533,14 @@ assert_wasi_layout(offsetof(__wasi_subscription_t, userdata) == 0, "witx calcula assert_wasi_layout(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset"); /* keep syncing with wasi_socket_ext.h */ -typedef enum { - /* Used only for sock_addr_resolve hints */ - SOCKET_ANY = -1, - SOCKET_DGRAM = 0, - SOCKET_STREAM, -} __wasi_sock_type_t; typedef uint16_t __wasi_ip_port_t; /* Ensure that __wasi_addr_type_t has a size of 4 byte (I32). However, it will not have the type safety of enum. */ typedef uint32_t __wasi_addr_type_t; -enum { IPv4 = 0, IPv6 }; +#define IPv4 (0) +#define IPv6 (1) /* n0.n1.n2.n3 */ typedef struct __wasi_addr_ip4_t { @@ -589,20 +587,40 @@ typedef struct __wasi_addr_t { } addr; } __wasi_addr_t; -typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t; +/* Force 32-bit wire width for cross-boundary fields */ +typedef int32_t __wasi_sock_type_t; +#define SOCKET_ANY (-1) +#define SOCKET_DGRAM (0) +#define SOCKET_STREAM (1) + +typedef int32_t __wasi_address_family_t; +#define INET4 (0) +#define INET6 (1) +#define INET_UNSPEC (2) typedef struct __wasi_addr_info_t { - __wasi_addr_t addr; + __wasi_addr_t addr; __wasi_sock_type_t type; } __wasi_addr_info_t; typedef struct __wasi_addr_info_hints_t { - __wasi_sock_type_t type; - __wasi_address_family_t family; - // this is to workaround lack of optional parameters - uint8_t hints_enabled; + __wasi_sock_type_t type; // 4 bytes + __wasi_address_family_t family; // 4 bytes + uint8_t hints_enabled; // 1 byte + uint8_t _pad[3]; // enforce layout } __wasi_addr_info_hints_t; +assert_wasi_layout(sizeof(__wasi_sock_type_t) == 4, "sock_type must be 4 bytes"); +assert_wasi_layout(sizeof(__wasi_address_family_t) == 4, "addr_family must be 4 bytes"); + +assert_wasi_layout(sizeof(__wasi_addr_info_hints_t) == 12, "hints_t must be 12 bytes"); +assert_wasi_layout(offsetof(__wasi_addr_info_hints_t, type) == 0, "hints.type@0"); +assert_wasi_layout(offsetof(__wasi_addr_info_hints_t, family) == 4, "hints.family@4"); +assert_wasi_layout(offsetof(__wasi_addr_info_hints_t, hints_enabled) == 8, "hints.enabled@8"); + +assert_wasi_layout(offsetof(__wasi_addr_info_t, type) == sizeof(__wasi_addr_t), + "addr_info.type follows addr"); + #undef assert_wasi_layout /* clang-format on */ @@ -610,4 +628,4 @@ typedef struct __wasi_addr_info_hints_t { } #endif -#endif /* end of _PLATFORM_WASI_TYPES_H */ \ No newline at end of file +#endif /* end of _PLATFORM_WASI_TYPES_H */ diff --git a/core/shared/platform/zephyr/zephyr_file.c b/core/shared/platform/zephyr/zephyr_file.c index 1f48bc010..54b357e31 100644 --- a/core/shared/platform/zephyr/zephyr_file.c +++ b/core/shared/platform/zephyr/zephyr_file.c @@ -120,13 +120,15 @@ zephyr_fs_alloc_obj(bool is_dir, const char *path, int *index) ptr = &desc_array[i]; ptr->used = true; ptr->is_dir = is_dir; - ptr->path = bh_strdup(path); ptr->dir_index = 0; + size_t path_len = strlen(path) + 1; + ptr->path = BH_MALLOC(path_len); if (ptr->path == NULL) { ptr->used = false; k_mutex_unlock(&desc_array_mutex); return NULL; } + strcpy(ptr->path, path); *index = i + 3; break; } @@ -451,6 +453,7 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, } if (!build_absolute_path(abs_path, sizeof(abs_path), path)) { + BH_FREE(*out); return __WASI_ENOMEM; } @@ -591,8 +594,9 @@ os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, total_read += bytes_read; - // If we read less than we asked for, stop reading - if (bytes_read < iov[i].buf_len) { + /* If we read less than we asked for, stop reading + bytes_read being a non-negative value was already checked */ + if ((size_t)bytes_read < iov[i].buf_len) { break; } } @@ -627,8 +631,9 @@ os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, total_written += bytes_written; - // If we wrote less than we asked for, stop writing - if (bytes_written < iov[i].buf_len) { + /* If we wrote less than we asked for, stop writing + bytes_read being a non-negative value was already checked */ + if ((size_t)bytes_written < iov[i].buf_len) { break; } } @@ -657,8 +662,9 @@ os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, total_read += bytes_read; - // If we read less than we asked for, stop reading - if (bytes_read < iov[i].buf_len) { + /* If we read less than we asked for, stop reading + bytes_read being a non-negative value was already checked */ + if ((size_t)bytes_read < iov[i].buf_len) { break; } } @@ -702,8 +708,9 @@ os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, total_written += bytes_written; - // If we wrote less than we asked for, stop writing - if (bytes_written < iov[i].buf_len) { + /* If we wrote less than we asked for, stop writing + bytes_read being a non-negative value was already checked */ + if ((size_t)bytes_written < iov[i].buf_len) { break; } } @@ -850,11 +857,17 @@ os_renameat(os_file_handle old_handle, const char *old_path, for (int i = 0; i < CONFIG_WASI_MAX_OPEN_FILES; i++) { struct zephyr_fs_desc *ptr = &desc_array[i]; if (ptr->used && ptr->path && strcmp(ptr->path, abs_old_path) == 0) { - char *new_path_copy = bh_strdup(new_path); + size_t new_path_len = strlen(abs_new_path) + 1; + char *new_path_copy = BH_MALLOC(new_path_len); if (new_path_copy != NULL) { + strcpy(new_path_copy, abs_new_path); BH_FREE(ptr->path); ptr->path = new_path_copy; } + else { + k_mutex_unlock(&desc_array_mutex); + return __WASI_ENOMEM; + } break; // Only one descriptor should match } } @@ -1195,4 +1208,4 @@ bool os_is_stderr_handle(os_file_handle handle) { return (handle == (os_file_handle)stderr); -} \ No newline at end of file +} diff --git a/core/shared/platform/zephyr/zephyr_socket.c b/core/shared/platform/zephyr/zephyr_socket.c index 6d108623e..56f37fc8e 100644 --- a/core/shared/platform/zephyr/zephyr_socket.c +++ b/core/shared/platform/zephyr/zephyr_socket.c @@ -173,7 +173,7 @@ os_socket_getbooloption(bh_socket_t socket, int level, int optname, int optval; socklen_t optval_size = sizeof(optval); - if (zsock_setsockopt(socket->fd, level, optname, &optval, optval_size) + if (zsock_getsockopt(socket->fd, level, optname, &optval, &optval_size) != 0) { return BHT_ERROR; } @@ -190,7 +190,7 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) *(sock) = BH_MALLOC(sizeof(zephyr_handle)); - if (!sock) { + if (!*sock) { return BHT_ERROR; } @@ -262,8 +262,13 @@ os_socket_settimeout(bh_socket_t socket, uint64 timeout_us) timeout.tv_sec = timeout_us / 1000000; timeout.tv_usec = timeout_us % 1000000; - return zsock_setsockopt(socket->fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, - sizeof(timeout)); + if (zsock_setsockopt(socket->fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, + sizeof(timeout)) + != 0) { + return BHT_ERROR; + } + + return BHT_OK; } int @@ -277,7 +282,7 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, unsigned int *addrlen) { *sock = BH_MALLOC(sizeof(zephyr_handle)); - if (!sock) { + if (!*sock) { return BHT_ERROR; } @@ -609,7 +614,7 @@ os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us) struct timeval tv; socklen_t tv_len = sizeof(tv); - if (zsock_setsockopt(socket->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, tv_len) + if (zsock_getsockopt(socket->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &tv_len) != 0) { return BHT_ERROR; } @@ -639,7 +644,7 @@ os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) struct timeval tv; socklen_t tv_len = sizeof(tv); - if (zsock_setsockopt(socket->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, tv_len) + if (zsock_getsockopt(socket->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &tv_len) != 0) { return BHT_ERROR; } @@ -693,21 +698,18 @@ os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) return BHT_ERROR; } -// TCP_NODELAY Disable TCP buffering (ignored, for compatibility) int os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) { - errno = ENOSYS; - - return BHT_ERROR; + return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_NODELAY, + is_enabled); } int os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) { - errno = ENOSYS; - - return BHT_ERROR; + return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_NODELAY, + is_enabled); } int @@ -760,8 +762,8 @@ os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32_t *time_s) socklen_t time_s_len = sizeof(time_s_int); #ifdef TCP_KEEPIDLE - if (zsock_setsockopt(socket->fd, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int, - time_s_len) + if (zsock_getsockopt(socket->fd, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int, + &time_s_len) != 0) { return BHT_ERROR; } @@ -769,8 +771,8 @@ os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32_t *time_s) return BHT_OK; #elif defined(TCP_KEEPALIVE) - if (zsock_setsockopt(socket->fd, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int, - time_s_len) + if (zsock_getsockopt(socket->fd, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int, + &time_s_len) != 0) { return BHT_ERROR; } @@ -856,17 +858,37 @@ os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) int os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) { - errno = ENOSYS; - - return BHT_ERROR; + if (ipv6) { +#ifdef IPPROTO_IPV6 + return os_socket_setbooloption(socket, IPPROTO_IPV6, + IPV6_MULTICAST_LOOP, is_enabled); +#else + errno = EAFNOSUPPORT; + return BHT_ERROR; +#endif + } + else { + return os_socket_setbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP, + is_enabled); + } } int os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) { - errno = ENOSYS; - - return BHT_ERROR; + if (ipv6) { +#ifdef IPPROTO_IPV6 + return os_socket_getbooloption(socket, IPPROTO_IPV6, + IPV6_MULTICAST_LOOP, is_enabled); +#else + errno = EAFNOSUPPORT; + return BHT_ERROR; +#endif + } + else { + return os_socket_getbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP, + is_enabled); + } } int @@ -965,13 +987,13 @@ os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) int os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) { - socklen_t opt_len = sizeof(*ttl_s); - - if (zsock_setsockopt(socket->fd, IPPROTO_IP, IP_MULTICAST_TTL, ttl_s, - opt_len) - != 0) { + /* Most socket-level options utilize an int argument for optval */ + int opt; + socklen_t opt_len = sizeof(opt); + if (zsock_getsockopt(socket->fd, IPPROTO_IP, IP_TTL, &opt, &opt_len) != 0) { return BHT_ERROR; } + *ttl_s = (uint8_t)opt; return BHT_OK; } @@ -991,13 +1013,15 @@ os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) int os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) { - socklen_t opt_len = sizeof(*ttl_s); - - if (zsock_setsockopt(socket->fd, IPPROTO_IP, IP_MULTICAST_TTL, ttl_s, - opt_len) + /* Most socket-level options utilize an int argument for optval */ + int opt; + socklen_t opt_len = sizeof(opt); + if (zsock_getsockopt(socket->fd, IPPROTO_IP, IP_MULTICAST_TTL, &opt, + &opt_len) != 0) { return BHT_ERROR; } + *ttl_s = (uint8_t)opt; return BHT_OK; } @@ -1059,4 +1083,4 @@ int os_poll(os_poll_file_handle *fds, os_nfds_t nfs, int timeout) { return zsock_poll(fds, nfs, timeout); -} \ No newline at end of file +} diff --git a/core/shared/utils/bh_common.c b/core/shared/utils/bh_common.c index 34b6f40e7..d86840d7d 100644 --- a/core/shared/utils/bh_common.c +++ b/core/shared/utils/bh_common.c @@ -166,6 +166,16 @@ wa_strdup(const char *s) return s1; } +char * +bh_strtok_r(char *str, const char *delim, char **saveptr) +{ +#if !(defined(_WIN32) || defined(_WIN32_)) + return strtok_r(str, delim, saveptr); +#else + return strtok_s(str, delim, saveptr); +#endif +} + #if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 int bh_system(const char *cmd) diff --git a/core/shared/utils/bh_common.h b/core/shared/utils/bh_common.h index 093e62208..2f31bd5d8 100644 --- a/core/shared/utils/bh_common.h +++ b/core/shared/utils/bh_common.h @@ -66,6 +66,9 @@ bh_strdup(const char *s); char * wa_strdup(const char *s); +char * +bh_strtok_r(char *str, const char *delim, char **saveptr); + #if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 /* Executes a system command in bash/cmd.exe */ int diff --git a/core/shared/utils/bh_queue.c b/core/shared/utils/bh_queue.c index ddbb6fffe..4fc756fbe 100644 --- a/core/shared/utils/bh_queue.c +++ b/core/shared/utils/bh_queue.c @@ -96,14 +96,15 @@ bh_queue_destroy(bh_queue *queue) bool bh_post_msg2(bh_queue *queue, bh_queue_node *msg) { + bh_queue_mutex_lock(&queue->queue_lock); + if (queue->cnt >= queue->max) { queue->drops++; bh_free_msg(msg); + bh_queue_mutex_unlock(&queue->queue_lock); return false; } - bh_queue_mutex_lock(&queue->queue_lock); - if (queue->cnt == 0) { bh_assert(queue->head == NULL); bh_assert(queue->tail == NULL); @@ -131,7 +132,9 @@ bh_post_msg(bh_queue *queue, unsigned short tag, void *body, unsigned int len) { bh_queue_node *msg = bh_new_msg(tag, body, len, NULL); if (msg == NULL) { + bh_queue_mutex_lock(&queue->queue_lock); queue->drops++; + bh_queue_mutex_unlock(&queue->queue_lock); if (len != 0 && body) BH_FREE(body); return false; diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 2cb3f45aa..4b7fbfd9f 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -1,35 +1,141 @@ # Build WAMR vmcore -WAMR vmcore is a set of runtime libraries for loading and running Wasm modules. This document introduces how to build the WAMR vmcore. +WAMR vmcore is the runtime library set that loads and runs Wasm modules. This guide walks you through building the WAMR vmcore. References: -- [how to build iwasm](../product-mini/README.md): building different target platforms such as Linux, Windows, Mac etc +- [how to build iwasm](../product-mini/README.md): build for Linux, Windows, macOS, and more - [Blog: Introduction to WAMR running modes](https://bytecodealliance.github.io/wamr.dev/blog/introduction-to-wamr-running-modes/) -## WAMR vmcore cmake building configurations +## building configurations -By including the script `runtime_lib.cmake` under folder [build-scripts](../build-scripts) in CMakeList.txt, it is easy to use vmcore to build host software with cmake. +Include the script `runtime_lib.cmake` from [build-scripts](../build-scripts) into your CMakeLists.txt to pull vmcore into your build. ```cmake -# add this into your CMakeList.txt +# add this into your CMakeLists.txt include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) ``` -The script `runtime_lib.cmake` defines a number of variables for configuring the WAMR runtime features. You can set these variables in your CMakeList.txt or pass the configurations from cmake command line. +The `runtime_lib.cmake` script exposes variables that control WAMR runtime features. Set them in CMakeLists.txt or pass them on the cmake command line. -Please refer to [a full list of configuration options](./tired_support.md#appendix-all-compilation-flags). +```cmake +# Set flags in CMakeLists.txt +set(WAMR_BUILD_AOT 1) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_LIBC_BUILTIN 1) +set(WAMR_BUILD_LIBC_WASI 1) +# Include the runtime lib script +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +``` + +### All compilation flags + +| Compilation flags | Description | +| -------------------------------------------------------------------------------------------------------- | ------------------------------------ | +| [WAMR_APP_THREAD_STACK_SIZE_MAX](#set-maximum-app-thread-stack-size) | Maximum stack size for app threads | +| [WAMR_BH_LOG](#host-defined-log) | Host defined logging | +| [WAMR_BH_VPRINTF](#host-defined-vprintf) | Host defined vprintf | +| [WAMR_BUILD_ALLOC_WITH_USAGE](#user-defined-linear-memory-allocator) | Allocation with usage tracking | +| [WAMR_BUILD_ALLOC_WITH_USER_DATA](#user-defined-linear-memory-allocator) | Allocation with user data | +| [WAMR_BUILD_AOT](#configure-aot) | AoT compilation(wamrc) | +| [WAMR_BUILD_AOT](#configure-aot) | AoT runtime | +| [WAMR_BUILD_AOT_INTRINSICS](#aot-intrinsics) | AoT intrinsics | +| [WAMR_BUILD_AOT_STACK_FRAME](#aot-stack-frame-feature) | AoT stack frame | +| [WAMR_BUILD_AOT_VALIDATOR](#aot-validator) | AoT validator | +| [WAMR_BUILD_BULK_MEMORY](#bulk-memory-feature) | bulk memory | +| [WAMR_BUILD_COPY_CALL_STACK](#copy-call-stack) | copy call stack | +| [WAMR_BUILD_CUSTOM_NAME_SECTION](#name-section) | name section | +| [WAMR_BUILD_DEBUG_AOT](#source-debugging-features) | debug AoT | +| [WAMR_BUILD_DEBUG_INTERP](#source-debugging-features) | debug interpreter | +| [WAMR_BUILD_DUMP_CALL_STACK](#dump-call-stack-feature) | dump call stack | +| [WAMR_BUILD_DYNAMIC_AOT_DEBUG](#source-debugging-features) | dynamic AoT debugging | +| [WAMR_BUILD_EXCE_HANDLING](#exception-handling) | exception handling | +| [WAMR_BUILD_EXTENDED_CONST_EXPR](#extended-constant-expression) | extended constant expressions | +| [WAMR_BUILD_FAST_INTERP](#configure-interpreters) | fast interpreter | +| [WAMR_BUILD_FAST_JIT](#configure-fast-jit) | fast JIT | +| [WAMR_BUILD_FAST_JIT_DUMP](#configure-fast-jit) | fast JIT dump | +| [WAMR_BUILD_GC](#garbage-collection) | garbage collection | +| [WAMR_BUILD_GC_HEAP_VERIFY](#garbage-collection) | garbage collection heap verification | +| [WAMR_BUILD_GC_HEAP_SIZE_DEFAULT](garbage-collection) | default garbage collection heap size | +| [WAMR_BUILD_GLOBAL_HEAP_POOL](#a-pre-allocation-for-runtime-and-wasm-apps) | global heap pool | +| [WAMR_BUILD_GLOBAL_HEAP_SIZE](#a-pre-allocation-for-runtime-and-wasm-apps) | global heap size | +| [WAMR_BUILD_INSTRUCTION_METERING](#instruction-metering) | instruction metering | +| [WAMR_BUILD_INTERP](#configure-interpreters) | interpreter | +| [WAMR_BUILD_INVOKE_NATIVE_GENERAL](#invoke-general-ffi) | FFI general | +| [WAMR_BUILD_JIT](#configure-llvm-jit) | JIT compilation | +| [WAMR_BUILD_LAZY_JIT](#configure-llvm-jit) | lazy JIT compilation | +| [WAMR_BUILD_LIBC_BUILTIN](#configure-libc) | libc builtin functions | +| [WAMR_BUILD_LIBC_EMCC](#configure-libc) | libc emcc compatibility | +| [WAMR_BUILD_LIBC_UVWASI](#configure-libc) | libc uvwasi compatibility | +| [WAMR_BUILD_LIBC_WASI](#configure-libc) | wasi libc | +| [WAMR_BUILD_LIB_PTHREAD](#lib-pthread) | pthread library | +| [WAMR_BUILD_LIB_PTHREAD_SEMAPHORE](#lib-pthread-semaphore) | pthread semaphore support | +| [WAMR_BUILD_LIB_RATS](#librats) | RATS library | +| [WAMR_BUILD_LIB_WASI_THREADS](#lib-wasi-threads) | wasi threads | +| [WAMR_BUILD_LINUX_PERF](#linux-perf-support) | Linux performance counters | +| [WAMR_BUILD_LIME1](#lime1-target) | LIME1 runtime | +| [WAMR_BUILD_LOAD_CUSTOM_SECTION](#load-wasm-custom-sections) | loading custom sections | +| [WAMR_BUILD_MEMORY64](#memory64-feature) | memory64 support | +| [WAMR_BUILD_MEMORY_PROFILING](#memory-profiling-experiment) | memory profiling | +| [WAMR_BUILD_MINI_LOADER](#wasm-mini-loader) :warning: :exclamation: | mini loader | +| [WAMR_BUILD_MODULE_INST_CONTEXT](#module-instance-context-apis) | module instance context | +| [WAMR_BUILD_MULTI_MEMORY](#multi-memory) | multi-memory support | +| [WAMR_BUILD_MULTI_MODULE](#multi-module-feature) | multi-module support | +| [WAMR_BUILD_PERF_PROFILING](#performance-profiling-experiment) | performance profiling | +| [WAMR_BUILD_PLATFORM](#configure-platform-and-architecture) | Default platform | +| [WAMR_BUILD_QUICK_AOT_ENTRY](#quick-aotjti-entries) | quick AOT entry | +| [WAMR_BUILD_REF_TYPES](#reference-types-feature) | reference types | +| [WAMR_BUILD_SANITIZER](#sanitizer) | sanitizer | +| [WAMR_BUILD_SGX_IPFS](#intel-protected-file-system) | Intel Protected File System support | +| [WAMR_BUILD_SHARED_HEAP](#shared-heap-among-wasm-apps-and-host-native) | shared heap | +| [WAMR_BUILD_SHARED_MEMORY](shared-memory-feature) | shared memory | +| [WAMR_BUILD_SHRUNK_MEMORY](#shrunk-the-memory-usage) | shrunk memory | +| [WAMR_BUILD_SIMD](#128-bit-simd-feature) | SIMD support | +| [WAMR_BUILD_SIMDE](#128-bit-simd-feature) | SIMD E extensions | +| [WAMR_BUILD_SPEC_TEST](#support-spec-test) | spec test | +| [WAMR_BUILD_STACK_GUARD_SIZE](#stack-guard-size) | Stack guard size | +| [WAMR_BUILD_STATIC_PGO](running-pgoprofile-guided-optimization-instrumented-aot-file) | Static PGO | +| [WAMR_BUILD_STRINGREF](#garbage-collection) | String reference support | +| [WAMR_BUILD_TAIL_CALL](#tail-call-feature) | Tail call optimization | +| [WAMR_BUILD_TARGET](#configure-platform-and-architecture) | Default target architecture | +| [WAMR_BUILD_THREAD_MGR](#thread-manager) | Thread manager | +| [WAMR_BUILD_WAMR_COMPILER](#configure-aot) | WAMR compiler | +| [WAMR_BUILD_WASI_EPHEMERAL_NN](#lib-wasi-nn-with-wasi_ephemeral_nn-module-support) | WASI ephemeral NN | +| [WAMR_BUILD_WASI_NN](#lib-wasi-nn) | WASI NN | +| [WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH](#lib-wasi-nn-external-delegate-mode) | External delegate path for WASI NN | +| [WAMR_BUILD_WASI_NN_ENABLE_GPU](#lib-wasi-nn-gpu-mode) | GPU support for WASI NN | +| [WAMR_BUILD_WASI_NN_LLAMACPP](#lib-wasi-nn) | LLAMA CPP for WASI NN | +| [WAMR_BUILD_WASI_NN_ONNX](#lib-wasi-nn) | ONNX for WASI NN | +| [WAMR_BUILD_WASI_NN_OPENVINO](#lib-wasi-nn) | OpenVINO for WASI NN | +| [WAMR_BUILD_WASI_NN_TFLITE](#lib-wasi-nn) | TFLite for WASI NN | +| [WAMR_BUILD_WASM_CACHE](#wasm-cache) | WASM cache | +| [WAMR_CONFIGURABLE_BOUNDS_CHECKS](#configurable-memory-access-boundary-check) :warning: :exclamation: | Configurable bounds checks | +| [WAMR_DISABLE_APP_ENTRY](#exclude-wamr-application-entry-functions) | Disable app entry | +| [WAMR_DISABLE_HW_BOUND_CHECK](#disable-boundary-check-with-hardware-trap) | Disable hardware bound check | +| [WAMR_DISABLE_STACK_HW_BOUND_CHECK](#disable-native-stack-boundary-check-with-hardware-trap) | Disable stack hardware bound check | +| [WAMR_DISABLE_WAKEUP_BLOCKING_OP](#disable-async-wakeup-of-blocking-operation) | Disable wakeup blocking operation | +| [WAMR_DISABLE_WRITE_GS_BASE](#disable-writing-the-linear-memory-base-address-to-x86-gs-segment-register) | Disable write GS base | +| [WAMR_TEST_GC](#test-garbage-collection) | Test garbage collection | + +### **Privileged Features** :warning: :exclamation: + +_Privileged Features_ are powerful options that can boost performance or add capabilities but lower security by compromising isolation. Use them with care and test thoroughly. + +### **[config.h](../core/config.h)** + +Above compilation flags map to macros in `config.h`. For example, `WAMR_BUILD_AOT` maps to `WAMR_BUILD_AOT` in `config.h`. The build system sets these macros automatically based on your CMake settings. If your build doesn't set those flags, default values in `config.h` apply. ### **Configure platform and architecture** -- **WAMR_BUILD_PLATFORM**: set the target platform. It can be set to any platform name (folder name) under folder [core/shared/platform](../core/shared/platform). +- **WAMR_BUILD_PLATFORM**: set the target platform. Match the platform folder name under [core/shared/platform](../core/shared/platform). -- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets are: X86_64, X86_32, AARCH64, ARM, THUMB, XTENSA, ARC, RISCV32, RISCV64 and MIPS. - - For ARM and THUMB, the format is \\[\]\[\_VFP], where \ is the ARM sub-architecture and the "\_VFP" suffix means using VFP coprocessor registers s0-s15 (d0-d7) for passing arguments or returning results in standard procedure-call. Both \ and "\_VFP" are optional, e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. - - For AARCH64, the format is\[\], VFP is enabled by default. \ is optional, e.g. AARCH64, AARCH64V8, AARCH64V8.1 and so on. - - For RISCV64, the format is \[_abi], where "\_abi" is optional, currently the supported formats are RISCV64, RISCV64_LP64D and RISCV64_LP64: RISCV64 and RISCV64_LP64D are identical, using [LP64D](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (LP64 with hardware floating-point calling convention for FLEN=64). And RISCV64_LP64 uses [LP64](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (Integer calling-convention only, and hardware floating-point calling convention is not used). - - For RISCV32, the format is \[_abi], where "\_abi" is optional, currently the supported formats are RISCV32, RISCV32_ILP32D, RISCV32_ILP32F and RISCV32_ILP32: RISCV32 and RISCV32_ILP32D are identical, using [ILP32D](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (ILP32 with hardware floating-point calling convention for FLEN=64). RISCV32_ILP32F uses [ILP32F](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (ILP32 with hardware floating-point calling convention for FLEN=32). And RISCV32_ILP32 uses [ILP32](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) as abi (Integer calling-convention only, and hardware floating-point calling convention is not used). +- **WAMR_BUILD_TARGET**: set the target CPU architecture. Supported targets: X86_64, X86_32, AARCH64, ARM, THUMB, XTENSA, ARC, RISCV32, RISCV64, and MIPS. + - For ARM and THUMB, use `[][_VFP]`. `` is the ARM sub-architecture. `_VFP` means arguments and returns use VFP coprocessor registers s0-s15 (d0-d7). Both are optional, for example ARMV7, ARMV7_VFP, THUMBV7, or THUMBV7_VFP. + - For AARCH64, use `[]`. VFP is on by default. `` is optional, for example AARCH64, AARCH64V8, or AARCH64V8.1. + - For RISCV64, use `[_abi]`. `_abi` is optional. Supported: RISCV64, RISCV64_LP64D, and RISCV64_LP64. RISCV64 and RISCV64_LP64D both use [LP64D](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) (LP64 with hardware floating-point for FLEN=64). RISCV64_LP64 uses [LP64](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) (integer calling convention only; no hardware floating-point calling convention). + - For RISCV32, use `[_abi]`. `_abi` is optional. Supported: RISCV32, RISCV32_ILP32D, RISCV32_ILP32F, and RISCV32_ILP32. RISCV32 and RISCV32_ILP32D both use [ILP32D](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) (ILP32 with hardware floating-point for FLEN=64). RISCV32_ILP32F uses [ILP32F](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) (ILP32 with hardware floating-point for FLEN=32). RISCV32_ILP32 uses [ILP32](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#named-abis) (integer calling convention only). ```bash cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM @@ -37,245 +143,275 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM ### **Configure interpreters** -- **WAMR_BUILD_INTERP**=1/0: enable or disable WASM interpreter +- **WAMR_BUILD_INTERP**=1/0: turn the WASM interpreter on or off. -- **WAMR_BUILD_FAST_INTERP**=1/0: build fast (default) or classic WASM interpreter. +- **WAMR_BUILD_FAST_INTERP**=1/0: pick fast (default) or classic interpreter. > [!NOTE] -> the fast interpreter runs ~2X faster than classic interpreter, but consumes about 2X memory to hold the pre-compiled code. +> The fast interpreter runs ~2X faster than classic interpreter, but consumes about 2X memory to hold the pre-compiled code. -### **Configure AOT and JITs** +### **Configure AOT** -- **WAMR_BUILD_AOT**=1/0, enable AOT or not, default to enable if not set -- **WAMR_BUILD_JIT**=1/0, enable LLVM JIT or not, default to disable if not set -- **WAMR_BUILD_FAST_JIT**=1/0, enable Fast JIT or not, default to disable if not set -- **WAMR_BUILD_FAST_JIT**=1 and **WAMR_BUILD_JIT**=1, enable Multi-tier JIT, default to disable if not set +- **WAMR_BUILD_AOT**=1/0: turn AOT on or off. Defaults to on. +- **WAMR_BUILD_WAMR_COMPILER**=1/0. It is used to wasm loader and compilation to indictate compiler mode. + +### **Configure LLVM JIT** + +Comparing with fast JIT, LLVM JIT covers more architectures and produces better optimized code, but takes longer on cold start. + +- **WAMR_BUILD_JIT**=1/0: turn LLVM JIT on or off. Defaults to off. +- **WAMR_BUILD_LAZY_JIT**=1/0: turn lazy JIT on or off. Defaults to off. With lazy JIT, functions are compiled in background threads before they are called, which can reduce startup time for large modules. + +### **Configure Fast JIT** + +The fast JIT is a lightweight JIT that emits code quickly and tunes hot functions. + +- **WAMR_BUILD_FAST_JIT**=1/0: turn Fast JIT on or off. Defaults to off. +- **WAMR_BUILD_FAST_JIT_DUMP**=1/0: dump fast JIT compiled code to stdout for debugging. Defaults to off. + +> [!WARNING] +> It currently covers only a few architectures (x86_64). + +### **Configure Multi-tier JIT** + +Use fast jit as the first tier and LLVM JIT as the second tier. + +- With **WAMR_BUILD_FAST_JIT**=1 and **WAMR_BUILD_JIT**=1, you get multi-tier JIT. Defaults to off. + +> [!WARNING] +> It currently covers only a few architectures (x86_64). ### **Configure LIBC** -- **WAMR_BUILD_LIBC_BUILTIN**=1/0, build the built-in libc subset for WASM app, default to enable if not set +- **WAMR_BUILD_LIBC_BUILTIN**=1/0: build the built-in libc subset for WASM apps. Defaults to on. -- **WAMR_BUILD_LIBC_WASI**=1/0, build the [WASI](https://github.com/WebAssembly/WASI) libc subset for WASM app, default to enable if not set +- **WAMR_BUILD_LIBC_WASI**=1/0: build the [WASI](https://github.com/WebAssembly/WASI) libc subset for WASM apps. Defaults to on. -- **WAMR_BUILD_LIBC_UVWASI**=1/0 (Experiment), build the [WASI](https://github.com/WebAssembly/WASI) libc subset for WASM app based on [uvwasi](https://github.com/nodejs/uvwasi) implementation, default to disable if not set +- **WAMR_BUILD_LIBC_UVWASI**=1/0 (Experiment): build the WASI libc subset for WASM apps using [uvwasi](https://github.com/nodejs/uvwasi). Defaults to off. + +- **WAMR_BUILD_LIBC_EMCC**=1/0: build the emcc-compatible libc subset for WASM apps. Defaults to off. > [!WARNING] -> WAMR doesn't support a safe sandbox on all platforms. For platforms that do not support **WAMR_BUILD_LIBC_WASI**, e.g. Windows, developers can try using an unsafe uvwasi-based WASI implementation by using **WAMR_BUILD_LIBC_UVWASI**. +> WAMR is not a secure sandbox on every platform. On platforms where **WAMR_BUILD_LIBC_WASI** is unsupported (for example Windows), you can try the uvwasi-based WASI via **WAMR_BUILD_LIBC_UVWASI**, but it is unsafe. -### **Enable Multi-Module feature** +### **Multi-Module feature** -- **WAMR_BUILD_MULTI_MODULE**=1/0, default to disable if not set +- **WAMR_BUILD_MULTI_MODULE**=1/0, default to off. > [!NOTE] -> See [Multiple Modules as Dependencies](./multi_module.md) for more details. +> See [Multiple Modules as Dependencies](./multi_module.md) for details. > [!WARNING] -> Currently, the multi-module feature is not supported in fast-jit and llvm-jit modes. +> The multi-module feature is not supported in fast-jit or llvm-jit modes. -### **Enable WASM mini loader** +### **WASM mini loader** -- **WAMR_BUILD_MINI_LOADER**=1/0, default to disable if not set +- **WAMR_BUILD_MINI_LOADER**=1/0, default to off. > [!NOTE] -> the mini loader doesn't check the integrity of the WASM binary file, developer must ensure that the WASM file is well-formed. - -### **Enable shared memory feature** - -- **WAMR_BUILD_SHARED_MEMORY**=1/0, default to disable if not set - -### **Enable bulk memory feature** - -- **WAMR_BUILD_BULK_MEMORY**=1/0, default to disable if not set - -### **Enable memory64 feature** - -- **WAMR_BUILD_MEMORY64**=1/0, default to disable if not set +> The mini loader skips integrity checks on the WASM binary. Make sure the file is valid yourself. > [!WARNING] -> Currently, the memory64 feature is only supported in classic interpreter running mode and AOT mode. +> This is a [privileged feature](#privileged-features) that compromises security. Use it only when you trust the WASM binary source. -### **Enable thread manager** +### **shared memory feature** -- **WAMR_BUILD_THREAD_MGR**=1/0, default to disable if not set +- **WAMR_BUILD_SHARED_MEMORY**=1/0, default to off. -### **Enable lib-pthread** +### **bulk memory feature** -- **WAMR_BUILD_LIB_PTHREAD**=1/0, default to disable if not set +- **WAMR_BUILD_BULK_MEMORY**=1/0, default to off. + +### **memory64 feature** + +- **WAMR_BUILD_MEMORY64**=1/0, default to off. + +> [!WARNING] +> Supported only in classic interpreter mode and AOT mode. + +### **thread manager** + +- **WAMR_BUILD_THREAD_MGR**=1/0, default to off. + +### **lib-pthread** + +- **WAMR_BUILD_LIB_PTHREAD**=1/0, default to off. > [!NOTE] -> The dependent feature of lib pthread such as the `shared memory` and `thread manager` will be enabled automatically. -> See [WAMR pthread library](./pthread_library.md) for more details. +> When you enable lib pthread, required features such as `shared memory` and `thread manager` are enabled automatically. See [WAMR pthread library](./pthread_library.md) for details. -### **Enable lib-pthread-semaphore** +### **lib-pthread-semaphore** -- **WAMR_BUILD_LIB_PTHREAD_SEMAPHORE**=1/0, default to disable if not set +- **WAMR_BUILD_LIB_PTHREAD_SEMAPHORE**=1/0, default to off. > [!NOTE] -> This feature depends on `lib-pthread`, it will be enabled automatically if this feature is enabled. +> This depends on `lib-pthread` and turns it on automatically. -### **Enable lib wasi-threads** +### **lib wasi-threads** -- **WAMR_BUILD_LIB_WASI_THREADS**=1/0, default to disable if not set +- **WAMR_BUILD_LIB_WASI_THREADS**=1/0, default to off. > [!NOTE] -> The dependent feature of lib wasi-threads such as the `shared memory` and `thread manager` will be enabled automatically. -> See [wasi-threads](./pthread_impls.md#wasi-threads-new) and [Introduction to WAMR WASI threads](https://bytecodealliance.github.io/wamr.dev/blog/introduction-to-wamr-wasi-threads) for more details. +> Enabling lib wasi-threads also enables its dependencies `shared memory` and `thread manager`. See [wasi-threads](./pthread_impls.md#wasi-threads-new) and [Introduction to WAMR WASI threads](https://bytecodealliance.github.io/wamr.dev/blog/introduction-to-wamr-wasi-threads) for details. -### **Enable lib wasi-nn** +### **lib wasi-nn** -- **WAMR_BUILD_WASI_NN**=1/0, default to disable if not set +- **WAMR_BUILD_WASI_NN**=1/0, default to off. +- **WAMR_BUILD_WASI_NN_LLAMACPP**=1/0, default to off. +- **WAMR_BUILD_WASI_NN_ONNX**=1/0, default to off. +- **WAMR_BUILD_WASI_NN_OPENVINO**=1/0, default to off. +- **WAMR_BUILD_WASI_NN_TFLITE**=1/0, default to off. > [!NOTE] -> WAMR_BUILD_WASI_NN without WAMR_BUILD_WASI_EPHEMERAL_NN is deprecated and will likely be removed in future versions of WAMR. Please consider to enable WAMR_BUILD_WASI_EPHEMERAL_NN as well. -> See [WASI-NN](../core/iwasm/libraries/wasi-nn) for more details. +> Using WAMR_BUILD_WASI_NN without WAMR_BUILD_WASI_EPHEMERAL_NN is deprecated and may be removed later. Please enable WAMR_BUILD_WASI_EPHEMERAL_NN too. See [WASI-NN](../core/iwasm/libraries/wasi-nn) for details. -### **Enable lib wasi-nn GPU mode** +### **lib wasi-nn GPU mode** -- **WAMR_BUILD_WASI_NN_ENABLE_GPU**=1/0, default to disable if not set +- **WAMR_BUILD_WASI_NN_ENABLE_GPU**=1/0, default to off. -### **Enable lib wasi-nn external delegate mode** +### **lib wasi-nn external delegate mode** -- **WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE**=1/0, default to disable if not set +- **WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE**=1/0, default to off. -- **WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH**=Path to the external delegate shared library (e.g. `libedgetpu.so.1.0` for Coral USB) +- **WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH**=Path to the external delegate shared library (for example `libedgetpu.so.1.0` for Coral USB). -### **Enable lib wasi-nn with `wasi_ephemeral_nn` module support** +### **lib wasi-nn with `wasi_ephemeral_nn` module support** -- **WAMR_BUILD_WASI_EPHEMERAL_NN**=1/0, default to enable if not set +- **WAMR_BUILD_WASI_EPHEMERAL_NN**=1/0, default to on. ### **Disable boundary check with hardware trap** -- **WAMR_DISABLE_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform +- **WAMR_DISABLE_HW_BOUND_CHECK**=1/0, default to on if the platform supports it. Otherwise, software boundary checks are used. > [!NOTE] -> by default only platform [linux/darwin/android/windows/vxworks 64-bit](https://github.com/bytecodealliance/wasm-micro-runtime/blob/5fb5119239220b0803e7045ca49b0a29fe65e70e/core/shared/platform/linux/platform_internal.h#L81) will enable the boundary check with hardware trap feature, for 32-bit platforms it's automatically disabled even when the flag is set to 0, and the wamrc tool will generate AOT code without boundary check instructions in all 64-bit targets except SGX to improve performance. The boundary check includes linear memory access boundary and native stack access boundary, if `WAMR_DISABLE_STACK_HW_BOUND_CHECK` below isn't set. +> By default only [linux/darwin/android/windows/vxworks 64-bit](https://github.com/bytecodealliance/wasm-micro-runtime/blob/5fb5119239220b0803e7045ca49b0a29fe65e70e/core/shared/platform/linux/platform_internal.h#L81) platforms enable this hardware trap boundary check. On 32-bit platforms it is off even if the flag is 0. The wamrc tool omits boundary check instructions in AOT code for all 64-bit targets except SGX to improve speed. The boundary check covers linear memory access and native stack access unless `WAMR_DISABLE_STACK_HW_BOUND_CHECK` is set. ### **Disable native stack boundary check with hardware trap** -- **WAMR_DISABLE_STACK_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform, same as `WAMR_DISABLE_HW_BOUND_CHECK`. +- **WAMR_DISABLE_STACK_HW_BOUND_CHECK**=1/0, default to on if the platform supports it; same rule as `WAMR_DISABLE_HW_BOUND_CHECK`. Otherwise, software boundary checks are used. > [!NOTE] -> When boundary check with hardware trap is disabled, or `WAMR_DISABLE_HW_BOUND_CHECK` is set to 1, the native stack boundary check with hardware trap will be disabled too, no matter what value is set to `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. And when boundary check with hardware trap is enabled, the status of this feature is set according to the value of `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. +> If hardware trap boundary checks are off (or `WAMR_DISABLE_HW_BOUND_CHECK` is 1), native stack boundary checks are also off regardless of `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. If hardware trap boundary checks are on, this setting decides whether the native stack check is on. ### **Disable async wakeup of blocking operation** -- **WAMR_DISABLE_WAKEUP_BLOCKING_OP**=1/0, default to enable if supported by the platform +- **WAMR_DISABLE_WAKEUP_BLOCKING_OP**=1/0, default to on when the platform supports it. > [!NOTE] -> The feature helps async termination of blocking threads. If you disable it, the runtime can wait for termination of blocking threads possibly forever. +> This feature lets blocking threads terminate asynchronously. If you disable it, blocking threads may never finish when asked to exit. -### **Enable tail call feature** +### **tail call feature** -- **WAMR_BUILD_TAIL_CALL**=1/0, default to disable if not set +- **WAMR_BUILD_TAIL_CALL**=1/0, default to off. -### **Enable 128-bit SIMD feature** +### **128-bit SIMD feature** -- **WAMR_BUILD_SIMD**=1/0, default to enable if not set +- **WAMR_BUILD_SIMD**=1/0, default to on. +- **WAMR_BUILD_SIMDE**=1/0, default to off. + +SIMDE (SIMD Everywhere) implements SIMD operations in fast interpreter mode. > [!WARNING] -> supported in AOT mode, JIT mode, and fast-interpreter mode with SIMDe library. +> Supported in AOT, JIT, and fast-interpreter modes with the SIMDe library. -### **Enable SIMDe library for SIMD in fast interpreter** +### **SIMDe library for SIMD in fast interpreter** -- **WAMR_BUILD_LIB_SIMDE**=1/0, default to disable if not set +- **WAMR_BUILD_LIB_SIMDE**=1/0, default to off. > [!NOTE] -> If enabled, SIMDe (SIMD Everywhere) library will be used to implement SIMD operations in fast interpreter mode. +> When enabled, SIMDe (SIMD Everywhere) implements SIMD operations in fast interpreter mode. -### **Enable Exception Handling** +### **Exception Handling** -- **WAMR_BUILD_EXCE_HANDLING**=1/0, default to disable if not set +- **WAMR_BUILD_EXCE_HANDLING**=1/0, default to off. + +> [!NOTE] +> Current implementation supports only Legacy Wasm exception handling proposal, not the latest version. > [!WARNING] -> Currently, the exception handling feature is only supported in classic interpreter running mode. +> Exception handling currently works only in classic interpreter mode. -### **Enable Garbage Collection** +### **Garbage Collection** -- **WAMR_BUILD_GC**=1/0, default to disable if not set +- **WAMR_BUILD_GC**=1/0, default to off. +- **WAMR_BUILD_GC_HEAP_VERIFY**=1/0, default to off. When enabled, verifies the heap during free. +- **WAMR_BUILD_STRINGREF**=1/0, default to off. When enabled, need to set WAMR_STRINGREF_IMPL_SOURCE as well > [!WARNING] -> Currently, the exception handling feature is not supported in fast-jit running mode. +> Current implentation of Garbage Collection(GC) is not fully compliant with the Wasm GC proposal and Wasm 3.0 specification. There are still few known limitations: +> +> - `exn` and `noexn` types are not supported. +> - nested structs and arrays are not fully supported. +> +> Garbage collection is not supported in fast-jit mode and multi-tier-jit mode. ### **Set the Garbage Collection heap size** -- **WAMR_BUILD_GC_HEAP_SIZE_DEFAULT**=n, default to 128 kB (131072) if not set +- **WAMR_BUILD_GC_HEAP_SIZE_DEFAULT**=n, default to 128 kB (131072). -### **Enable Multi Memory** +### **Multi Memory** -- **WAMR_BUIL_MULTI_MEMORY**=1/0, default to disable if not set +- **WAMR_BUIL_MULTI_MEMORY**=1/0, default to off. > [!WARNING] -> Currently, the multi memory feature is only supported in classic interpreter running mode. +> Multi memory is supported only in classic interpreter mode. -### **Configure Debug** +### **Name Section** -- **WAMR_BUILD_CUSTOM_NAME_SECTION**=1/0, load the function name from custom name section, default to disable if not set +- **WAMR_BUILD_CUSTOM_NAME_SECTION**=1/0: load function names from the custom name section. Default is off. -### **Enable AOT stack frame feature** +### **AOT stack frame feature** -- **WAMR_BUILD_AOT_STACK_FRAME**=1/0, default to disable if not set +- **WAMR_BUILD_AOT_STACK_FRAME**=1/0, default to off. > [!NOTE] -> if it is enabled, the AOT or JIT stack frames (like stack frame of classic interpreter but only necessary data is committed) will be created for AOT or JIT mode in function calls. And please add `--enable-dump-call-stack` option to wamrc during compiling AOT module. +> When enabled, AOT or JIT stack frames (similar to classic interpreter frames but storing only what is needed) are built during calls. Add `--enable-dump-call-stack` to wamrc when compiling AOT modules. -### **Enable dump call stack feature** +### **dump call stack feature** -- **WAMR_BUILD_DUMP_CALL_STACK**=1/0, default to disable if not set +- **WAMR_BUILD_DUMP_CALL_STACK**=1/0, default to off. > [!NOTE] -> if it is enabled, the call stack will be dumped when exception occurs. +> When enabled, the runtime dumps the call stack on exceptions. > -> - For interpreter mode, the function names are firstly extracted from _custom name section_, if this section doesn't exist or the feature is not enabled, then the name will be extracted from the import/export sections -> - For AOT/JIT mode, the function names are extracted from import/export section, please export as many functions as possible (for `wasi-sdk` you can use `-Wl,--export-all`) when compiling wasm module, and add `--enable-dump-call-stack --emit-custom-sections=name` option to wamrc during compiling AOT module. +> - In interpreter mode, names come first from the custom name section. If that section is absent or disabled, names come from import/export sections. +> - In AOT/JIT mode, names come from the import/export section. Export as many functions as possible (for `wasi-sdk` you can use `-Wl,--export-all`) when compiling the wasm module, and add `--enable-dump-call-stack --emit-custom-sections=name` to wamrc when compiling the AOT module. -### **Enable memory profiling (Experiment)** +### **memory profiling (Experiment)** -- **WAMR_BUILD_MEMORY_PROFILING**=1/0, default to disable if not set +- **WAMR_BUILD_MEMORY_PROFILING**=1/0, default to off. > [!NOTE] -> if it is enabled, developer can use API `void wasm_runtime_dump_mem_consumption(wasm_exec_env_t exec_env)` to dump the memory consumption info. -> Currently we only profile the memory consumption of module, module_instance and exec_env, the memory consumed by other components such as `wasi-ctx`, `multi-module` and `thread-manager` are not included. -> -> Also refer to [Memory usage estimation for a module](./memory_usage.md). +> When enabled, call `void wasm_runtime_dump_mem_consumption(wasm_exec_env_t exec_env)` to dump memory usage. Currently only module, module_instance, and exec_env memory are measured; other components such as `wasi-ctx`, `multi-module`, and `thread-manager` are not included. See [Memory usage estimation for a module](./memory_usage.md). -### **Enable performance profiling (Experiment)** +### **performance profiling (Experiment)** -- **WAMR_BUILD_PERF_PROFILING**=1/0, default to disable if not set +- **WAMR_BUILD_PERF_PROFILING**=1/0, default to off. > [!NOTE] -> if it is enabled, developer can use API `void wasm_runtime_dump_perf_profiling(wasm_module_inst_t module_inst)` to dump the performance consumption info. Currently we only profile the performance consumption of each WASM function. -> The function name searching sequence is the same with dump call stack feature. -> Also refer to [Tune the performance of running wasm/aot file](./perf_tune.md). +> When enabled, call `void wasm_runtime_dump_perf_profiling(wasm_module_inst_t module_inst)` to dump per-function performance. Function name lookup follows the same order as the dump call stack feature. See [Tune the performance of running wasm/aot file](./perf_tune.md). -### **Enable the global heap** +### **A pre-allocation for runtime and wasm apps** -- **WAMR_BUILD_GLOBAL_HEAP_POOL**=1/0, default to disable if not set for all _iwasm_ applications, except for the platforms Alios and Zephyr. +- **WAMR_BUILD_GLOBAL_HEAP_POOL**=1/0, default to off for _iwasm_ apps except on Alios and Zephyr. +- **WAMR_BUILD_GLOBAL_HEAP_SIZE**=n, default to 10 MB (10485760) for _iwasm_ apps, except Alios (256 kB), Riot (256 kB), and Zephyr (128 kB). > [!NOTE] -> **WAMR_BUILD_GLOBAL_HEAP_POOL** is used in the _iwasm_ applications provided in the directory `product-mini`. When writing your own host application using WAMR, if you want to use a global heap and allocate memory from it, you must set the initialization argument `mem_alloc_type` to `Alloc_With_Pool`. -> The global heap is defined in the documentation [Memory model and memory usage tunning](memory_tune.md). - -### **Set the global heap size** - -- **WAMR_BUILD_GLOBAL_HEAP_SIZE**=n, default to 10 MB (10485760) if not set for all _iwasm_ applications, except for the platforms Alios (256 kB), Riot (256 kB) and Zephyr (128 kB). - -> [!NOTE] -> **WAMR_BUILD_GLOBAL_HEAP_SIZE** is used in the _iwasm_ applications provided in the directory `product-mini`. When writing your own host application using WAMR, if you want to set the amount of memory dedicated to the global heap pool, you must set the initialization argument `mem_alloc_option.pool` with the appropriate values. -> The global heap is defined in the documentation [Memory model and memory usage tunning](memory_tune.md). +> When enabled, WAMR uses a big global heap for runtime and wasm apps instead of allocating memory from the system directly. This can reduce memory fragmentation and improve performance when many small allocations happen. The global heap is allocated at startup. **WAMR_BUILD_GLOBAL_HEAP_POOL** applies to _iwasm_ apps in `product-mini`. For your own host app, set `mem_alloc_type` to `Alloc_With_Pool` if you want to use a global heap. The global heap is described in [Memory model and memory usage tunning](memory_tune.md). **WAMR_BUILD_GLOBAL_HEAP_SIZE** applies to _iwasm_ apps in `product-mini`. For your host app, set `mem_alloc_option.pool` with the size you want for the global heap. The global heap is described in [Memory model and memory usage tunning](memory_tune.md). ### **Set maximum app thread stack size** -- **WAMR_APP_THREAD_STACK_SIZE_MAX**=n, default to 8 MB (8388608) if not set +- **WAMR_APP_THREAD_STACK_SIZE_MAX**=n, default to 8 MB (8388608). > [!NOTE] -> the AOT boundary check with hardware trap mechanism might consume large stack since the OS may lazily grow the stack mapping as a guard page is hit, we may use this configuration to reduce the total stack usage, e.g. -DWAMR_APP_THREAD_STACK_SIZE_MAX=131072 (128 KB). +> AOT boundary checks with hardware traps may use large stacks because the OS can grow stacks lazily when a guard page is hit. Use this setting to cap total stack use, for example `-DWAMR_APP_THREAD_STACK_SIZE_MAX=131072` (128 KB). -### **Set vprintf callback** +### **Host defined vprintf** -- **WAMR_BH_VPRINTF**=, default to disable if not set +- **WAMR_BH_VPRINTF**=, default to off. > [!NOTE] -> if the vprintf_callback function is provided by developer, the os_printf() and os_vprintf() in Linux, Darwin, Windows, VxWorks, Android and esp-idf platforms, besides WASI Libc output will call the callback function instead of libc vprintf() function to redirect the stdout output. For example, developer can define the callback function like below outside runtime lib: +> If you provide `vprintf_callback`, `os_printf()` and `os_vprintf()` on Linux, Darwin, Windows, VxWorks, Android, and esp-idf, plus WASI libc output, call your callback instead of libc `vprintf()`. Example outside the runtime lib: > > ```C > int my_vprintf(const char *format, va_list ap) @@ -293,12 +429,12 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM > } > ``` > -> and then use `cmake -DWAMR_BH_VPRINTF=my_vprintf ..` to pass the callback function, or add `BH_VPRINTF=my_vprintf` macro for the compiler, e.g. add line `add_definitions(-DBH_VPRINTF=my_vprintf)` in CMakeLists.txt. See [basic sample](../samples/basic/src/main.c) for a usage example. +> Then run `cmake -DWAMR_BH_VPRINTF=my_vprintf ..`, or add the compiler macro `BH_VPRINTF=my_vprintf` (for example `add_definitions(-DBH_VPRINTF=my_vprintf)` in CMakeLists.txt). See [basic sample](../samples/basic/src/main.c) for an example. -### **WAMR_BH_LOG**=, default to disable if not set +### **WAMR_BH_LOG**=, default to off. > [!NOTE] -> if the log_callback function is provided by the developer, WAMR logs are redirected to such callback. For example: +> If you provide `log_callback`, WAMR logs go there. Example: > > ```C > void my_log(uint32 log_level, const char *file, int line, const char *fmt, ...) @@ -307,77 +443,76 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM > } > ``` > -> See [basic sample](../samples/basic/src/main.c) for a usage example. +> See [basic sample](../samples/basic/src/main.c) for an example. -### **Enable reference types feature** +### **reference types feature** -- **WAMR_BUILD_REF_TYPES**=1/0, default to enable if not set +- **WAMR_BUILD_REF_TYPES**=1/0, default to on. ### **Exclude WAMR application entry functions** -- **WAMR_DISABLE_APP_ENTRY**=1/0, default to disable if not set +- **WAMR_DISABLE_APP_ENTRY**=1/0, default to off. > [!NOTE] -> The WAMR application entry (`core/iwasm/common/wasm_application.c`) encapsulate some common process to instantiate, execute the wasm functions and print the results. Some platform related APIs are used in these functions, so you can enable this flag to exclude this file if your platform doesn't support those APIs. -> _Don't enable this flag if you are building `product-mini`_ +> The WAMR application entry (`core/iwasm/common/wasm_application.c`) wraps common steps to instantiate and run wasm functions and print results. These use platform APIs. this flag to skip the file if your platform lacks those APIs. _Do not enable this flag when building `product-mini`._ -### **Enable source debugging features** +### **source debugging features** -- **WAMR_BUILD_DEBUG_INTERP**=1/0, default to 0 if not set +- **WAMR_BUILD_DEBUG_INTERP**=1/0, default to off. +- **WAMR_BUILD_DEBUG_AOT**=1/0, default to off. +- **WAMR_BUILD_DYNAMIC_AOT_DEBUG**=1/0, default to off. > [!NOTE] -> There are some other setup required by source debugging, please refer to [source_debugging.md](./source_debugging.md) and [WAMR source debugging basic](https://bytecodealliance.github.io/wamr.dev/blog/wamr-source-debugging-basic) for more details. +> Source debugging needs extra setup. See [source_debugging.md](./source_debugging.md) and [WAMR source debugging basic](https://bytecodealliance.github.io/wamr.dev/blog/wamr-source-debugging-basic). -### **Enable load wasm custom sections** +### **load wasm custom sections** -- **WAMR_BUILD_LOAD_CUSTOM_SECTION**=1/0, default to disable if not set +- **WAMR_BUILD_LOAD_CUSTOM_SECTION**=1/0, default to off. > [!NOTE] -> By default, the custom sections are ignored. If the embedder wants to get custom sections from `wasm_module_t`, then `WAMR_BUILD_LOAD_CUSTOM_SECTION` should be enabled, and then `wasm_runtime_get_custom_section` can be used to get a custom section by name. -> -> If `WAMR_BUILD_CUSTOM_NAME_SECTION` is enabled, then the `custom name section` will be treated as a special section and consumed by the runtime, not available to the embedder. -> For AoT file, must use `--emit-custom-sections` to specify which sections need to be emitted into AoT file, otherwise all custom sections will be ignored. +> By default, custom sections are ignored. `WAMR_BUILD_LOAD_CUSTOM_SECTION` so the embedder can read them via `wasm_runtime_get_custom_section`. If `WAMR_BUILD_CUSTOM_NAME_SECTION` is on, the custom name section is consumed by the runtime and unavailable to the embedder. For AoT files, pass `--emit-custom-sections` to wamrc to keep the sections; otherwise they are dropped. ### **Stack guard size** -- **WAMR_BUILD_STACK_GUARD_SIZE**=n, default to N/A if not set. +- **WAMR_BUILD_STACK_GUARD_SIZE**=n, default to N/A when not set. > [!NOTE] -> By default, the stack guard size is 1K (1024) or 24K (if uvwasi enabled). +> By default, stack guard size is 1K (1024) or 24K when uvwasi is enabled. ### **Disable writing the linear memory base address to x86 GS segment register** -- **WAMR_DISABLE_WRITE_GS_BASE**=1/0, default to enable if not set and supported by platform +- **WAMR_DISABLE_WRITE_GS_BASE**=1/0, default to on if the platform supports it. > [!NOTE] -> by default only platform [linux x86-64](https://github.com/bytecodealliance/wasm-micro-runtime/blob/5fb5119239220b0803e7045ca49b0a29fe65e70e/core/shared/platform/linux/platform_internal.h#L67) will enable this feature, for 32-bit platforms it's automatically disabled even when the flag is set to 0. In linux x86-64, writing the linear memory base address to x86 GS segment register may be used to speedup the linear memory access for LLVM AOT/JIT, when `--enable-segue=[]` option is added for `wamrc` or `iwasm`. - -> See [Enable segue optimization for wamrc when generating the aot file](./perf_tune.md#3-enable-segue-optimization-for-wamrc-when-generating-the-aot-file) for more details. +> By default only [linux x86-64](https://github.com/bytecodealliance/wasm-micro-runtime/blob/5fb5119239220b0803e7045ca49b0a29fe65e70e/core/shared/platform/linux/platform_internal.h#L67) enables this. On 32-bit platforms it stays off even if set to 0. On linux x86-64, writing the linear memory base to the GS segment can speed up linear memory access for LLVM AOT/JIT when `--enable-segue=[]` is passed to `wamrc` or `iwasm`. +> +> See [segue optimization for wamrc when generating the aot file](./perf_tune.md#3-enable-segue-optimization-for-wamrc-when-generating-the-aot-file) for details. ### **User defined linear memory allocator** -- **WAMR_BUILD_ALLOC_WITH_USAGE**=1/0, default to disable if not set +- **WAMR_BUILD_ALLOC_WITH_USAGE**=1/0, default to off. +- **WAMR_BUILD_ALLOC_WITH_USER_DATA**=1/0, default to off. > [!NOTE] -> by default, the linear memory is allocated by system. when it's set to 1 and Alloc_With_Allocator is selected, it will be allocated by customer. +> By default, the system allocates linear memory. With this on and `Alloc_With_Allocator` selected, you can provide your own allocator. -### **Enable running PGO(Profile-Guided Optimization) instrumented AOT file** +### **running PGO(Profile-Guided Optimization) instrumented AOT file** -- **WAMR_BUILD_STATIC_PGO**=1/0, default to disable if not set +- **WAMR_BUILD_STATIC_PGO**=1/0, default to off. > [!NOTE] -> See [Use the AOT static PGO method](./perf_tune.md#5-use-the-aot-static-pgo-method) for more details. +> See [Use the AOT static PGO method](./perf_tune.md#5-use-the-aot-static-pgo-method). -### **Enable linux perf support** +### **linux perf support** -- **WAMR_BUILD_LINUX_PERF**=1/0, enable linux perf support to generate the flamegraph to analyze the performance of a wasm application, default to disable if not set +- **WAMR_BUILD_LINUX_PERF**=1/0: enable linux perf support to generate flamegraphs for wasm app performance. Default is off. > [!NOTE] -> See [Use linux-perf](./perf_tune.md#7-use-linux-perf) for more details. +> See [Use linux-perf](./perf_tune.md#7-use-linux-perf). -### **Enable module instance context APIs** +### **module instance context APIs** -- **WAMR_BUILD_MODULE_INST_CONTEXT**=1/0, enable module instance context APIs which can set one or more contexts created by the embedder for a wasm module instance, default to enable if not set: +- **WAMR_BUILD_MODULE_INST_CONTEXT**=1/0: enable module instance context APIs so the embedder can set one or more contexts for a wasm module instance. Default is on. ```C wasm_runtime_create_context_key @@ -388,78 +523,63 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM ``` > [!NOTE] -> See [wasm_export.h](../core/iwasm/include/wasm_export.h) for more details. +> See [wasm_export.h](../core/iwasm/include/wasm_export.h) for details. -### **Enable quick AOT/JTI entries** +### **quick AOT/JTI entries** -- **WAMR_BUILD_QUICK_AOT_ENTRY**=1/0, enable registering quick call entries to speedup the aot/jit func call process, default to enable if not set +- **WAMR_BUILD_QUICK_AOT_ENTRY**=1/0: register quick call entries to speed up AOT/JIT function calls. Default is on. > [!NOTE] -> See [Refine callings to AOT/JIT functions from host native](./perf_tune.md#83-refine-callings-to-aotjit-functions-from-host-native) for more details. +> See [Refine callings to AOT/JIT functions from host native](./perf_tune.md#83-refine-callings-to-aotjit-functions-from-host-native). -### **Enable AOT intrinsics** +### **AOT intrinsics** -- **WAMR_BUILD_AOT_INTRINSICS**=1/0, enable the AOT intrinsic functions, default to enable if not set. These functions can be called from the AOT code when `--disable-llvm-intrinsics` flag or `--enable-builtin-intrinsics=` flag is used by wamrc to generate the AOT file. +- **WAMR_BUILD_AOT_INTRINSICS**=1/0: turn on AOT intrinsic functions. Default is on. AOT code can call these when wamrc uses `--disable-llvm-intrinsics` or `--enable-builtin-intrinsics=`. > [!NOTE] -> See [Tuning the XIP intrinsic functions](./xip.md#tuning-the-xip-intrinsic-functions) for more details. +> See [Tuning the XIP intrinsic functions](./xip.md#tuning-the-xip-intrinsic-functions). -### **Enable extended constant expression** +### **extended constant expression** -- **WAMR_BUILD_EXTENDED_CONST_EXPR**=1/0, default to disable if not set. +- **WAMR_BUILD_EXTENDED_CONST_EXPR**=1/0, default to off. > [!NOTE] -> See [Extended Constant Expressions](https://github.com/WebAssembly/extended-const/blob/main/proposals/extended-const/Overview.md) for more details. +> See [Extended Constant Expressions](https://github.com/WebAssembly/extended-const/blob/main/proposals/extended-const/Overview.md). -### **Enable bulk-memory-opt** +### **bulk-memory-opt** -- **WAMR_BUILD_BULK_MEMORY_OPT**=1/0, default to disable if not set. +- **WAMR_BUILD_BULK_MEMORY_OPT**=1/0, default to off. > [!NOTE] -> See [bulk-memory-opt](https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#bulk-memory-opt) for more details. +> See [bulk-memory-opt](https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#bulk-memory-opt). -### **Enable call-indirect-overlong** +### **call-indirect-overlong** -- **WAMR_BUILD_CALL_INDIRECT_OVERLONG**=1/0, default to disable if not set. +- **WAMR_BUILD_CALL_INDIRECT_OVERLONG**=1/0, default to off. > [!NOTE] -> See [call-indirect-overlong](https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#call-indirect-overlong) for more details. +> See [call-indirect-overlong](https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#call-indirect-overlong). -### **Enable Lime1 target** +### **Lime1 target** -- **WAMR_BUILD_LIME1**=1/0, default to disable if not set. +- **WAMR_BUILD_LIME1**=1/0, default to off. > [!NOTE] -> See [Lime1](https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1) for more details. +> See [Lime1](https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1). ### **Configurable memory access boundary check** -- **WAMR_CONFIGURABLE_BOUNDS_CHECKS**=1/0, default to disable if not set +- **WAMR_CONFIGURABLE_BOUNDS_CHECKS**=1/0, default to off. -> [!NOTE] -> If it is enabled, allow to run `iwasm --disable-bounds-checks` to disable the memory access boundary checks for interpreter mode. - -### **Module instance context APIs** - -- **WAMR_BUILD_MODULE_INST_CONTEXT**=1/0, default to disable if not set - -> [!NOTE] -> If it is enabled, allow to set one or more contexts created by embedder for a module instance, the below APIs are provided: -> -> ```C -> wasm_runtime_create_context_key -> wasm_runtime_destroy_context_key -> wasm_runtime_set_context -> wasm_runtime_set_context_spread -> wasm_runtime_get_context -> ``` +> [!WARNING] +> When enabled, you can run `iwasm --disable-bounds-checks` to turn off memory access boundary checks in interpreter mode. This is a [privileged feature](#privileged-features); use it carefully. ### **Shared heap among wasm apps and host native** -- **WAMR_BUILD_SHARED_HEAP**=1/0, default to disable if not set +- **WAMR_BUILD_SHARED_HEAP**=1/0, default to off. > [!NOTE] -> If it is enabled, allow to create one or more shared heaps, and attach one to a module instance, the belows APIs ared provided: +> When enabled, you can create and attach shared heaps, and the following APIs become available: > > ```C > wasm_runtime_create_shared_heap @@ -469,7 +589,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM > wasm_runtime_shared_heap_free > ``` > -> And the wasm app can calls below APIs to allocate/free memory from/to the shared heap if it is attached to the app's module instance: +> A wasm app can call these to use the shared heap attached to its module instance: > > ```C > void *shared_heap_malloc(); @@ -477,44 +597,118 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM > ``` > [!WARNING] -> Currently, the shared-heap feature is not supported in fast-jit mode. +> The shared-heap feature is not supported in fast-jit mode. ### **Shrunk the memory usage** -- **WAMR_BUILD_SHRUNK_MEMORY**=1/0, default to enable if not set +- **WAMR_BUILD_SHRUNK_MEMORY**=1/0, default to on. > [!NOTE] -> When enabled, this feature will reduce memory usage by decreasing the size of the linear memory, particularly when the `memory.grow` opcode is not used and memory usage is somewhat predictable. +> When enabled, this reduces memory by shrinking linear memory, especially when `memory.grow` is unused and memory needs are predictable. -## **Instruction metering** +### **Instruction metering** -- **WAMR_BUILD_INSTRUCTION_METERING**=1/0, default to disable if not set +- **WAMR_BUILD_INSTRUCTION_METERING**=1/0, default to off. > [!NOTE] -> Enabling this feature allows limiting the number of instructions a wasm module instance can execute. Use the `wasm_runtime_set_instruction_count_limit(...)` API before calling `wasm_runtime_call_*(...)` APIs to enforce this limit. +> This limits the number of instructions a wasm module instance can run. Call `wasm_runtime_set_instruction_count_limit(...)` before `wasm_runtime_call_*(...)` to enforce the cap. + +> [!WARNING] +> This is only supported in classic interpreter mode. + +## **Branch hints** + +- **WAMR_BUILD_BRANCH_HINTS**=1/0, default to disable if not set + +> [!NOTE] +> Enabling this feature allows the runtime to utilize branch hints for better performance during aot/jit execution. ## **Combination of configurations:** -We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command: +### **Invoke general FFI** + +- **WAMR_BUILD_INVOKE_NATIVE_GENERAL**=1/0, default to off. + +By default, WAMR uses architecture-specific calling conventions to call native functions from WASM modules. When this feature is enabled, WAMR uses a general calling convention that works on all architectures but is slower. The details are in [iwasm_common.cmake](../core/iwasm/common/iwasm_common.cmake) + +### **Host defined log** + +- **WAMR_BH_LOG**=, default to off. + +### **AOT Validator** + +- **WAMR_BUILD_AOT_VALIDATOR**=1/0, default to off. + +> [!NOTE] +> By default, WAMR believes AOT files are valid and unforged. + +### **Copy Call Stack** + +- **WAMR_BUILD_COPY_CALL_STACK**=1/0, default to off. + +> [!NOTE] +> Unlike [dump call stack](dump-call-stack-feature), which prints the call stack on exceptions, this feature lets the embedder copy the call stack programmatically via `wasm_runtime_dump_call_stack_to_buf()`. + +### **Librats** + +- **WAMR_BUILD_LIB_RATS**=1/0, default to off. + +> [librats](https://github.com/inclavare-containers/librats) is a C library designed to facilitate remote attestation for secure computing environments. It provides a framework for attesting the integrity of computing environments remotely, enabling trust establishment between different Trusted Execution Environments (TEEs). + +> [!WARNING] +> This is for Intel SGX platforms only. + +### **Sanitizer** + +- **WAMR_BUILD_SANITIZER**=[ubsan|asan|tsan|posan], default is empty + +Use one or more of the following sanitizers when building WAMR with sanitizer support: AddressSanitizer, UndefinedBehaviorSanitizer, ThreadSanitizer, or Pointer-Overflow Sanitizer. + +### **Intel Protected File System** + +- **WAMR_BUILD_SGX_IPFS**=1/0, default to off. + +> [!WARNING] +> This is for Intel SGX platforms only. + +### **Support spec test** + +- **WAMR_BUILD_SPEC_TEST**=1/0, default to off. + +### **WASM Cache** + +- **WAMR_BUILD_WASM_CACHE**=1/0, default to off. + +### **Test Garbage Collection** + +- **WAMR_TEST_GC**=1/0, default to off. + +It is used to test garbage collection related APIs and features. Refer to [iwasm_gc.cmake](../core/iwasm/common/gc/iwasm_gc.cmake) for details. + +It is used to cache loaded wasm modules in memory to speed up module instantiation only in wasm-c-api. + +## **Combination of configurations** + +You can mix settings. For example, to disable the interpreter, enable AOT and WASI, run: ```Bash cmake .. -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_LIBC_WASI=1 -DWAMR_BUILD_PLATFORM=linux ``` -Or if we want to enable interpreter, disable AOT and WASI, and build as X86_32, we can run command: +To enable the interpreter, disable AOT and WASI, and target X86_32, run: ```Bash cmake .. -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_LIBC_WASI=0 -DWAMR_BUILD_TARGET=X86_32 ``` -When enabling SIMD for fast interpreter mode, you'll need to enable both SIMD and the SIMDe library: +When enabling SIMD for fast interpreter mode, turn on both SIMD and the SIMDe library: ```Bash cmake .. -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_SIMD=1 -DWAMR_BUILD_LIB_SIMDE=1 ``` -For Valgrind, begin with the following configurations and add additional ones as needed: +For Valgrind, start with these and add more as needed: ```Bash #... @@ -524,8 +718,7 @@ For Valgrind, begin with the following configurations and add additional ones as #... ``` -To enable the minimal Lime1 feature set, we need to disable some features that are on by default, such as -bulk memory and reference types: +To enable the minimal Lime1 feature set, turn off features that are on by default such as bulk memory and reference types: ```Bash cmake .. -DWAMR_BUILD_LIME1=1 -DWAMR_BUILD_BULK_MEMORY=0 -DWAMR_BUILD_REF_TYPES=0 -DDWAMR_BUILD_SIMD=0 diff --git a/doc/shared_heap.md b/doc/shared_heap.md new file mode 100644 index 000000000..4d014b08b --- /dev/null +++ b/doc/shared_heap.md @@ -0,0 +1,38 @@ +# Introducing the Shared-Heap Feature in WAMR + +In the world of WebAssembly, flexibility and performance are key. The WebAssembly Micro Runtime (WAMR) has introduced a powerful feature known as the shared heap, designed to enhance performance by allowing data sharing between multiple WebAssembly (WASM) instances, or between WASM and its host, without incurring the overhead of data copying. Let's delve into what this feature offers and how it can be effectively utilized. + +## What is the Shared Heap? + +The shared heap is an innovative extension of the WebAssembly linear memory. Unlike traditional memory, which requires data copying between WASM instances or to the host, the shared heap allows direct access to the same memory space. This can significantly improve performance in scenarios where multiple WASM instances need to interact or share data with the host. + +## Key Benefits + +- Expanded Memory Space: The shared-heap feature effectively expands the linear memory space by introducing hosted memory address spaces. This new linear memory space can be seen as a virtual space, encompassing multiple real spaces. +- Toolchain Workaround: The shared heap acts as a workaround for the current lack of toolchain support for the multi-memory proposal. This provides a practical solution for developers needing enhanced memory capabilities. +- Boundary Checks and Sandbox Protection: The shared heap maintains boundary checks and extends sandbox protection to portions of the real memory space, ensuring secure and reliable memory access across shared heaps. +- Ongoing Evaluation: The shared-heap feature is still under evaluation, and the team is actively seeking better solutions to further improve the functionality and performance. + +## How Does It Work? + +While the concept of a shared heap might seem straightforward, implementing it correctly requires careful attention. It is a runtime feature, not part of the standard WebAssembly specification, nor an ongoing proposal. Here’s how you can leverage the shared heap in your applications: + +### Creating a Shared Heap + +1. WAMR Managed Shared Heap: Use the `wasm_runtime_create_shared_heap(SharedHeapInitArgs \*init_args)` API to create a shared heap. If only `init_args.size` is specified with `init_args.pre_allocated_addr` set to NULL, WAMR will allocate and manage the shared heap. This allows dynamic memory management through `wasm_runtime_shared_heap_malloc()` and `wasm_runtime_shared_heap_free()`. Memory allocation from this heap is valid and can be shared, with automatic cleanup when the runtime is destroyed. + +2. Preallocated Shared Heap: Alternatively, you can use pre-allocated memory, either from the system heap or a static global buffer. This requires you to handle its accessibility, size, and management. Specify `init_args.pre_allocated_addr` along with `init_args.size` to create this type of shared heap, which acts as a single large chunk for direct data sharing. + +### Creating and Attaching Shared Heap Chains + +To form a unified memory space, you can chain multiple shared heaps using the `wasm_runtime_chain_shared_heaps(wasm_shared_heap_t head, wasm_shared_heap_t body)` API. This creates a continuous memory region from the perspective of the WASM app, even though it might consist of separate regions in the native environment. + +Once chained, attach the shared heap to WASM apps using `wasm_runtime_attach_shared_heaps(wasm_module_inst_t module_inst, wasm_shared_heap_t shared_heaps)`. This ensures no overlap with the existing linear memory of the WASM app instance, preventing accidental overwrites. + +### Resource Allocation and Data Transfer + +After attaching the shared heap, both host and WASM code can allocate resources directly from it. Host code can use `wasm_runtime_shared_heap_malloc()`, while WASM code can utilize `shared_heap_malloc()`. This allows one side to allocate memory and pass the address or index to the other side, facilitating efficient data transfer. The original boundary checks for loading and storing in linear memory naturally extend to the shared-heap area, as it is part of the linear memory. This integration ensures that memory operations remain secure and consistent. + +## Conclusion + +The shared heap feature is an exciting advancement in WASM performance optimization. By enabling direct memory sharing, it reduces overhead and boosts efficiency in applications requiring high interactivity. While it offers great benefits, remember it heavily relies on correct implementation to manage shared data effectively. As the feature is still under evaluation, let's work together on a better solution. We are collecting every potential usage and unique feature, looking for the shared common ground that will drive future innovations in WebAssembly applications. diff --git a/doc/stability_wasm_proposals.md b/doc/stability_wasm_proposals.md index 8ad057119..12f9fee66 100644 --- a/doc/stability_wasm_proposals.md +++ b/doc/stability_wasm_proposals.md @@ -12,17 +12,16 @@ Users can turn those features on or off by using compilation options. If a relev ## On-by-default Wasm Proposals -| Proposal | >= Phase 4 | Compilation Option | -| ------------------------------------- | ---------- |----------------------------| -| Bulk Memory Operations | Yes | `WAMR_BUILD_BULK_MEMORY` | -| Fixed-width SIMD[^1] | Yes | `WAMR_BUILD_SIMD` | -| Import/Export of Mutable Globals[^2] | Yes | N/A | -| Multi-value | Yes | N/A | -| Non-trapping float-to-int Conversions | Yes | N/A | -| Reference Types | Yes | `WAMR_BUILD_REF_TYPES` | -| Sign-extension Operators | Yes | N/A | -| WebAssembly C and C++ API | No | N/A | -| Branch Hinting | Yes | `WASM_ENABLE_BRANCH_HINTS` | +| Proposal | >= Phase 4 | Compilation Option | +| ------------------------------------- | ---------- | ------------------------ | +| Bulk Memory Operations | Yes | `WAMR_BUILD_BULK_MEMORY` | +| Fixed-width SIMD[^1] | Yes | `WAMR_BUILD_SIMD` | +| Import/Export of Mutable Globals[^2] | Yes | N/A | +| Multi-value | Yes | N/A | +| Non-trapping float-to-int Conversions | Yes | N/A | +| Reference Types | Yes | `WAMR_BUILD_REF_TYPES` | +| Sign-extension Operators | Yes | N/A | +| WebAssembly C and C++ API | No | N/A | [^1]: llvm-jit and aot only. @@ -31,7 +30,8 @@ Users can turn those features on or off by using compilation options. If a relev ## Off-by-default Wasm Proposals | Proposal | >= Phase 4 | Compilation Option | -| ----------------------------- | ---------- | ---------------------------------| +| ----------------------------- | ---------- | -------------------------------- | +| Branch Hinting | Yes | `WASM_ENABLE_BRANCH_HINTS` | | Extended Constant Expressions | Yes | `WAMR_BUILD_EXTENDED_CONST_EXPR` | | Garbage Collection | Yes | `WAMR_BUILD_GC` | | Legacy Exception Handling[^3] | No | `WAMR_BUILD_EXCE_HANDLING` | @@ -49,6 +49,7 @@ Users can turn those features on or off by using compilation options. If a relev this proposal is discouraged. [^4]: interpreter only + [^5]: `WAMR_BUILD_LIB_PTHREAD` can also be used to enable ## Unimplemented Wasm Proposals diff --git a/doc/tiered_support.md b/doc/tiered_support.md index 565d347b2..4cce12c8c 100644 --- a/doc/tiered_support.md +++ b/doc/tiered_support.md @@ -1,196 +1,184 @@ -# Tiered Supported +# Tiered Support -**Tier definitions** +## Tier A -- **A — Production Ready:** fully tested and stable. -- **B — Almost Production Ready:** partially tested; close to production. -- **C — Experimental / Not Production Ready:** unfinished or volatile. +This tier is the highest level of support. Features and targets in this tier are fully supported, actively maintained, and regularly tested. Users can expect prompt assistance and comprehensive documentation for any issues or questions related to these features. Users can rely on Tier A features for production environments. Targets in this tier usually have been used in products. -The condition _tested_ mentioned above specifically refers to whether there are enough tests in CI. +## Tier B -## Architecture Support +This tier represents a moderate level of support. Features and targets in this tier are generally supported and maintained, but may not receive the same level of attention as Tier A. While efforts are made to ensure stability, users may encounter occasional issues that are not immediately addressed. Documentation may be less comprehensive compared to Tier A. Users are encouraged to report any issues they encounter, but response times may vary. -| Architecture | Tier | -| ------------ | ----- | -| **x86-64** | **A** | -| **x86-32** | **A** | -| AArch64 | B | -| ARC | B | -| ARM | B | -| RISCV32 | B | -| RISCV64 | B | -| THUMB | B | -| XTENSA | B | -| MIPS | C | +## Tier C -## OS / Platform Support +This tier indicates experimental features with foundational support levels. These implementations are typically optimized for specific platforms, running modes, or use cases, and may not receive active maintenance. Documentation tends to be minimal or require updates. Production deployment requires specialized expertise and careful evaluation, including establishing appropriate threat models and ensuring comprehensive understanding of the implementation scope. Users should be prepared to troubleshoot issues and handle ongoing maintenance independently, accepting full responsibility for any limitations or challenges that may arise. -| Platform | Tier | -| ------------------ | ----- | -| **NuttX** | **A** | -| **Ubuntu** | **A** | -| Android | B | -| macOS | B | -| Windows | B | -| Zephyr | B | -| AliOS-Things | C | -| Cosmopolitan | C | -| ESP-IDF (FreeRTOS) | C | -| FreeBSD | C | -| iOS | C | -| RT-Thread | C | -| RIOT | C | -| VxWorks | C | +> [!NOTE] +> +> - **actively maintained** and **fully supported**. users can expect timely assistance, comprehensive documentation, and regular updates for any issues or questions related to these features. +> - **regularly tested**. means there are automated tests in CI that run on a regular basis to ensure the stability and functionality of these features. -## WebAssembly Proposal Support +## Labels -> During configuration, It is able to disable or enable the following features by setting the corresponding flags (see Appendix). It is also possible to check features status in the configuration output. +**Target** refers to the specific hardware architecture or operating system that the runtime can be compiled for and run on. -| WASM Proposal / Extension | Tier | -| -------------------------------------- | ----------- | -| **Bulk Memory** | A | -| **Extended Constant Expressions** | A | -| **Import/Export of Mutable Globals** | A | -| **Memory64** | A | -| **Multi-value** | A | -| **Non-trapping float-to-int** | A | -| **Reference Types** | A | -| **Shared Memory (Threads)** | A | -| **SIMD (128-bit)** | A | -| **Sign-extension Operators** | A | -| GC (Garbage Collection) | B | -| Stringref | B | -| Tail Calls | B | -| Multi-memory | C | -| Legacy Exception Handling | C | -| Branch Hinting | Unsupported | -| Custom Annotation Syntax (text format) | Unsupported | -| Exception Handling (new spec) | Unsupported | -| JS String Builtins | Unsupported | -| Relaxed SIMD | Unsupported | +**Runtime Extensions** are features that extend the runtime capabilities of the system beyond the core WebAssembly specification. These extensions may include optimizations, additional APIs, or other enhancements that improve performance, usability, or functionality. -# WAMR-Specific Feature Support +**Portability** indicates the ability of the runtime to operate across different platforms or environments without requiring significant modifications. This includes compatibility with various operating systems, hardware architectures, and development frameworks. -> During configuration, It is able to disable or enable the following features by setting the corresponding flags (see Appendix). It is also possible to check features status in the configuration output. +# TierA -| WAMR Feature | Tier | -| --------------------------------- | ---- | -| **AoT (wamrc)** | A | -| **AOT intrinsics** | A | -| **Fast Interpreter** | A | -| **Interpreter (classic)** | A | -| **Libc builtin** | A | -| **Libc WASI** | A | -| **Quick AOT/JIT entries** | A | -| **Shrunk memory** | A | -| **Wakeup of blocking operations** | A | -| **WASM C API** | A | -| Fast JIT | B | -| LLVM ORC JIT | B | -| Memory profiling | B | -| Module instance context[^7] | B | -| Multi-module | B | -| Perf profiling | B | -| Pthread | B | -| Shared heap | B | -| WASI threads | B | -| WASI-NN (neural network APIs) | B | -| Debug Interpreter | B | -| Debug AOT | C | -| Tier-up (Fast JIT → LLVM JIT) | C | +## Targets ---- +| Description | +| -------------------------- | +| aarch64-unknown-nuttx-eabi | +| i386-pc-linux-gnu | +| x86_64-pc-linux-gnu | +| x86_64-apple-darwin | +| x86_64-none-linux-gnu | -# Appendix: All compilation flags +## Features -| Compilation flags | Tiered | Default | on Ubuntu | -| ------------------------------------------- | ------ | ------- | --------- | -| WAMR_APP_THREAD_STACK_SIZE_MAX | B | ND[^1] | | -| WAMR_BH_LOG | B | ND | | -| WAMR_BH_VPRINTF | B | ND | | -| WAMR_BUILD_ALLOC_WITH_USAGE | B | ND | | -| WAMR_BUILD_ALLOC_WITH_USER_DATA | B | ND | | -| WAMR_BUILD_AOT | A | ND | 1 | -| WAMR_BUILD_AOT_INTRINSICS | A | 1[^2] | | -| WAMR_BUILD_AOT_STACK_FRAME | A | ND | | -| WAMR_BUILD_AOT_VALIDATOR | B | ND | | -| WAMR_BUILD_BULK_MEMORY | A | 1 | | -| WAMR_BUILD_COPY_CALL_STACK | B | ND | | -| WAMR_BUILD_CUSTOM_NAME_SECTION | B | ND | | -| WAMR_BUILD_DEBUG_AOT | C | ND | | -| WAMR_BUILD_DEBUG_INTERP | B | ND | | -| WAMR_BUILD_DUMP_CALL_STACK | B | ND | | -| WAMR_BUILD_DYNAMIC_AOT_DEBUG | C | ND | | -| WAMR_BUILD_EXCE_HANDLING | C | 0 | | -| WAMR_BUILD_EXTENDED_CONST_EXPR | A | 0 | | -| WAMR_BUILD_FAST_INTERP | A | ND | 1 | -| WAMR_BUILD_FAST_JIT | B | ND | | -| WAMR_BUILD_FAST_JIT_DUMP | B | ND | | -| WAMR_BUILD_GC | B | 0 | | -| WAMR_BUILD_GC_HEAP_VERIFY | B | ND | | -| WAMR_BUILD_GLOBAL_HEAP_POOL | A | ND | | -| WAMR_BUILD_GLOBAL_HEAP_SIZE | A | ND | | -| WAMR_BUILD_INSTRUCTION_METERING | C | ND | | -| WAMR_BUILD_INTERP | A | ND | 1 | -| WAMR_BUILD_INVOKE_NATIVE_GENERAL | B | ND | | -| WAMR_BUILD_JIT | B | ND | | -| WAMR_BUILD_LAZY_JIT | B | 1[^3] | | -| WAMR_BUILD_LIBC_BUILTIN | A | ND | 1 | -| WAMR_BUILD_LIBC_EMCC | C | ND | | -| WAMR_BUILD_LIBC_UVWASI | C | ND | | -| WAMR_BUILD_LIBC_WASI | A | ND | 1 | -| WAMR_BUILD_LIB_PTHREAD | B | ND | | -| WAMR_BUILD_LIB_PTHREAD_SEMAPHORE | B | ND | | -| WAMR_BUILD_LIB_RATS | C | ND | | -| WAMR_BUILD_LIB_WASI_THREADS | B | ND | | -| WAMR_BUILD_LINUX_PERF | B | ND | | -| WAMR_BUILD_LIME1 | A | NO | | -| WAMR_BUILD_LOAD_CUSTOM_SECTION | A | ND | | -| WAMR_BUILD_MEMORY64 | A | 0 | | -| WAMR_BUILD_MEMORY_PROFILING | B | ND | | -| WAMR_BUILD_MINI_LOADER | B | ND | | -| WAMR_BUILD_MODULE_INST_CONTEXT | B | ND | 1 | -| WAMR_BUILD_MULTI_MEMORY | C | 0 | | -| WAMR_BUILD_MULTI_MODULE | B | ND | | -| WAMR_BUILD_PERF_PROFILING | B | ND | | -| WAMR_BUILD_PLATFORM | - | ND | linux | -| WAMR_BUILD_QUICK_AOT_ENTRY | A | 1[^4] | | -| WAMR_BUILD_REF_TYPES | A | ND | 1 | -| WAMR_BUILD_SANITIZER | B | ND | | -| WAMR_BUILD_SGX_IPFS | C | ND | | -| WAMR_BUILD_SHARED_HEAP | A | ND | | -| WAMR_BUILD_SHARED_MEMORY | A | 0 | 1 | -| WAMR_BUILD_SHRUNK_MEMORY | A | ND | 1 | -| WAMR_BUILD_SIMD | A | ND | 1 | -| WAMR_BUILD_SIMDE | A | ND | 1 | -| WAMR_BUILD_SPEC_TEST | A | ND | | -| WAMR_BUILD_STACK_GUARD_SIZE | B | ND | | -| WAMR_BUILD_STATIC_PGO | B | ND | | -| WAMR_BUILD_STRINGREF | B | 0 | | -| WAMR_BUILD_TAIL_CALL | A | 0 | 1 | -| WAMR_BUILD_TARGET | - | ND | X86-64 | -| WAMR_BUILD_THREAD_MGR | A | ND | | -| WAMR_BUILD_WAMR_COMPILER | A | ND | | -| WAMR_BUILD_WASI_EPHEMERAL_NN | B | ND | | -| WAMR_BUILD_WASI_NN | B | ND | | -| WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE | B | ND | | -| WAMR_BUILD_WASI_NN_ENABLE_GPU | B | ND | | -| WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH | B | ND | | -| WAMR_BUILD_WASI_NN_LLAMACPP | B | ND | | -| WAMR_BUILD_WASI_NN_ONNX | B | ND | | -| WAMR_BUILD_WASI_NN_OPENVINO | B | ND | | -| WAMR_BUILD_WASI_NN_TFLITE | B | ND | | -| WAMR_BUILD_WASI_TEST | B | ND | | -| WAMR_BUILD_WASM_CACHE | B | ND | | -| WAMR_CONFIGURABLE_BOUNDS_CHECKS | C | ND | | -| WAMR_DISABLE_APP_ENTRY | A | ND | | -| WAMR_DISABLE_HW_BOUND_CHECK | A | ND | | -| WAMR_DISABLE_STACK_HW_BOUND_CHECK | A | ND | | -| WAMR_DISABLE_WAKEUP_BLOCKING_OP | B | ND | | -| WAMR_DISABLE_WRITE_GS_BASE | B | ND | | -| WAMR_TEST_GC | B | ND | | +| Description | Compilation Flags | Labels | +| -------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------ | +| Linux Compatibility | WAMR_BUILD_PLATFORM=linux | Portability | +| AoT runtime | [WAMR_BUILD_AOT](./build_wamr.md#configure-aot) | Running mode | +| Fast Interpreter | [WAMR_BUILD_FAST_INTERP](./build_wamr.md#configure-interpreters) | Running mode | +| Classic Interpreter | [WAMR_BUILD_INTERP](./build_wamr.md#configure-interpreters) | Running mode | +| AoT compilation (wamrc) | [WAMR_BUILD_WAMR_COMPILER](./build_wamr.md#configure-aot) | Compiler | +| Bulk Memory | [WAMR_BUILD_BULK_MEMORY](./build_wamr.md#bulk-memory-feature) | Wasm Proposal | +| Name section | [WAMR_BUILD_CUSTOM_NAME_SECTION](./build_wamr.md#name-section) | Wasm Proposal | +| Extended Constant Expressions | [WAMR_BUILD_EXTENDED_CONST_EXPR](./build_wamr.md#extended-constant-expression) | Wasm Proposal | +| Non-trapping float-to-int | ALWAYS ON. Can not be disabled | Wasm Proposal | +| Import/Export of Mutable Globals | ALWAYS ON. Can not be disabled | Wasm Proposal | +| Multi-value | ALWAYS ON. Can not be disabled | Wasm Proposal | +| WASI LIBC | [WAMR_BUILD_LIBC_WASI](./build_wamr.md#configure-libc) | Wasm Proposal | +| WASI threads | [WAMR_BUILD_LIB_WASI_THREADS](./build_wamr.md#lib-wasi-threads) | Wasm Proposal | +| Custom sections | [WAMR_BUILD_LOAD_CUSTOM_SECTION](./build_wamr.md#load-wasm-custom-sections) | Wasm Proposal | +| Memory64 | [WAMR_BUILD_MEMORY64](./build_wamr.md#memory64-feature) | Wasm Proposal | +| Reference Types | [WAMR_BUILD_REF_TYPES](./build_wamr.md#reference-types-feature) | Wasm Proposal | +| Threads | [WAMR_BUILD_SHARED_MEMORY](./build_wamr.md#shared-memory-feature) | Wasm Proposal | +| SIMD (128-bit) | [WAMR_BUILD_SIMD](./build_wamr.md#128-bit-simd-feature) | Wasm Proposal | +| AOT intrinsics | [WAMR_BUILD_AOT_INTRINSICS](./build_wamr.md#aot-intrinsics) | Runtime Extensions | +| AoT stack frame | [WAMR_BUILD_AOT_STACK_FRAME](./build_wamr.md#aot-stack-frame-feature) | Runtime Extensions | +| Global heap pool | [WAMR_BUILD_GLOBAL_HEAP_POOL](./build_wamr.md#a-pre-allocation-for-runtime-and-wasm-apps) | Runtime Extensions | +| Global heap size | [WAMR_BUILD_GLOBAL_HEAP_SIZE](./build_wamr.md#a-pre-allocation-for-runtime-and-wasm-apps) | Runtime Extensions | +| Libc builtin | [WAMR_BUILD_LIBC_BUILTIN](./build_wamr.md#configure-libc) | Runtime Extensions | +| Module instance context | [WAMR_BUILD_MODULE_INST_CONTEXT](./build_wamr.md#module-instance-context-apis) | Runtime Extensions | +| Quick AOT/JIT entries | [WAMR_BUILD_QUICK_AOT_ENTRY](./build_wamr.md#configure-aot) | Runtime Extensions | +| Shrunk memory | [WAMR_BUILD_SHRUNK_MEMORY](./build_wamr.md#shrunk-the-memory-usage) | Runtime Extensions | +| Thread manager | [WAMR_BUILD_THREAD_MGR](./build_wamr.md#thread-manager) | Runtime Extensions | +| App entry | [WAMR_DISABLE_APP_ENTRY](./build_wamr.md#exclude-wamr-application-entry-functions) | Runtime Extensions | +| hardware bound check | [WAMR_DISABLE_HW_BOUND_CHECK](./build_wamr.md#disable-boundary-check-with-hardware-trap) | Runtime Extensions | +| stack hardware bound check | [WAMR_DISABLE_STACK_HW_BOUND_CHECK](./build_wamr.md#disable-native-stack-boundary-check-with-hardware-trap) | Runtime Extensions | +| Wakeup blocking operation | [WAMR_DISABLE_WAKEUP_BLOCKING_OP](./build_wamr.md#disable-async-wakeup-of-blocking-operation) | Runtime Extensions | -[^1]: _ND_ represents _not defined_ -[^2]: active if `WAMR_BUILD_AOT` is 1 -[^3]: active if `WAMR_BUILD_FAST_JIT` or `WAMR_BUILD_JIT1` is 1 -[^4]: active if `WAMR_BUILD_AOT` or `WAMR_BUILD_JIT` is 1 +# TierB + +## Targets + +| Description | +| ---------------------- | +| arc-unknown-none-elf | +| x86_64-pc-windows-msvc | +| mips-unknown-elf | +| mips64-unknown-elf | + +## Features + +| Description | Compilation Flags | Labels | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------ | +| Darwin Compatibility | WAMR_BUILD_PLATFORM=darwin | Portability | +| ESP-IDF Compatibility | WAMR_BUILD_PALTFORM=esp-idf | Portability | +| Nuttx Compatibility | WAMR_BUILD_PALTFORM=nuttx | Portability | +| SGX Compatibility | WAMR_BUILD_PALTFORM=linux-sgx | Portability | +| Zephyr Compatibility | WAMR_BUILD_PALTFORM=zephyr | Portability | +| Stringref | [WAMR_BUILD_STRINGREF](./build_wamr.md#garbage-collection) | Wasm Proposal | +| Tail Calls | [WAMR_BUILD_TAIL_CALL](./build_wamr.md#tail-call-feature) | Wasm Proposal | +| LLVM JIT | [WAMR_BUILD_JIT](./build_wamr.md#configure-llvm-jit) | Running mode | +| Per Instance running mode | ALWAYS ON. Can not be disabled | Runtime Extensions | +| Maximum stack size for app threads | [WAMR_APP_THREAD_STACK_SIZE_MAX](./build_wamr.md#set-maximum-app-thread-stack-size) | Runtime Extensions | +| Host defined logging | [WAMR_BH_LOG](./build_wamr.md#host-defined-log) | Runtime Extensions | +| Host defined vprintf | [WAMR_BH_vprintf](./build_wamr.md#host-defined-vprintf) | Runtime Extensions | +| Allocation with usage tracking | [WAMR_BUILD_ALLOC_WITH_USAGE](./build_wamr.md#user-defined-linear-memory-allocator) | Runtime Extensions | +| Allocation with user data | [WAMR_BUILD_ALLOC_WITH_USER_DATA](./build_wamr.md#user-defined-linear-memory-allocator) | Runtime Extensions | +| Bulk-memory-opt | [WAMR_BUILD_BULK_MEMORY_OPT](./build_wamr.md#bulk-memory-opt) | Runtime Extensions | +| Call-indirect-overlong | [WAMR_BUILD_CALL_INDIRECT_OVERLONG](./build_wamr.md#call-indirect-overlong) | Runtime Extensions | +| Copy Call Stack | [WAMR_BUILD_COPY_CALL_STACK](./build_wamr.md#copy-call-stack) | Runtime Extensions | +| Debug Interpreter | [WAMR_BUILD_DEBUG_INTERP](./build_wamr.md#configure-debug) | Runtime Extensions | +| Dump call stack | [WAMR_BUILD_DUMP_CALL_STACK](./build_wamr.md#dump-call-stack-feature) | Runtime Extensions | +| Native General Invocation | [WAMR_BUILD_INVOKE_NATIVE_GENERAL](./build_wamr.md#invoke-general-ffi) | Runtime Extensions | +| Lazy JIT Compilation | [WAMR_BUILD_LAZY_JIT](./build_wamr.md#configure-llvm-jit) | Runtime Extensions | +| Pthread | [WAMR_BUILD_LIB_PTHREAD](./build_wamr.md#lib-pthread) | Runtime Extensions | +| Pthread Semaphore Support | [WAMR_BUILD_LIB_PTHREAD_SEMAPHORE](./build_wamr.md#lib-pthread-semaphore) | Runtime Extensions | +| Lime1 runtime | [WAMR_BUILD_LIME1](./build_wamr.md#lime1-target) | Runtime Extensions | +| Linux Performance Counters | [WAMR_BUILD_LINUX_PERF](./build_wamr.md#linux-perf-support) | Runtime Extensions | +| Memory profiling | [WAMR_BUILD_MEMORY_PROFILING](./build_wamr.md#memory-profiling-experiment) | Runtime Extensions | +| Multi-module | [WAMR_BUILD_MULTI_MODULE](./build_wamr.md#multi-module-feature) | Runtime Extensions | +| Perf profiling | [WAMR_BUILD_PERF_PROFILING](./build_wamr.md#performance-profiling-experiment) | Runtime Extensions | +| Shared heap | [WAMR_BUILD_SHARED_HEAP](./build_wamr.md#shared-heap-among-wasm-apps-and-host-native) | Runtime Extensions | +| Stack Guard Size | [WAMR_BUILD_STACK_GUARD_SIZE](./build_wamr.md#stack-guard-size) | Runtime Extensions | +| WASI Ephemeral NN | [WAMR_BUILD_WASI_EPHEMERAL_NN](./build_wamr.md#lib-wasi-nn-with-wasi_ephemeral_nn-module-support) | Runtime Extensions | +| WASI-NN (neural network APIs) | [WAMR_BUILD_WASI_NN](./build_wamr.md#lib-wasi-nn) | Runtime Extensions | +| External Delegate for WASI NN | [WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE](./build_wamr.md#lib-wasi-nn-external-delegate-mode) | Runtime Extensions | +| GPU Support for WASI NN | [WAMR_BUILD_WASI_NN_ENABLE_GPU](./build_wamr.md#lib-wasi-nn-gpu-mode) | Runtime Extensions | +| External Delegate Path for WASI NN | [WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH](./build_wamr.md#lib-wasi-nn-external-delegate-mode) | Runtime Extensions | +| LLAMA CPP for WASI NN | [WAMR_BUILD_WASI_NN_LLAMACPP](./build_wamr.md#lib-wasi-nn) | Runtime Extensions | +| ONNX for WASI NN | [WAMR_BUILD_WASI_NN_ONNX](./build_wamr.md#lib-wasi-nn) | Runtime Extensions | +| OpenVINO for WASI NN | [WAMR_BUILD_WASI_NN_OPENVINO](./build_wamr.md#lib-wasi-nn) | Runtime Extensions | +| TFLite for WASI NN | [WAMR_BUILD_WASI_NN_TFLITE](./build_wamr.md#lib-wasi-nn) | Runtime Extensions | +| Configurable bounds checks | [WAMR_CONFIGURABLE_BOUNDS_CHECKS](./build_wamr.md#configurable-memory-access-boundary-check) | Runtime Extensions | +| Write GS base | [WAMR_DISABLE_WRITE_GS_BASE](./build_wamr.md#disable-writing-the-linear-memory-base-address-to-x86-gs-segment-register) | Runtime Extensions | + +# TierC + +## Targets + +| Description | +| ---------------------- | +| aarch64-apple-ios | +| arm-none-eabi | +| i386-unknown-elf | +| i386-wrs-vxworks | +| riscv32-esp-elf | +| riscv32-unknown-elf | +| riscv64-unknown-elf | +| x86_64-linux-android | +| x86_64-linux-cosmo | +| x86_64-unknown-freebsd | +| x86_64-wrs-vxworks | +| xtensa-esp32-elf | + +## Features + +| Description | Compilation Flags | Labels | +| ------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------------ | +| AliOS compatibility | WAMR_BUILD_PLATFORM=alios-things | Portability | +| Android Compatibility | WAMR_BUILD_PLATFORM=android | Portability | +| Cosmo Compatibility | WAMR_BUILD_PLATFORM=cosmopolitan | Portability | +| FreeBSD Compatibility | WAMR_BUILD_PLATFORM=freebsd | Portability | +| iOS Compatibility | WAMR_BUILD_PLATFORM=darwin | Portability | +| RIOT OS Compatibility | WAMR_BUILD_PLATFORM=riot | Portability | +| RT-Thread Compatibility | WAMR_BUILD_PLATFORM=rt-thread | Portability | +| VxWorks Compatibility | WAMR_BUILD_PLATFORM=vxworks | Portability | +| Windows Compatibility | WAMR_BUILD_PLATFORM=windows | Portability | +| GC (Garbage Collection) | [WAMR_BUILD_GC](./build_wamr.md#garbage-collection) | Wasm Proposal | +| Legacy Exception Handling | [WAMR_BUILD_EXCE_HANDLING](./build_wamr.md#exception-handling) | Wasm Proposal | +| Multi-memory | [WAMR_BUILD_MULTI_MEMORY](./build_wamr.md#multi-memory) | Wasm Proposal | +| Branch Hints | [WAMR_BUILD_BRANCH_HINTS](./build_wamr.md#branch-hints-feature) | Wasm Proposal | +| Fast JIT | [WAMR_BUILD_FAST_JIT](./build_wamr.md#configure-fast-jit) | Running mode | +| Multi-tier JIT | [Combination of flags](./build_wamr.md#configure-multi-tier-jit) | Running mode | +| AoT Validator | [WAMR_BUILD_AOT_VALIDATOR](./build_wamr.md#aot-validator) | Runtime Extensions | +| Debug AOT | [WAMR_BUILD_DEBUG_AOT](./build_wamr.md#configure-debug) | Runtime Extensions | +| Dynamic AoT debugging | [WAMR_BUILD_DYNAMIC_AOT_DEBUG](./build_wamr.md#configure-debug) | Runtime Extensions | +| Fast JIT Dump | [WAMR_BUILD_FAST_JIT_DUMP](./build_wamr.md#configure-fast-jit) | Runtime Extensions | +| Garbage Collection Heap Verify | [WAMR_BUILD_GC_HEAP_VERIFY](./build_wamr.md#garbage-collection) | Runtime Extensions | +| Instruction Metering | [WAMR_BUILD_INSTRUCTION_METERING](./build_wamr.md#instruction-metering) | Runtime Extensions | +| Libc EMCC Compatibility | [WAMR_BUILD_LIBC_EMCC](./build_wamr.md#libc-emcc) | Runtime Extensions | +| Libc UVWASI Compatibility | [WAMR_BUILD_LIBC_UVWASI](./build_wamr.md#libc-uvwasi) | Runtime Extensions | +| RATS Library | [WAMR_BUILD_LIB_RATS](./build_wamr.md#librats) | Runtime Extensions | +| Mini Loader | [WAMR_BUILD_MINI_LOADER](./build_wamr.md#wasm-mini-loader) | Runtime Extensions | +| SGX IPFS Support | [WAMR_BUILD_SGX_IPFS](./build_wamr.md#intel-protected-file-system) | Runtime Extensions | +| Static PGO | [WAMR_BUILD_STATIC_PGO](./build_wamr.md#running-pgoprofile-guided-optimization-instrumented-aot-file) | Runtime Extensions | +| WASM cache | [WAMR_BUILD_WASM_CACHE](./build_wamr.md#wasm-cache) | Runtime Extensions | +| Test garbage collection | [WAMR_TEST_GC](./build_wamr.md#test-garbage-collection) | Runtime Extensions | diff --git a/gitbook/tutorial/README.md b/gitbook/tutorial/README.md index 85b63677f..7d76c83ed 100644 --- a/gitbook/tutorial/README.md +++ b/gitbook/tutorial/README.md @@ -1,6 +1,6 @@ # Tutorial -In this chapter, we want to walk you through the basic development knowledge and skills of WARM you may need so that you are ready to write your wasm application with WARM. +In this chapter, we want to walk you through the basic development knowledge and skills of WAMR you may need so that you are ready to write your wasm application with WAMR. For starters, you could learn how to compile different running mode of WAMR and their usage in [this section](build-tutorial/README.md). diff --git a/language-bindings/go/build.sh b/language-bindings/go/build.sh index fe46a9a83..c6736ed87 100755 --- a/language-bindings/go/build.sh +++ b/language-bindings/go/build.sh @@ -21,7 +21,7 @@ cmake ${WAMR_DIR}/product-mini/platforms/${PLATFORM} \ -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \ -DWAMR_BUILD_MEMORY_PROFILING=1 make -j ${nproc} -cp -a libvmlib.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-${ARCH} +cp -a libiwasm.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-${ARCH} cd ${WAMR_GO_DIR} go test diff --git a/language-bindings/go/go.mod b/language-bindings/go/go.mod index b7e428654..3425bcb27 100644 --- a/language-bindings/go/go.mod +++ b/language-bindings/go/go.mod @@ -2,4 +2,4 @@ module github.com/bytecodealliance/wasm-micro-runtime/language-bindings/go go 1.15 -require github.com/stretchr/testify v1.7.0 +require github.com/stretchr/testify v1.11.1 diff --git a/language-bindings/go/go.sum b/language-bindings/go/go.sum index acb88a48f..1cd876dc1 100644 --- a/language-bindings/go/go.sum +++ b/language-bindings/go/go.sum @@ -1,11 +1,19 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/language-bindings/go/wamr/cgo.go b/language-bindings/go/wamr/cgo.go index 74766c301..cac3bcbcc 100644 --- a/language-bindings/go/wamr/cgo.go +++ b/language-bindings/go/wamr/cgo.go @@ -6,7 +6,7 @@ package wamr // #cgo CFLAGS: -I${SRCDIR}/packaged/include -// #cgo LDFLAGS: -lvmlib -lm +// #cgo LDFLAGS: -liwasm -lm // // #cgo linux,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/linux-amd64 -L${SRCDIR}/packaged/lib/linux-amd64 // #cgo linux,arm64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/linux-aarch64 -L${SRCDIR}/packaged/lib/linux-aarch64 diff --git a/product-mini/platforms/android/CMakeLists.txt b/product-mini/platforms/android/CMakeLists.txt index 9cc8cc6b9..7c4671331 100644 --- a/product-mini/platforms/android/CMakeLists.txt +++ b/product-mini/platforms/android/CMakeLists.txt @@ -111,12 +111,6 @@ set_version_info (vmlib) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE") -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () -endif () - # The following flags are to enhance security, but it may impact performance, # we disable them by default. #if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") diff --git a/product-mini/platforms/cosmopolitan/CMakeLists.txt b/product-mini/platforms/cosmopolitan/CMakeLists.txt index 37641497a..6b834369e 100644 --- a/product-mini/platforms/cosmopolitan/CMakeLists.txt +++ b/product-mini/platforms/cosmopolitan/CMakeLists.txt @@ -136,14 +136,6 @@ set_version_info (vmlib) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mindirect-branch-register") - # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub - endif () -endif () - # The following flags are to enhance security, but it may impact performance, # we disable them by default. #if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") diff --git a/product-mini/platforms/ios/CMakeLists.txt b/product-mini/platforms/ios/CMakeLists.txt index bc8542ffe..80c618e8d 100644 --- a/product-mini/platforms/ios/CMakeLists.txt +++ b/product-mini/platforms/ios/CMakeLists.txt @@ -113,12 +113,6 @@ include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE") -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () -endif () - # The following flags are to enhance security, but it may impact performance, # we disable them by default. #if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.config.xml b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.config.xml index cb08e3479..ea3a63f8f 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.config.xml +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.config.xml @@ -8,7 +8,8 @@ 1 10 1 - 0 + + 1 0 0xFFFFFFFF diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp index 91f03a979..dc3b6c3a2 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -81,6 +81,171 @@ static EnclaveModule *enclave_module_list = NULL; static korp_mutex enclave_module_list_lock = OS_THREAD_MUTEX_INITIALIZER; #endif +/* Handle table for secure EnclaveModule reference management */ +#define MAX_MODULES 128 +typedef struct HandleTableEntry { + uint32 id; + EnclaveModule *module_ref; + bool in_use; +} HandleTableEntry; + +static HandleTableEntry module_table[MAX_MODULES] = { 0 }; +static uint32 next_module_id = 1; +static korp_mutex module_table_lock = OS_THREAD_MUTEX_INITIALIZER; + +/* : Allocate secure handle for EnclaveModule, preventing pointer + * exposure */ +static uint32 +allocate_module_handle(EnclaveModule *module) +{ + uint32 handle_id = 0; + + os_mutex_lock(&module_table_lock); + + /* Find free slot */ + for (uint32 i = 0; i < MAX_MODULES; i++) { + if (!module_table[i].in_use) { + module_table[i].id = next_module_id++; + module_table[i].module_ref = module; + module_table[i].in_use = true; + handle_id = module_table[i].id; + break; + } + } + + os_mutex_unlock(&module_table_lock); + + if (handle_id == 0) { + int bytes_written = 0; + ocall_print(&bytes_written, + "SECURITY WARNING: Module handle table full\n"); + } + + return handle_id; +} + +/* Lookup EnclaveModule by handle ID, preventing direct pointer access */ +static EnclaveModule * +lookup_module_by_handle(uint32 handle_id) +{ + EnclaveModule *module = NULL; + + if (handle_id == 0) + return NULL; + + os_mutex_lock(&module_table_lock); + + for (uint32 i = 0; i < MAX_MODULES; i++) { + if (module_table[i].in_use && module_table[i].id == handle_id) { + module = module_table[i].module_ref; + break; + } + } + + os_mutex_unlock(&module_table_lock); + + return module; +} + +static void +release_module_handle(uint32 handle_id) +{ + os_mutex_lock(&module_table_lock); + + for (uint32 i = 0; i < MAX_MODULES; i++) { + if (module_table[i].in_use && module_table[i].id == handle_id) { + module_table[i].id = 0; + module_table[i].module_ref = NULL; + module_table[i].in_use = false; + break; + } + } + + os_mutex_unlock(&module_table_lock); +} + +/* Handle table for secure wasm_module_inst_t reference management */ +#define MAX_INSTANCES 128 +typedef struct InstanceTableEntry { + uint32 id; + wasm_module_inst_t inst_ref; + bool in_use; +} InstanceTableEntry; + +static InstanceTableEntry instance_table[MAX_INSTANCES] = { 0 }; +static uint32 next_instance_id = 1; +static korp_mutex instance_table_lock = OS_THREAD_MUTEX_INITIALIZER; + +/*Allocate secure handle for wasm_module_inst_t, preventing pointer exposure */ +static uint32 +allocate_instance_handle(wasm_module_inst_t inst) +{ + uint32 handle_id = 0; + + os_mutex_lock(&instance_table_lock); + + for (uint32 i = 0; i < MAX_INSTANCES; i++) { + if (!instance_table[i].in_use) { + instance_table[i].id = next_instance_id++; + instance_table[i].inst_ref = inst; + instance_table[i].in_use = true; + handle_id = instance_table[i].id; + break; + } + } + + os_mutex_unlock(&instance_table_lock); + + if (handle_id == 0) { + int bytes_written = 0; + ocall_print(&bytes_written, + "SECURITY WARNING: Instance handle table full\n"); + } + + return handle_id; +} + +/* SECURITY: Lookup wasm_module_inst_t by handle ID, preventing direct pointer + * access */ +static wasm_module_inst_t +lookup_instance_by_handle(uint32 handle_id) +{ + wasm_module_inst_t inst = NULL; + + if (handle_id == 0) + return NULL; + + os_mutex_lock(&instance_table_lock); + + for (uint32 i = 0; i < MAX_INSTANCES; i++) { + if (instance_table[i].in_use && instance_table[i].id == handle_id) { + inst = instance_table[i].inst_ref; + break; + } + } + + os_mutex_unlock(&instance_table_lock); + + return inst; +} + +static void +release_instance_handle(uint32 handle_id) +{ + os_mutex_lock(&instance_table_lock); + + for (uint32 i = 0; i < MAX_INSTANCES; i++) { + if (instance_table[i].in_use && instance_table[i].id == handle_id) { + instance_table[i].id = 0; + instance_table[i].inst_ref = NULL; + instance_table[i].in_use = false; + break; + } + } + + os_mutex_unlock(&instance_table_lock); +} + #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE] = { 0 }; #endif @@ -277,7 +442,17 @@ handle_cmd_load_module(uint64 *args, uint32 argc) return; } - *(EnclaveModule **)args_org = enclave_module; + uint32 enclave_module_id = allocate_module_handle(enclave_module); + if (enclave_module_id == 0) { + /* Handle table full - cleanup and return error */ + if (!enclave_module->is_xip_file) + wasm_runtime_free(enclave_module); + else + os_munmap(enclave_module, (uint32)total_size); + *(void **)args_org = NULL; + return; + } + *(uint32 *)args_org = enclave_module_id; #if WASM_ENABLE_LIB_RATS != 0 /* Calculate the module hash */ @@ -299,7 +474,8 @@ handle_cmd_load_module(uint64 *args, uint32 argc) static void handle_cmd_unload_module(uint64 *args, uint32 argc) { - EnclaveModule *enclave_module = *(EnclaveModule **)args++; + uint32 module_handle_id = *(uint32 *)args++; + EnclaveModule *enclave_module = lookup_module_by_handle(module_handle_id); bh_assert(argc == 1); @@ -328,6 +504,9 @@ handle_cmd_unload_module(uint64 *args, uint32 argc) os_mutex_unlock(&enclave_module_list_lock); #endif + /* Release module handle */ + release_module_handle(module_handle_id); + /* Destroy enclave module resources */ if (enclave_module->wasi_arg_buf) wasm_runtime_free(enclave_module->wasi_arg_buf); @@ -368,7 +547,8 @@ static void handle_cmd_instantiate_module(uint64 *args, uint32 argc) { uint64 *args_org = args; - EnclaveModule *enclave_module = *(EnclaveModule **)args++; + uint32 module_handle_id = *(uint32 *)args++; + EnclaveModule *enclave_module = lookup_module_by_handle(module_handle_id); uint32 stack_size = *(uint32 *)args++; uint32 heap_size = *(uint32 *)args++; char *error_buf = *(char **)args++; @@ -377,7 +557,7 @@ handle_cmd_instantiate_module(uint64 *args, uint32 argc) bh_assert(argc == 5); - if (!runtime_inited) { + if (!runtime_inited || !enclave_module) { *(void **)args_org = NULL; return; } @@ -389,7 +569,13 @@ handle_cmd_instantiate_module(uint64 *args, uint32 argc) return; } - *(wasm_module_inst_t *)args_org = module_inst; + uint32 instance_id = allocate_instance_handle(module_inst); + if (instance_id == 0) { + wasm_runtime_deinstantiate(module_inst); + *(void **)args_org = NULL; + return; + } + *(uint32 *)args_org = instance_id; LOG_VERBOSE("Instantiate module success.\n"); } @@ -397,7 +583,9 @@ handle_cmd_instantiate_module(uint64 *args, uint32 argc) static void handle_cmd_deinstantiate_module(uint64 *args, uint32 argc) { - wasm_module_inst_t module_inst = *(wasm_module_inst_t *)args++; + uint32 instance_handle_id = *(uint32 *)args++; + wasm_module_inst_t module_inst = + lookup_instance_by_handle(instance_handle_id); bh_assert(argc == 1); @@ -407,6 +595,8 @@ handle_cmd_deinstantiate_module(uint64 *args, uint32 argc) wasm_runtime_deinstantiate(module_inst); + release_instance_handle(instance_handle_id); + LOG_VERBOSE("Deinstantiate module success.\n"); } @@ -414,7 +604,9 @@ static void handle_cmd_get_exception(uint64 *args, uint32 argc) { uint64 *args_org = args; - wasm_module_inst_t module_inst = *(wasm_module_inst_t *)args++; + uint32 instance_handle_id = *(uint32 *)args++; + wasm_module_inst_t module_inst = + lookup_instance_by_handle(instance_handle_id); char *exception = *(char **)args++; uint32 exception_size = *(uint32 *)args++; const char *exception1; @@ -438,7 +630,9 @@ handle_cmd_get_exception(uint64 *args, uint32 argc) static void handle_cmd_exec_app_main(uint64 *args, int32 argc) { - wasm_module_inst_t module_inst = *(wasm_module_inst_t *)args++; + uint32 instance_handle_id = *(uint32 *)args++; + wasm_module_inst_t module_inst = + lookup_instance_by_handle(instance_handle_id); uint32 app_argc = *(uint32 *)args++; char **app_argv = NULL; uint64 total_size; @@ -471,7 +665,9 @@ handle_cmd_exec_app_main(uint64 *args, int32 argc) static void handle_cmd_exec_app_func(uint64 *args, int32 argc) { - wasm_module_inst_t module_inst = *(wasm_module_inst_t *)args++; + uint32 instance_handle_id = *(uint32 *)args++; + wasm_module_inst_t module_inst = + lookup_instance_by_handle(instance_handle_id); char *func_name = *(char **)args++; uint32 app_argc = *(uint32 *)args++; char **app_argv = NULL; @@ -515,7 +711,8 @@ static void handle_cmd_set_wasi_args(uint64 *args, int32 argc) { uint64 *args_org = args; - EnclaveModule *enclave_module = *(EnclaveModule **)args++; + uint32 module_handle_id = *(uint32 *)args++; + EnclaveModule *enclave_module = lookup_module_by_handle(module_handle_id); char **dir_list = *(char ***)args++; uint32 dir_list_size = *(uint32 *)args++; char **env_list = *(char ***)args++; @@ -533,7 +730,48 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) bh_assert(argc == 10); - if (!runtime_inited) { + if (!runtime_inited || !enclave_module) { + *args_org = false; + return; + } + + /* Validate all pointer arrays before use */ + if (dir_list_size > 0 + && (!dir_list + || !sgx_is_outside_enclave(dir_list, + sizeof(char *) * dir_list_size))) { + int bytes_written = 0; + ocall_print(&bytes_written, "SECURITY ERROR: Invalid dir_list\n"); + *args_org = false; + return; + } + + if (env_list_size > 0 + && (!env_list + || !sgx_is_outside_enclave(env_list, + sizeof(char *) * env_list_size))) { + int bytes_written = 0; + ocall_print(&bytes_written, "SECURITY ERROR: Invalid env_list\n"); + *args_org = false; + return; + } + + if (wasi_argc > 0 + && (!wasi_argv + || !sgx_is_outside_enclave(wasi_argv, + sizeof(char *) * wasi_argc))) { + int bytes_written = 0; + ocall_print(&bytes_written, "SECURITY ERROR: Invalid wasi_argv\n"); + *args_org = false; + return; + } + + if (addr_pool_list_size > 0 + && (!addr_pool_list + || !sgx_is_outside_enclave(addr_pool_list, + sizeof(char *) * addr_pool_list_size))) { + int bytes_written = 0; + ocall_print(&bytes_written, "SECURITY ERROR: Invalid addr_pool_list\n"); *args_org = false; return; } @@ -695,9 +933,38 @@ void ecall_handle_command(unsigned cmd, unsigned char *cmd_buf, unsigned cmd_buf_size) { + /* + * Validate buffer before processing + * cmd_buf can be NULL if cmd_buf_size is 0, but if cmd_buf_size is + * non-zero, cmd_buf must be valid + */ + if ((!cmd_buf && cmd_buf_size > 0) || (cmd_buf && cmd_buf_size == 0)) { + int bytes_written = 0; + ocall_print(&bytes_written, + "SECURITY ERROR: Invalid buffer parameters\n"); + return; + } + + // Because of [in, out] cmd_buf in edl, it is allocated inside enclave. + if (cmd_buf && sgx_is_outside_enclave(cmd_buf, cmd_buf_size)) { + int bytes_written = 0; + ocall_print(&bytes_written, + "SECURITY ERROR: Buffer should be inside enclave\n"); + return; + } + + if (cmd_buf_size % sizeof(uint64) != 0) { + int bytes_written = 0; + ocall_print(&bytes_written, + "SECURITY ERROR: Buffer alignment invalid\n"); + return; + } + uint64 *args = (uint64 *)cmd_buf; uint32 argc = cmd_buf_size / sizeof(uint64); + LOG_VERBOSE("Received command %d with %u arguments.\n", cmd, argc); + switch (cmd) { case CMD_INIT_RUNTIME: handle_cmd_init_runtime(args, argc); diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.edl b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.edl index 0de4c6404..5fe69a8d3 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.edl +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.edl @@ -18,6 +18,7 @@ enclave { from "sgx_tprotected_fs.edl" import *; #endif + //TODO: replace void with an int as error code trusted { /* define ECALLs here. */ public void ecall_handle_command(unsigned cmd, diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index e369197dc..a0c0675d5 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -139,14 +139,6 @@ check_pie_supported() set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mindirect-branch-register") - # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub - endif () -endif () - # The following flags are to enhance security, but it may impact performance, # we disable them by default. #if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") diff --git a/product-mini/platforms/windows/CMakeLists.txt b/product-mini/platforms/windows/CMakeLists.txt index 39b373deb..326c2cf6c 100644 --- a/product-mini/platforms/windows/CMakeLists.txt +++ b/product-mini/platforms/windows/CMakeLists.txt @@ -114,12 +114,6 @@ if (NOT MINGW) set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") endif () -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang" OR MSVC)) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () -endif () - # The following flags are to enhance security, but it may impact performance, # we disable them by default. #if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") diff --git a/samples/basic/CMakeLists.txt b/samples/basic/CMakeLists.txt index e7417e634..244ed81c1 100644 --- a/samples/basic/CMakeLists.txt +++ b/samples/basic/CMakeLists.txt @@ -60,11 +60,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () # build out vmlib diff --git a/samples/file/src/CMakeLists.txt b/samples/file/src/CMakeLists.txt index d54e93c08..11cbd5ac1 100644 --- a/samples/file/src/CMakeLists.txt +++ b/samples/file/src/CMakeLists.txt @@ -61,11 +61,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () # build out vmlib diff --git a/samples/import-func-callback/CMakeLists.txt b/samples/import-func-callback/CMakeLists.txt index be0cc5032..64a4ddc7b 100644 --- a/samples/import-func-callback/CMakeLists.txt +++ b/samples/import-func-callback/CMakeLists.txt @@ -53,11 +53,6 @@ if (NOT MSVC) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () # build out vmlib diff --git a/samples/inst-context-threads/CMakeLists.txt b/samples/inst-context-threads/CMakeLists.txt index b32d3053b..6d4b1e856 100644 --- a/samples/inst-context-threads/CMakeLists.txt +++ b/samples/inst-context-threads/CMakeLists.txt @@ -61,11 +61,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () # build out vmlib diff --git a/samples/inst-context/CMakeLists.txt b/samples/inst-context/CMakeLists.txt index b9866a5eb..91584ad9c 100644 --- a/samples/inst-context/CMakeLists.txt +++ b/samples/inst-context/CMakeLists.txt @@ -60,11 +60,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () # build out vmlib diff --git a/samples/multi-module/CMakeLists.txt b/samples/multi-module/CMakeLists.txt index 7d0499e4c..c823e517b 100644 --- a/samples/multi-module/CMakeLists.txt +++ b/samples/multi-module/CMakeLists.txt @@ -65,11 +65,6 @@ set(WAMR_BUILD_MULTI_MODULE 1) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () -endif () # build out vmlib set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) diff --git a/samples/native-stack-overflow/CMakeLists.txt b/samples/native-stack-overflow/CMakeLists.txt index a2079bf4f..48ffd4f5b 100644 --- a/samples/native-stack-overflow/CMakeLists.txt +++ b/samples/native-stack-overflow/CMakeLists.txt @@ -60,11 +60,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () if (CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 13.0.0) diff --git a/samples/ref-types/CMakeLists.txt b/samples/ref-types/CMakeLists.txt index 0d0852a2e..13807444d 100644 --- a/samples/ref-types/CMakeLists.txt +++ b/samples/ref-types/CMakeLists.txt @@ -74,11 +74,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif() # build out vmlib set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) diff --git a/samples/shared-heap/CMakeLists.txt b/samples/shared-heap/CMakeLists.txt index 94690a4ed..89e79a5b3 100644 --- a/samples/shared-heap/CMakeLists.txt +++ b/samples/shared-heap/CMakeLists.txt @@ -61,11 +61,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () # build out vmlib diff --git a/samples/shared-module/CMakeLists.txt b/samples/shared-module/CMakeLists.txt index 4c9201e51..552aa9315 100644 --- a/samples/shared-module/CMakeLists.txt +++ b/samples/shared-module/CMakeLists.txt @@ -65,11 +65,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () # build out vmlib diff --git a/samples/terminate/CMakeLists.txt b/samples/terminate/CMakeLists.txt index 380733258..80b8fb688 100644 --- a/samples/terminate/CMakeLists.txt +++ b/samples/terminate/CMakeLists.txt @@ -68,11 +68,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif () # build out vmlib diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index 15eafaf4b..fb95a0628 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -89,11 +89,6 @@ if (NOT MSVC) if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () - if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () - endif () endif() # build out vmlib set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) diff --git a/test-tools/aot-analyzer/CMakeLists.txt b/test-tools/aot-analyzer/CMakeLists.txt index 04d3b636c..9c317a6e6 100644 --- a/test-tools/aot-analyzer/CMakeLists.txt +++ b/test-tools/aot-analyzer/CMakeLists.txt @@ -61,12 +61,6 @@ if (NOT DEFINED WAMR_BIG_ENDIAN) set (WAMR_BIG_ENDIAN 0) endif () -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () -endif () - # build out vmlib set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) diff --git a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt index 500ad8fe3..28ffd0fea 100644 --- a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt @@ -78,7 +78,7 @@ find_package(LLVM REQUIRED CONFIG) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) add_definitions(${LLVM_DEFINITIONS_LIST}) @@ -172,21 +172,19 @@ set(IWASM_DIR ${REPO_ROOT_DIR}/core/iwasm) # Global setting add_compile_options(-Wno-unused-command-line-argument) -# Enable fuzzer -add_definitions(-DWASM_ENABLE_FUZZ_TEST=1) -# '-fsanitize=vptr' not allowed with '-fno-rtti -# But, LLVM by default, disables the use of `rtti` in the compiler -add_compile_options(-fsanitize=fuzzer -fno-sanitize=vptr) -add_link_options(-fsanitize=fuzzer -fno-sanitize=vptr) - # Enable sanitizers if not in oss-fuzz environment set(CFLAGS_ENV $ENV{CFLAGS}) -string(FIND "${CFLAGS_ENV}" "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" FUZZ_POS) + string(FIND "${CFLAGS_ENV}" "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" FUZZ_POS) if (FUZZ_POS GREATER -1) set(IN_OSS_FUZZ 1) else() set(IN_OSS_FUZZ 0) endif() +# Enable fuzzer +add_definitions(-DWASM_ENABLE_FUZZ_TEST=1) + +include(${CMAKE_CURRENT_LIST_DIR}/sanitizer_flags.cmake) + add_subdirectory(aot-compiler) add_subdirectory(wasm-mutator) diff --git a/tests/fuzz/wasm-mutator-fuzz/aot-compiler/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/aot-compiler/CMakeLists.txt index 5ca33906a..120902daf 100644 --- a/tests/fuzz/wasm-mutator-fuzz/aot-compiler/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/aot-compiler/CMakeLists.txt @@ -1,12 +1,6 @@ # Copyright (C) 2025 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# Set default build options with the ability to override from the command line -if(NOT WAMR_BUILD_INTERP) - set(WAMR_BUILD_INTERP 1) -endif() - -set(WAMR_BUILD_WAMR_COMPILER 1) set(WAMR_BUILD_AOT 0) set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_JIT 0) @@ -67,17 +61,6 @@ target_link_directories(aotclib PUBLIC ${LLVM_LIBRARY_DIR}) target_link_libraries(aotclib PUBLIC ${REQUIRED_LLVM_LIBS}) -if(NOT IN_OSS_FUZZ) - message(STATUS "Enable ASan and UBSan in non-oss-fuzz environment for aotclib") - target_compile_options(aotclib PUBLIC - -fprofile-instr-generate -fcoverage-mapping - -fno-sanitize-recover=all - -fsanitize=address,undefined - -fsanitize=float-divide-by-zero,unsigned-integer-overflow,local-bounds,nullability - -fno-sanitize=alignment - ) - target_link_options(aotclib PUBLIC -fsanitize=address,undefined -fprofile-instr-generate) -endif() - -add_executable(aot_compiler_fuzz aot_compiler_fuzz.cc) +add_executable(aot_compiler_fuzz aot_compiler_fuzz.cc ../common/fuzzer_common.cc) +target_include_directories(aot_compiler_fuzz PRIVATE ../common) target_link_libraries(aot_compiler_fuzz PRIVATE stdc++ aotclib) diff --git a/tests/fuzz/wasm-mutator-fuzz/aot-compiler/aot_compiler_fuzz.cc b/tests/fuzz/wasm-mutator-fuzz/aot-compiler/aot_compiler_fuzz.cc index c8ec4c0d5..49f275b18 100644 --- a/tests/fuzz/wasm-mutator-fuzz/aot-compiler/aot_compiler_fuzz.cc +++ b/tests/fuzz/wasm-mutator-fuzz/aot-compiler/aot_compiler_fuzz.cc @@ -11,6 +11,7 @@ #include "aot_export.h" #include "wasm_export.h" #include "bh_read_file.h" +#include "../common/fuzzer_common.h" static void handle_aot_recent_error(const char *tag) @@ -26,32 +27,41 @@ handle_aot_recent_error(const char *tag) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + char kTargetArch[] = "x86_64"; + char kTargetAbi[] = "gnu"; wasm_module_t module = NULL; - char error_buf[128] = { 0 }; + char error_buf[ERROR_BUF_SIZE] = { 0 }; AOTCompOption option = { 0 }; aot_comp_data_t comp_data = NULL; aot_comp_context_t comp_ctx = NULL; + uint8 *aot_file_buf = NULL; + uint32 aot_file_size = 0; + wasm_module_t aot_module = NULL; + wasm_module_inst_t inst = NULL; - /* libfuzzer don't allow to modify the given Data, so make a copy here */ - std::vector myData(Data, Data + Size); + /* wasm_runtime_load may modify the input buffer in-place, + * so we must work on a copy to avoid overwriting libFuzzer's const input */ + std::vector data_copy(Data, Data + Size); if (Size >= 4 - && get_package_type(myData.data(), Size) != Wasm_Module_Bytecode) { + && get_package_type(data_copy.data(), Size) + != Wasm_Module_Bytecode) { printf("Invalid wasm file: magic header not detected\n"); return 0; } wasm_runtime_init(); - module = wasm_runtime_load((uint8_t *)myData.data(), Size, error_buf, 120); + module = wasm_runtime_load(data_copy.data(), Size, error_buf, + MAX_ERROR_BUF_SIZE); if (!module) { std::cout << "[LOADING] " << error_buf << std::endl; goto DESTROY_RUNTIME; } // TODO: target_arch and other fields - option.target_arch = "x86_64"; - option.target_abi = "gnu"; + option.target_arch = kTargetArch; + option.target_abi = kTargetAbi; option.enable_bulk_memory = true; option.enable_thread_mgr = true; option.enable_tail_call = true; @@ -78,6 +88,34 @@ LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) goto DESTROY_COMP_CTX; } + aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size); + if (!aot_file_buf) { + handle_aot_recent_error("[EMITTING AOT FILE]"); + goto DESTROY_COMP_CTX; + } + + aot_module = wasm_runtime_load(aot_file_buf, aot_file_size, error_buf, + ERROR_BUF_SIZE); + if (!aot_module) { + std::cout << "[LOADING AOT MODULE] " << error_buf << std::endl; + goto RELEASE_AOT_FILE_BUF; + } + + inst = wasm_runtime_instantiate(aot_module, 1024 * 8, 0, error_buf, + ERROR_BUF_SIZE); + if (!inst) { + std::cout << "[INSTANTIATING AOT MODULE] " << error_buf << std::endl; + goto UNLOAD_AOT_MODULE; + } + + execute_export_functions(module, inst); + +DEINSTANTIZE_AOT_MODULE: + wasm_runtime_deinstantiate(inst); +UNLOAD_AOT_MODULE: + wasm_runtime_unload(aot_module); +RELEASE_AOT_FILE_BUF: + wasm_runtime_free(aot_file_buf); DESTROY_COMP_CTX: aot_destroy_comp_context(comp_ctx); DESTROY_COMP_DATA: diff --git a/tests/fuzz/wasm-mutator-fuzz/common/fuzzer_common.cc b/tests/fuzz/wasm-mutator-fuzz/common/fuzzer_common.cc new file mode 100644 index 000000000..9a25c118d --- /dev/null +++ b/tests/fuzz/wasm-mutator-fuzz/common/fuzzer_common.cc @@ -0,0 +1,145 @@ +// Copyright (C) 2025 Intel Corporation. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "fuzzer_common.h" +#include +#include + +void +print_execution_args(const wasm_export_t &export_type, + const std::vector &args, unsigned param_count) +{ + std::cout << "[EXECUTION] " << export_type.name << "("; + for (unsigned p_i = 0; p_i < param_count; p_i++) { + if (p_i != 0) { + std::cout << ", "; + } + + switch (args[p_i].kind) { + case WASM_I32: + std::cout << "i32:" << args[p_i].of.i32; + break; + case WASM_I64: + std::cout << "i64:" << args[p_i].of.i64; + break; + case WASM_F32: + std::cout << "f32:" << args[p_i].of.f32; + break; + case WASM_F64: + std::cout << "f64:" << args[p_i].of.f64; + break; + case WASM_EXTERNREF: + std::cout << "externref:" << args[p_i].of.foreign; + break; + default: + // because aft is_supported_val_kind() check, so we can safely + // return as WASM_FUNCREF + std::cout << "funcref:" << args[p_i].of.ref; + break; + } + } + std::cout << ")" << std::endl; +} + +bool +execute_export_functions(wasm_module_t module, wasm_module_inst_t inst) +{ + int32_t export_count = wasm_runtime_get_export_count(module); + + for (int e_i = 0; e_i < export_count; e_i++) { + wasm_export_t export_type; + + memset(&export_type, 0, sizeof(export_type)); + wasm_runtime_get_export_type(module, e_i, &export_type); + + if (export_type.kind != WASM_IMPORT_EXPORT_KIND_FUNC) { + continue; + } + + wasm_function_inst_t func = + wasm_runtime_lookup_function(inst, export_type.name); + if (!func) { + std::cout << "Failed to lookup function: " << export_type.name + << std::endl; + continue; + } + + wasm_func_type_t func_type = export_type.u.func_type; + uint32_t param_count = wasm_func_type_get_param_count(func_type); + + /* build arguments with capacity reservation */ + std::vector args; + args.reserve(param_count); // Optimization: prevent reallocations + for (unsigned p_i = 0; p_i < param_count; p_i++) { + wasm_valkind_t param_type = + wasm_func_type_get_param_valkind(func_type, p_i); + + if (!is_supported_val_kind(param_type)) { + std::cout + << "Bypass execution because of unsupported value kind: " + << param_type << std::endl; + return true; + } + + wasm_val_t arg = pre_defined_val(param_type); + args.push_back(arg); + } + + /* build results storage */ + uint32_t result_count = wasm_func_type_get_result_count(func_type); + std::vector results( + result_count); // Optimization: direct initialization + + print_execution_args(export_type, args, param_count); + + /* execute the function */ + wasm_exec_env_t exec_env = wasm_runtime_get_exec_env_singleton(inst); + if (!exec_env) { + std::cout << "Failed to get exec env" << std::endl; + return false; + } + + bool ret = + wasm_runtime_call_wasm_a(exec_env, func, result_count, + results.data(), param_count, args.data()); + if (!ret) { + const char *exception = wasm_runtime_get_exception(inst); + if (!exception) { + std::cout << "[EXECUTION] " << export_type.name + << "() failed. No exception info." << std::endl; + } + else { + std::cout << "[EXECUTION] " << export_type.name << "() failed. " + << exception << std::endl; + } + } + + wasm_runtime_clear_exception(inst); + } + + return true; +} + +void +report_fuzzer_error(FuzzerErrorPhase phase, const char *message) +{ + const char *phase_name = ""; + switch (phase) { + case FuzzerErrorPhase::LOADING: + phase_name = "LOADING"; + break; + case FuzzerErrorPhase::INSTANTIATING: + phase_name = "INSTANTIATING"; + break; + case FuzzerErrorPhase::COMPILING: + phase_name = "COMPILING"; + break; + case FuzzerErrorPhase::EXECUTION: + phase_name = "EXECUTION"; + break; + case FuzzerErrorPhase::CLEANUP: + phase_name = "CLEANUP"; + break; + } + std::cout << "[" << phase_name << "] " << message << std::endl; +} \ No newline at end of file diff --git a/tests/fuzz/wasm-mutator-fuzz/common/fuzzer_common.h b/tests/fuzz/wasm-mutator-fuzz/common/fuzzer_common.h new file mode 100644 index 000000000..365562c90 --- /dev/null +++ b/tests/fuzz/wasm-mutator-fuzz/common/fuzzer_common.h @@ -0,0 +1,77 @@ +// Copyright (C) 2025 Intel Corporation. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef FUZZER_COMMON_H +#define FUZZER_COMMON_H + +#include "wasm_export.h" +#include +#include + +// Constants for consistent buffer sizes +constexpr size_t ERROR_BUF_SIZE = 128; +constexpr size_t MAX_ERROR_BUF_SIZE = 120; // Used in wasm_runtime_load + +// Error phases for consistent reporting +enum class FuzzerErrorPhase { + LOADING, + INSTANTIATING, + COMPILING, + EXECUTION, + CLEANUP +}; + +// Small inline helper functions + +// Check if a value kind is supported by the fuzzer +static inline bool +is_supported_val_kind(wasm_valkind_t kind) +{ + return kind == WASM_I32 || kind == WASM_I64 || kind == WASM_F32 + || kind == WASM_F64 || kind == WASM_EXTERNREF + || kind == WASM_FUNCREF; +} + +// Generate a predefined value for a given value kind +static inline wasm_val_t +pre_defined_val(wasm_valkind_t kind) +{ + if (kind == WASM_I32) { + return wasm_val_t{ .kind = WASM_I32, .of = { .i32 = 2025 } }; + } + else if (kind == WASM_I64) { + return wasm_val_t{ .kind = WASM_I64, .of = { .i64 = 168 } }; + } + else if (kind == WASM_F32) { + return wasm_val_t{ .kind = WASM_F32, .of = { .f32 = 3.14159f } }; + } + else if (kind == WASM_F64) { + return wasm_val_t{ .kind = WASM_F64, .of = { .f64 = 2.71828 } }; + } + else if (kind == WASM_EXTERNREF) { + return wasm_val_t{ .kind = WASM_EXTERNREF, + .of = { .foreign = 0xabcddead } }; + } + // because aft is_supported_val_kind() check, so we can safely return as + // WASM_FUNCREF + else { + return wasm_val_t{ .kind = WASM_FUNCREF, .of = { .ref = nullptr } }; + } +} + +// Function declarations (implemented in fuzzer_common.cc) + +// Print execution arguments for debugging +void +print_execution_args(const wasm_export_t &export_type, + const std::vector &args, unsigned param_count); + +// Execute all export functions in a module +bool +execute_export_functions(wasm_module_t module, wasm_module_inst_t inst); + +// Helper for consistent error reporting +void +report_fuzzer_error(FuzzerErrorPhase phase, const char *message); + +#endif // FUZZER_COMMON_H \ No newline at end of file diff --git a/tests/fuzz/wasm-mutator-fuzz/sanitizer_flags.cmake b/tests/fuzz/wasm-mutator-fuzz/sanitizer_flags.cmake new file mode 100644 index 000000000..cb3815244 --- /dev/null +++ b/tests/fuzz/wasm-mutator-fuzz/sanitizer_flags.cmake @@ -0,0 +1,31 @@ +if(NOT IN_OSS_FUZZ) + message(STATUS "Enable ASan and UBSan in non-oss-fuzz environment for vmlib") + + add_compile_options(-fprofile-instr-generate -fcoverage-mapping) + + # + # Sync up with the content of infra/base-images/base-builder/Dockerfile in oss-fuzz + # + + # SANITIZER_FLAGS_address + add_compile_options(-fsanitize=address -fsanitize-address-use-after-scope) + + # SANITIZER_FLAGS_undefined + add_compile_options( + -O1 + -fsanitize=array-bounds,bool,builtin,enum,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr + -fno-sanitize-recover=array-bounds,bool,builtin,enum,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr + ) + + add_link_options(-fsanitize=address,undefined -fprofile-instr-generate) +endif() + +# Always disable unsigned-integer-overflow +if(CMAKE_C_COMPILER_ID MATCHES ".*Clang") + add_compile_options(-fno-sanitize=unsigned-integer-overflow) +endif() + +# '-fsanitize=vptr' not allowed with '-fno-rtti +# But, LLVM by default, disables the use of `rtti` in the compiler +add_compile_options(-fsanitize=fuzzer -fno-sanitize=vptr) +add_link_options(-fsanitize=fuzzer -fno-sanitize=vptr) diff --git a/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh b/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh index 097e5348b..c4ce7ba78 100755 --- a/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh +++ b/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh @@ -45,26 +45,23 @@ WASM_SHAPE=" --ensure-termination \ --export-everything true \ --fuel 7 \ --generate-custom-sections true \ ---min-funcs 5 \ +--min-funcs 10 \ --max-instructions 1024 \ --min-globals 10" -WASM_MVP_FEATURES=" --bulk-memory-enabled true \ +TIERED_A_FEATURE=" --bulk-memory-enabled true \ +--extended-const-enabled true \ +--memory64-enabled true \ --multi-value-enabled true \ --reference-types-enabled true \ --simd-enabled true \ ---tail-call-enabled true" +--tail-call-enabled true \ +--threads-enabled true" for i in $(seq 1 $EXPECTED_NUM) do - # mvp - try_generate_wasm "${WASM_SHAPE} ${WASM_MVP_FEATURES}" test_mvp_$i.wasm - - # other proposals - try_generate_wasm "${WASM_SHAPE} --exceptions-enabled true" test_exception_$i.wasm - try_generate_wasm "${WASM_SHAPE} --gc-enabled true" test_gc_$i.wasm - try_generate_wasm "${WASM_SHAPE} --memory64-enabled true" test_memory64_$i.wasm - try_generate_wasm "${WASM_SHAPE} --threads-enabled true" test_threads_$i.wasm + # tiered A wasm files + try_generate_wasm "${WASM_SHAPE} ${TIERED_A_FEATURE}" test_tiered_a_$i.wasm done printf "Done\n" diff --git a/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/CMakeLists.txt index b501baecf..e33b1826e 100644 --- a/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/CMakeLists.txt @@ -6,45 +6,49 @@ if(CUSTOM_MUTATOR EQUAL 1) endif() # Set default build options with the ability to override from the command line -if(NOT WAMR_BUILD_INTERP) +if(NOT DEFINED WAMR_BUILD_INTERP) set(WAMR_BUILD_INTERP 1) endif() -if(NOT WAMR_BUILD_AOT) +if(NOT DEFINED WAMR_BUILD_AOT) set(WAMR_BUILD_AOT 1) endif() -if(NOT WAMR_BUILD_JIT) +if(NOT DEFINED WAMR_BUILD_JIT) set(WAMR_BUILD_JIT 0) endif() -if(NOT WAMR_BUILD_LIBC_BUILTIN) +if(NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) set(WAMR_BUILD_LIBC_BUILTIN 0) endif() -if(NOT WAMR_BUILD_LIBC_WASI) +if(NOT DEFINED WAMR_BUILD_LIBC_WASI) set(WAMR_BUILD_LIBC_WASI 1) endif() -if(NOT WAMR_BUILD_FAST_INTERP) +if(NOT DEFINED WAMR_BUILD_FAST_INTERP) set(WAMR_BUILD_FAST_INTERP 1) endif() -if(NOT WAMR_BUILD_MULTI_MODULE) +if(NOT DEFINED WAMR_BUILD_MULTI_MODULE) set(WAMR_BUILD_MULTI_MODULE 0) endif() -if(NOT WAMR_BUILD_LIB_PTHREAD) +if(NOT DEFINED WAMR_BUILD_LIB_PTHREAD) set(WAMR_BUILD_LIB_PTHREAD 0) endif() -if(NOT WAMR_BUILD_MINI_LOADER) +if(NOT DEFINED WAMR_BUILD_MINI_LOADER) set(WAMR_BUILD_MINI_LOADER 0) endif() -set(WAMR_BUILD_SIMD 1) +if(NOT DEFINED WAMR_BUILD_SIMD) + set(WAMR_BUILD_SIMD 1) +endif() + set(WAMR_BUILD_REF_TYPES 1) -set(WAMR_BUILD_GC 1) +# disable it since it is not fully supported +set(WAMR_BUILD_GC 0) include(${REPO_ROOT_DIR}/build-scripts/runtime_lib.cmake) include(${REPO_ROOT_DIR}/core/shared/utils/uncommon/shared_uncommon.cmake) @@ -54,17 +58,6 @@ target_include_directories(vmlib PUBLIC ${RUNTIME_LIB_HEADER_LIST}) target_link_directories(vmlib PUBLIC ${RUNTIME_LIB_LINK_LIST}) target_link_libraries(vmlib PUBLIC ${REQUIRED_LLVM_LIBS}) -add_executable(wasm_mutator_fuzz wasm_mutator_fuzz.cc) +add_executable(wasm_mutator_fuzz wasm_mutator_fuzz.cc ../common/fuzzer_common.cc) +target_include_directories(wasm_mutator_fuzz PRIVATE ../common) target_link_libraries(wasm_mutator_fuzz PRIVATE vmlib m) - -if(NOT IN_OSS_FUZZ) - message(STATUS "Enable ASan and UBSan in non-oss-fuzz environment for vmlib") - target_compile_options(vmlib PUBLIC - -fprofile-instr-generate -fcoverage-mapping - -fno-sanitize-recover=all - -fsanitize=address,undefined - -fsanitize=float-divide-by-zero,unsigned-integer-overflow,local-bounds,nullability - -fno-sanitize=alignment - ) - target_link_options(vmlib PUBLIC -fsanitize=address,undefined -fprofile-instr-generate) -endif() diff --git a/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/wasm_mutator_fuzz.cc b/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/wasm_mutator_fuzz.cc index 391d899cf..d07568f5d 100644 --- a/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/wasm_mutator_fuzz.cc +++ b/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/wasm_mutator_fuzz.cc @@ -1,175 +1,30 @@ // Copyright (C) 2019 Intel Corporation. All rights reserved. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include "wasm_runtime_common.h" #include "wasm_export.h" -#include "bh_read_file.h" #include #include #include #include #include #include +#include "../common/fuzzer_common.h" using namespace std; -static bool -is_supported_val_kind(wasm_valkind_t kind) -{ - return kind == WASM_I32 || kind == WASM_I64 || kind == WASM_F32 - || kind == WASM_F64 || kind == WASM_EXTERNREF - || kind == WASM_FUNCREF; -} - -static wasm_val_t -pre_defined_val(wasm_valkind_t kind) -{ - if (kind == WASM_I32) { - return wasm_val_t{ .kind = WASM_I32, .of = { .i32 = 2025 } }; - } - else if (kind == WASM_I64) { - return wasm_val_t{ .kind = WASM_I64, .of = { .i64 = 168 } }; - } - else if (kind == WASM_F32) { - return wasm_val_t{ .kind = WASM_F32, .of = { .f32 = 3.14159f } }; - } - else if (kind == WASM_F64) { - return wasm_val_t{ .kind = WASM_F64, .of = { .f64 = 2.71828 } }; - } - else if (kind == WASM_EXTERNREF) { - return wasm_val_t{ .kind = WASM_EXTERNREF, - .of = { .foreign = 0xabcddead } }; - } - // because aft is_supported_val_kind() check, so we can safely return as - // WASM_FUNCREF - else { - return wasm_val_t{ .kind = WASM_FUNCREF, .of = { .ref = nullptr } }; - } -} -void -print_execution_args(const wasm_export_t &export_type, - const std::vector &args, unsigned param_count) -{ - std::cout << "[EXECUTION] " << export_type.name << "("; - for (unsigned p_i = 0; p_i < param_count; p_i++) { - if (p_i != 0) { - std::cout << ", "; - } - - switch (args[p_i].kind) { - case WASM_I32: - std::cout << "i32:" << args[p_i].of.i32; - break; - case WASM_I64: - std::cout << "i64:" << args[p_i].of.i64; - break; - case WASM_F32: - std::cout << "f32:" << args[p_i].of.f32; - break; - case WASM_F64: - std::cout << "f64:" << args[p_i].of.f64; - break; - case WASM_EXTERNREF: - std::cout << "externref:" << args[p_i].of.foreign; - break; - default: - // because aft is_supported_val_kind() check, so we can safely - // return as WASM_FUNCREF - std::cout << "funcref:" << args[p_i].of.ref; - break; - } - } - std::cout << ")" << std::endl; -} - -static bool -execute_export_functions(wasm_module_t module, wasm_module_inst_t inst) -{ - int32_t export_count = wasm_runtime_get_export_count(module); - - for (int e_i = 0; e_i < export_count; e_i++) { - wasm_export_t export_type = { 0 }; - wasm_runtime_get_export_type(module, e_i, &export_type); - - if (export_type.kind != WASM_IMPORT_EXPORT_KIND_FUNC) { - continue; - } - - wasm_function_inst_t func = - wasm_runtime_lookup_function(inst, export_type.name); - if (!func) { - std::cout << "Failed to lookup function: " << export_type.name - << std::endl; - continue; - } - - wasm_func_type_t func_type = export_type.u.func_type; - uint32_t param_count = wasm_func_type_get_param_count(func_type); - - /* build arguments */ - std::vector args; - for (unsigned p_i = 0; p_i < param_count; p_i++) { - wasm_valkind_t param_type = - wasm_func_type_get_param_valkind(func_type, p_i); - - if (!is_supported_val_kind(param_type)) { - std::cout - << "Bypass execution because of unsupported value kind: " - << param_type << std::endl; - return true; - } - - wasm_val_t arg = pre_defined_val(param_type); - args.push_back(arg); - } - - /* build results storage */ - uint32_t result_count = wasm_func_type_get_result_count(func_type); - std::vector results = std::vector(result_count); - - print_execution_args(export_type, args, param_count); - - /* execute the function */ - wasm_exec_env_t exec_env = wasm_runtime_get_exec_env_singleton(inst); - if (!exec_env) { - std::cout << "Failed to get exec env" << std::endl; - return false; - } - - bool ret = - wasm_runtime_call_wasm_a(exec_env, func, result_count, - results.data(), param_count, args.data()); - if (!ret) { - const char *exception = wasm_runtime_get_exception(inst); - if (!exception) { - std::cout << "[EXECUTION] " << export_type.name - << "() failed. No exception info." << std::endl; - } - else { - std::cout << "[EXECUTION] " << export_type.name << "() failed. " - << exception << std::endl; - } - } - - wasm_runtime_clear_exception(inst); - } - - return true; -} - extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - /* libfuzzer don't allow us to modify the given Data, so we copy the data - * here */ - std::vector myData(Data, Data + Size); + /* wasm_runtime_load may modify the input buffer in-place, + * so we must work on a copy to avoid overwriting libFuzzer's const input */ + std::vector data_copy(Data, Data + Size); /* init runtime environment */ wasm_runtime_init(); - char error_buf[128] = { 0 }; - wasm_module_t module = - wasm_runtime_load((uint8_t *)myData.data(), Size, error_buf, 120); + char error_buf[ERROR_BUF_SIZE] = { 0 }; + wasm_module_t module = wasm_runtime_load(data_copy.data(), Size, + error_buf, MAX_ERROR_BUF_SIZE); if (!module) { std::cout << "[LOADING] " << error_buf << std::endl; wasm_runtime_destroy(); @@ -177,8 +32,9 @@ LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) return 0; } - wasm_module_inst_t inst = wasm_runtime_instantiate( - module, 8 * 1024 * 1024, 16 * 1024 * 1024, error_buf, 120); + wasm_module_inst_t inst = + wasm_runtime_instantiate(module, 8 * 1024 * 1024, 16 * 1024 * 1024, + error_buf, MAX_ERROR_BUF_SIZE); if (!inst) { std::cout << "[INSTANTIATE] " << error_buf << std::endl; wasm_runtime_unload(module); @@ -237,42 +93,29 @@ LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, return LLVMFuzzerMutate(Data, Size, MaxSize); } - /* 3.read modified file */ - int read_len = 0; - int file_len = 0; - int res = 0; - uint8_t *buf = NULL; + /* 3.read modified file using RAII container */ FILE *fread_fp = fopen("./modified.wasm", "rb"); if (NULL == fread_fp) { printf("Faild to open modified.wasm file!\n"); exit(0); } - fseek(fread_fp, 0, SEEK_END); /* location to file end */ - file_len = ftell(fread_fp); /* get file size */ - buf = (uint8_t *)malloc(file_len); + fseek(fread_fp, 0, SEEK_END); /* location to file end */ + long file_len = ftell(fread_fp); /* get file size */ + fseek(fread_fp, 0, SEEK_SET); /* location to file start */ - if (NULL != buf) { - fseek(fread_fp, 0, SEEK_SET); /* location to file start */ - read_len = fread(buf, 1, file_len, fread_fp); - if ((read_len == file_len) && (read_len < MaxSize)) { - /* 4.fill Data buffer */ - memcpy(Data, buf, read_len); - res = read_len; - } - else { - res = 0; - } - } - else { - res = 0; - } - - memset(buf, 0, file_len); - free(buf); + std::vector buf(file_len); + size_t read_len = fread(buf.data(), 1, file_len, fread_fp); fclose(fread_fp); fread_fp = NULL; + int res = 0; + if (read_len == static_cast(file_len) && read_len < MaxSize) { + /* 4.fill Data buffer */ + memcpy(Data, buf.data(), read_len); + res = static_cast(read_len); + } + return res; } else { diff --git a/tests/regression/ba-issues/build_wamr.sh b/tests/regression/ba-issues/build_wamr.sh index 98a065b0f..f48dcbe4e 100755 --- a/tests/regression/ba-issues/build_wamr.sh +++ b/tests/regression/ba-issues/build_wamr.sh @@ -60,4 +60,7 @@ build_iwasm "-DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LIBC_WASI= # build fast-jit iwasm for testing fast-jit with libc-wasi disabled build_iwasm "-DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_SIMD=0 -DWAMR_BUILD_LIBC_WASI=0" "fast-jit-wasi-disabled" +# build default iwasm for testing wasm loader with branch hints enabled +build_iwasm "-DWAMR_BUILD_BRANCH_HINTS=1" "default-branch-hints-enabled" + # TODO: add more version of iwasm, for example, sgx version diff --git a/tests/regression/ba-issues/issues/issue-980002/branch_hint_invalid_free.wasm b/tests/regression/ba-issues/issues/issue-980002/branch_hint_invalid_free.wasm new file mode 100644 index 000000000..f11b50270 Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-980002/branch_hint_invalid_free.wasm differ diff --git a/tests/regression/ba-issues/issues/issue-980002/create_samples.py b/tests/regression/ba-issues/issues/issue-980002/create_samples.py new file mode 100644 index 000000000..036170e32 --- /dev/null +++ b/tests/regression/ba-issues/issues/issue-980002/create_samples.py @@ -0,0 +1,48 @@ +from pathlib import Path + +def u32leb(n): + out = bytearray() + while True: + b = n & 0x7f + n >>= 7 + if n: + b |= 0x80 + out.append(b) + if not n: + break + return bytes(out) +name = b"metadata.code.branch_hint" +assert len(name) == 25 +def build_module(payload_tail, out_path): + payload = b"".join([ + u32leb(len(name)), + name, + payload_tail + ]) + custom_section = b"\x00" + u32leb(len(payload)) + payload + payload_type = u32leb(1) + b"\x60" + u32leb(0) + u32leb(0) + sec_type = b"\x01" + u32leb(len(payload_type)) + payload_type + payload_func = u32leb(1) + u32leb(0) + sec_func = b"\x03" + u32leb(len(payload_func)) + payload_func + body = u32leb(0) + b"\x0b" + payload_code = u32leb(1) + u32leb(len(body)) + body + sec_code = b"\x0a" + u32leb(len(payload_code)) + payload_code + module = b"\x00asm" + b"\x01\x00\x00\x00" + sec_type + sec_func + sec_code + custom_section + Path(out_path).write_bytes(module) +payload_invalid_free = b"".join([ + b"\x01", # numFunctionHints + b"\x00", # func_idx + b"\x02", # num_hints + b"\x00", # hint0 offset + b"\x01", # hint0 size + b"\x00", # hint0 data + b"\x00", # hint1 offset + b"\x02", # hint1 size (invalid) +]) +build_module(payload_invalid_free, "branch_hint_invalid_free.wasm") +payload_dos = b"".join([ + b"\x01", + b"\x00", + b"\xff\xff\xff\xff\x0f", +]) +build_module(payload_dos, "branch_hint_null_deref.wasm") \ No newline at end of file diff --git a/tests/regression/ba-issues/issues/issue-980003/branch_hint_null_deref.wasm b/tests/regression/ba-issues/issues/issue-980003/branch_hint_null_deref.wasm new file mode 100644 index 000000000..396747fc4 Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-980003/branch_hint_null_deref.wasm differ diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json index 025b96fbd..4b84a152c 100644 --- a/tests/regression/ba-issues/running_config.json +++ b/tests/regression/ba-issues/running_config.json @@ -1818,6 +1818,40 @@ "stdout content": "Exception: unsupported opcode", "description": "classic-interp will exit gracefully when meeting simd opcodes" } + }, + { + "deprecated": false, + "ids": [ + 980002 + ], + "runtime": "iwasm-default-branch-hints-enabled", + "file": "branch_hint_invalid_free.wasm", + "mode": "fast-interp", + "options": "", + "argument": "", + "expected return": { + "ret code": 255, + "stdout content": "WASM module load failed: invalid number of branch hints: expected at most 0, got 2", + "description": "" + } + + }, + { + "deprecated": false, + "ids": [ + 980003 + ], + "runtime": "iwasm-default-branch-hints-enabled", + "file": "branch_hint_null_deref.wasm", + "mode": "fast-interp", + "options": "", + "argument": "", + "expected return": { + "ret code": 255, + "stdout content": "WASM module load failed: invalid number of branch hints: expected at most 0, got 42949672", + "description": "" + } + } ] } diff --git a/tests/standalone/test-aot-x18-reserve/run.sh b/tests/standalone/test-aot-x18-reserve/run.sh new file mode 100755 index 000000000..fe31e2d17 --- /dev/null +++ b/tests/standalone/test-aot-x18-reserve/run.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# Test for x18 register reservation on macOS ARM64 (aarch64). +# +# On macOS ARM64, x18 is reserved by Apple for TLS (Thread Local Storage). +# Without the +reserve-x18 LLVM flag, the AOT compiler may generate code +# that uses x18, causing random SIGSEGV crashes when run on macOS. +# +# This test compiles a WASM module that stresses register allocation +# (forcing x18 usage without the fix) and runs it 1000 times to verify +# no crashes occur. +# + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +WAMR_DIR="${SCRIPT_DIR}/../../.." + +# Detect platform +UNAME_S=$(uname -s) +UNAME_M=$(uname -m) + +# Only run this test on macOS ARM64 +if [[ "${UNAME_S}" != "Darwin" ]] || [[ "${UNAME_M}" != "arm64" ]]; then + echo "Skipping x18 reserve test: only applicable on macOS ARM64" + echo "Current platform: ${UNAME_S} ${UNAME_M}" + exit 0 +fi + +# Determine iwasm path based on platform +if [[ "${UNAME_S}" == "Darwin" ]]; then + IWASM_CMD="${WAMR_DIR}/product-mini/platforms/darwin/build/iwasm" +else + IWASM_CMD="${WAMR_DIR}/product-mini/platforms/linux/build/iwasm" +fi + +WAMRC_CMD="${WAMR_DIR}/wamr-compiler/build/wamrc" + +# Check if required binaries exist +if [[ ! -x "${IWASM_CMD}" ]]; then + echo "Error: iwasm not found at ${IWASM_CMD}" + echo "Please build iwasm first" + exit 1 +fi + +if [[ ! -x "${WAMRC_CMD}" ]]; then + echo "Error: wamrc not found at ${WAMRC_CMD}" + echo "Please build wamrc first" + exit 1 +fi + +cd "${SCRIPT_DIR}" + +# Find wat2wasm (check CI path first, then system PATH) +if [[ -x "/opt/wabt/bin/wat2wasm" ]]; then + WAT2WASM="/opt/wabt/bin/wat2wasm" +elif command -v wat2wasm &> /dev/null; then + WAT2WASM="wat2wasm" +else + echo "Error: wat2wasm not found" + echo "Please install wabt tools" + exit 1 +fi + +# Compile WAT to WASM if needed +if [[ ! -f stress_registers.wasm ]] || [[ stress_registers.wat -nt stress_registers.wasm ]]; then + echo "Compiling stress_registers.wat to WASM..." + if ! ${WAT2WASM} stress_registers.wat -o stress_registers.wasm; then + echo "Error: Failed to compile WAT to WASM" + exit 1 + fi +fi + +if [[ $1 != "--aot" ]]; then + echo "============> run stress_registers.wasm (interpreter mode)" + echo "Running 1000 iterations in interpreter mode..." + for i in $(seq 1 1000); do + if ! ${IWASM_CMD} stress_registers.wasm 2>&1; then + echo "FAILED: Crash at iteration $i" + exit 1 + fi + done + echo "PASSED: 1000 iterations completed without crash" +else + echo "============> compile stress_registers.wasm to AOT" + + # Compile to AOT - the fix should add +reserve-x18 automatically on macOS ARM64 + if ! ${WAMRC_CMD} --opt-level=3 -o stress_registers.aot stress_registers.wasm; then + echo "Error: Failed to compile WASM to AOT" + exit 1 + fi + + echo "============> run stress_registers.aot" + echo "Running 1000 iterations to verify x18 is properly reserved..." + echo "(Without the fix, this would crash ~80% of the time)" + + failed=0 + for i in $(seq 1 1000); do + if ! ${IWASM_CMD} stress_registers.aot 2>&1 > /dev/null; then + echo "FAILED: Crash at iteration $i" + failed=1 + break + fi + # Progress indicator every 100 iterations + if [[ $((i % 100)) -eq 0 ]]; then + echo " Progress: $i/1000 iterations completed" + fi + done + + if [[ ${failed} -eq 0 ]]; then + echo "PASSED: 1000 iterations completed without crash" + echo "The +reserve-x18 fix is working correctly" + exit 0 + else + echo "FAILED: x18 register corruption detected" + echo "The +reserve-x18 fix may not be applied correctly" + exit 1 + fi +fi diff --git a/tests/standalone/test-aot-x18-reserve/stress_registers.wat b/tests/standalone/test-aot-x18-reserve/stress_registers.wat new file mode 100644 index 000000000..71b627fd5 --- /dev/null +++ b/tests/standalone/test-aot-x18-reserve/stress_registers.wat @@ -0,0 +1,97 @@ +;; Copyright (C) 2019 Intel Corporation. All rights reserved. +;; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +;; Test module that uses many local variables to stress register allocation. +;; On ARM64, this will force LLVM to use x18 register if +reserve-x18 is not set. +;; x18 is reserved by Apple on macOS for TLS, so using it causes crashes. + +(module + (memory (export "memory") 1) + + (func $stress_registers (export "stress_registers") (param $input i64) (result i64) + (local $a i64) (local $b i64) (local $c i64) (local $d i64) + (local $e i64) (local $f i64) (local $g i64) (local $h i64) + (local $i i64) (local $j i64) (local $k i64) (local $l i64) + (local $m i64) (local $n i64) (local $o i64) (local $p i64) + (local $q i64) (local $r i64) (local $s i64) (local $t i64) + (local $u i64) (local $v i64) (local $w i64) (local $x i64) + + ;; Initialize all locals with different values based on input + (local.set $a (i64.add (local.get $input) (i64.const 1))) + (local.set $b (i64.mul (local.get $a) (i64.const 2))) + (local.set $c (i64.add (local.get $b) (i64.const 3))) + (local.set $d (i64.mul (local.get $c) (i64.const 4))) + (local.set $e (i64.add (local.get $d) (i64.const 5))) + (local.set $f (i64.mul (local.get $e) (i64.const 6))) + (local.set $g (i64.add (local.get $f) (i64.const 7))) + (local.set $h (i64.mul (local.get $g) (i64.const 8))) + (local.set $i (i64.add (local.get $h) (i64.const 9))) + (local.set $j (i64.mul (local.get $i) (i64.const 10))) + (local.set $k (i64.add (local.get $j) (i64.const 11))) + (local.set $l (i64.mul (local.get $k) (i64.const 12))) + (local.set $m (i64.add (local.get $l) (i64.const 13))) + (local.set $n (i64.mul (local.get $m) (i64.const 14))) + (local.set $o (i64.add (local.get $n) (i64.const 15))) + (local.set $p (i64.mul (local.get $o) (i64.const 16))) + (local.set $q (i64.add (local.get $p) (i64.const 17))) + (local.set $r (i64.mul (local.get $q) (i64.const 18))) + (local.set $s (i64.add (local.get $r) (i64.const 19))) + (local.set $t (i64.mul (local.get $s) (i64.const 20))) + (local.set $u (i64.add (local.get $t) (i64.const 21))) + (local.set $v (i64.mul (local.get $u) (i64.const 22))) + (local.set $w (i64.add (local.get $v) (i64.const 23))) + (local.set $x (i64.mul (local.get $w) (i64.const 24))) + + ;; Now use all of them together to prevent optimization + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (local.get $a) + (local.get $b)) + (local.get $c)) + (local.get $d)) + (local.get $e)) + (local.get $f)) + (local.get $g)) + (local.get $h)) + (local.get $i)) + (local.get $j)) + (local.get $k)) + (local.get $l)) + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (i64.add + (local.get $m) + (local.get $n)) + (local.get $o)) + (local.get $p)) + (local.get $q)) + (local.get $r)) + (local.get $s)) + (local.get $t)) + (local.get $u)) + (local.get $v)) + (local.get $w)) + (local.get $x)))) + + (func $_start (export "_start") + (drop (call $stress_registers (i64.const 42))) + ) +) diff --git a/tests/standalone/test-invoke-native/CMakeLists.txt b/tests/standalone/test-invoke-native/CMakeLists.txt index ce659ae42..3483ebd14 100644 --- a/tests/standalone/test-invoke-native/CMakeLists.txt +++ b/tests/standalone/test-invoke-native/CMakeLists.txt @@ -103,12 +103,6 @@ if (NOT WAMR_BUILD_PLATFORM STREQUAL "darwin") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE") endif () -if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () -endif () - # The following flags are to enhance security, but it may impact performance, # we disable them by default. #if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index df3c2b80d..d99d991bb 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -14,7 +14,30 @@ set(CMAKE_POLICY_VERSION_MINIMUM 3.5) SET(CMAKE_BUILD_TYPE Debug) -# add_definitions (-m32) +set(CMAKE_CXX_STANDARD 17) + +#TODO: modularization me +# Detect Hosting target info +string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") @@ -64,8 +87,11 @@ add_subdirectory(linux-perf) add_subdirectory(gc) add_subdirectory(tid-allocator) add_subdirectory(unsupported-features) +add_subdirectory(smart-tests) +add_subdirectory(exception-handling) +add_subdirectory(running-modes) -if (NOT WAMR_BUILD_TARGET STREQUAL "X86_32") +if(WAMR_BUILD_TARGET STREQUAL "X86_64") add_subdirectory(aot-stack-frame) # should enable 32-bit llvm when X86_32 @@ -73,11 +99,22 @@ if (NOT WAMR_BUILD_TARGET STREQUAL "X86_32") add_subdirectory (custom-section) add_subdirectory (compilation) - # Fast-JIT or mem64 is not supported on X86_32 - add_subdirectory (running-modes) add_subdirectory (memory64) add_subdirectory (shared-heap) # HW_BOUND_CHECK is not supported on X86_32 + add_subdirectory (runtime-common) +endif() + +if(WAMR_BUILD_TARGET STREQUAL "AARCH64") + add_subdirectory(aot-stack-frame) + + add_subdirectory (aot) + add_subdirectory (custom-section) + add_subdirectory (compilation) + + add_subdirectory (memory64) + add_subdirectory (shared-heap) + add_subdirectory (runtime-common) endif () diff --git a/tests/unit/aot-stack-frame/CMakeLists.txt b/tests/unit/aot-stack-frame/CMakeLists.txt index b20bb67b9..44b4b4811 100644 --- a/tests/unit/aot-stack-frame/CMakeLists.txt +++ b/tests/unit/aot-stack-frame/CMakeLists.txt @@ -22,7 +22,7 @@ set (WAMR_BUILD_GC 1) include (../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/unit/aot/CMakeLists.txt b/tests/unit/aot/CMakeLists.txt index e45d4c003..66fe801b2 100644 --- a/tests/unit/aot/CMakeLists.txt +++ b/tests/unit/aot/CMakeLists.txt @@ -23,7 +23,7 @@ set (WAMR_BUILD_APP_FRAMEWORK 0) include (../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include (${IWASM_DIR}/compilation/iwasm_compl.cmake) diff --git a/tests/unit/common/test_helper.h b/tests/unit/common/test_helper.h index 4db465fc8..f15c26bef 100644 --- a/tests/unit/common/test_helper.h +++ b/tests/unit/common/test_helper.h @@ -11,6 +11,20 @@ #include #include #include +#include +#include +#include + +static inline std::string +get_test_binary_dir() +{ + char cwd[PATH_MAX] = { 0 }; + if (!getcwd(cwd, sizeof(cwd))) { + return std::string(); + } + + return std::string(cwd); +} template class WAMRRuntimeRAII diff --git a/tests/unit/compilation/CMakeLists.txt b/tests/unit/compilation/CMakeLists.txt index f6912122d..00530fbe8 100644 --- a/tests/unit/compilation/CMakeLists.txt +++ b/tests/unit/compilation/CMakeLists.txt @@ -26,7 +26,7 @@ set (WAMR_BUILD_JIT 0) include (../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include (${IWASM_DIR}/compilation/iwasm_compl.cmake) diff --git a/tests/unit/compilation/aot_compiler_test.cc b/tests/unit/compilation/aot_compiler_test.cc index 6fbccbb17..7c5df9c34 100644 --- a/tests/unit/compilation/aot_compiler_test.cc +++ b/tests/unit/compilation/aot_compiler_test.cc @@ -14,23 +14,6 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - extern "C" { char * aot_generate_tempfile_name(const char *prefix, const char *extension, @@ -50,7 +33,7 @@ class aot_compiler_test_suit : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); } @@ -117,8 +100,13 @@ TEST_F(aot_compiler_test_suit, aot_emit_object_file) // Test size_level in range from 0 to 3. option.opt_level = 3; - for (i = 0; i <= 3; i++) { - option.size_level = i; +#if defined(__aarch64__) || defined(_M_ARM64) + std::vector size_levels = { 0, 3 }; +#else + std::vector size_levels = { 0, 1, 2, 3 }; +#endif + for (auto size_level : size_levels) { + option.size_level = size_level; test_aot_emit_object_file_with_option(&option); } diff --git a/tests/unit/compilation/aot_emit_aot_file_test.cc b/tests/unit/compilation/aot_emit_aot_file_test.cc index 8b0f63a8e..c94b15402 100644 --- a/tests/unit/compilation/aot_emit_aot_file_test.cc +++ b/tests/unit/compilation/aot_emit_aot_file_test.cc @@ -14,23 +14,6 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - extern "C" { uint8 * aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data, @@ -50,7 +33,7 @@ class aot_emit_aot_file_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); } diff --git a/tests/unit/compilation/aot_emit_control_test.cc b/tests/unit/compilation/aot_emit_control_test.cc index 849189c90..c8a47554c 100644 --- a/tests/unit/compilation/aot_emit_control_test.cc +++ b/tests/unit/compilation/aot_emit_control_test.cc @@ -15,23 +15,6 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class aot_emit_control_test_suite : public testing::Test { protected: @@ -45,7 +28,7 @@ class aot_emit_control_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); } diff --git a/tests/unit/compilation/aot_emit_function_test.cc b/tests/unit/compilation/aot_emit_function_test.cc index d10d639a1..db67c3b20 100644 --- a/tests/unit/compilation/aot_emit_function_test.cc +++ b/tests/unit/compilation/aot_emit_function_test.cc @@ -14,23 +14,6 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class aot_emit_function_test_suite : public testing::Test { protected: @@ -44,7 +27,7 @@ class aot_emit_function_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); } diff --git a/tests/unit/compilation/aot_emit_memory_test.cc b/tests/unit/compilation/aot_emit_memory_test.cc index 0e8e86f21..840a30f6d 100644 --- a/tests/unit/compilation/aot_emit_memory_test.cc +++ b/tests/unit/compilation/aot_emit_memory_test.cc @@ -16,29 +16,12 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class compilation_aot_emit_memory_test : public testing::Test { protected: void SetUp() override { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); AOTCompOption option = { 0 }; diff --git a/tests/unit/compilation/aot_emit_numberic_test.cc b/tests/unit/compilation/aot_emit_numberic_test.cc index 70f119f9e..22a62505d 100644 --- a/tests/unit/compilation/aot_emit_numberic_test.cc +++ b/tests/unit/compilation/aot_emit_numberic_test.cc @@ -15,23 +15,6 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class aot_emit_numberic_test_suite : public testing::Test { protected: @@ -45,7 +28,7 @@ class aot_emit_numberic_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); } diff --git a/tests/unit/compilation/aot_emit_parametric_test.cc b/tests/unit/compilation/aot_emit_parametric_test.cc index aa7b08df3..4ecac1894 100644 --- a/tests/unit/compilation/aot_emit_parametric_test.cc +++ b/tests/unit/compilation/aot_emit_parametric_test.cc @@ -14,23 +14,6 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class aot_emit_parametric_test_suite : public testing::Test { protected: @@ -44,7 +27,7 @@ class aot_emit_parametric_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); } diff --git a/tests/unit/compilation/aot_emit_table_test.cc b/tests/unit/compilation/aot_emit_table_test.cc index c77d16c6d..457e1073a 100644 --- a/tests/unit/compilation/aot_emit_table_test.cc +++ b/tests/unit/compilation/aot_emit_table_test.cc @@ -14,23 +14,6 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class aot_emit_table_test_suite : public testing::Test { protected: @@ -44,7 +27,7 @@ class aot_emit_table_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); } diff --git a/tests/unit/compilation/aot_llvm_test.cc b/tests/unit/compilation/aot_llvm_test.cc index de4ab17c4..83714130c 100644 --- a/tests/unit/compilation/aot_llvm_test.cc +++ b/tests/unit/compilation/aot_llvm_test.cc @@ -14,23 +14,6 @@ static std::string CWD; static std::string MAIN_WASM = "/main.wasm"; static char *WASM_FILE; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class aot_llvm_test_suite : public testing::Test { protected: @@ -44,7 +27,7 @@ class aot_llvm_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); } diff --git a/tests/unit/custom-section/CMakeLists.txt b/tests/unit/custom-section/CMakeLists.txt index b57fb8bff..bcceed0a6 100644 --- a/tests/unit/custom-section/CMakeLists.txt +++ b/tests/unit/custom-section/CMakeLists.txt @@ -38,7 +38,7 @@ set (WAMR_BUILD_LOAD_CUSTOM_SECTION 1) include (../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include (${IWASM_DIR}/compilation/iwasm_compl.cmake) diff --git a/tests/unit/exception-handling/CMakeLists.txt b/tests/unit/exception-handling/CMakeLists.txt new file mode 100644 index 000000000..073f62aae --- /dev/null +++ b/tests/unit/exception-handling/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright (C) 2024 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +project (test-exception-handling) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) + +set (WAMR_BUILD_AOT 0) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_FAST_INTERP 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_EXCE_HANDLING 1) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) +include_directories (${IWASM_DIR}/interpreter) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} +) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (exception_handling_test ${unit_test_sources}) + +target_link_libraries (exception_handling_test gtest_main) + +gtest_discover_tests(exception_handling_test) diff --git a/tests/unit/exception-handling/exception_handling_test.cc b/tests/unit/exception-handling/exception_handling_test.cc new file mode 100644 index 000000000..60554957a --- /dev/null +++ b/tests/unit/exception-handling/exception_handling_test.cc @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2024 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "wasm_runtime_common.h" +#include "bh_platform.h" + +/* Pull in the INVALID_TAGINDEX definitions */ +#include "wasm_runtime.h" + +class ExceptionHandlingTest : public testing::Test +{ + protected: + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + virtual void TearDown() { wasm_runtime_destroy(); } + + public: + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; + char error_buf[256]; +}; + +/* + * Test that IS_INVALID_TAGINDEX correctly identifies the invalid tag index + * value (0xFFFFFFFF) used for cross-module exceptions with unknown tags. + * + * The RETHROW handler must check IS_INVALID_TAGINDEX before accessing + * module->module->tags[exception_tag_index]. Without the check, + * exception_tag_index = INVALID_TAGINDEX (0xFFFFFFFF) would cause + * tags[0xFFFFFFFF] -- a massive out-of-bounds read. + * + * The THROW handler at wasm_interp_classic.c properly checks + * IS_INVALID_TAGINDEX, but previously RETHROW did not. + */ +TEST_F(ExceptionHandlingTest, invalid_tagindex_detected) +{ + uint32_t tag_index = INVALID_TAGINDEX; + EXPECT_TRUE(IS_INVALID_TAGINDEX(tag_index)) + << "INVALID_TAGINDEX (0xFFFFFFFF) should be detected"; +} + +TEST_F(ExceptionHandlingTest, valid_tagindex_not_rejected) +{ + uint32_t tag_index = 0; + EXPECT_FALSE(IS_INVALID_TAGINDEX(tag_index)) + << "Tag index 0 should not be detected as invalid"; + + tag_index = 5; + EXPECT_FALSE(IS_INVALID_TAGINDEX(tag_index)) + << "Tag index 5 should not be detected as invalid"; +} + +/* + * Test that a WASM module with exception handling (try/catch/throw) + * can load and instantiate correctly when exception handling is enabled. + */ +TEST_F(ExceptionHandlingTest, load_module_with_exception_handling) +{ + /* + * Minimal WASM module with exception handling: + * - Tag section (id=13): 1 tag, type 0 (no params) + * - Function with try/catch_all/end that does nothing + */ + uint8_t wasm_eh[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, + /* Type section: 1 type, () -> () */ + 0x01, 0x04, 0x01, 0x60, 0x00, 0x00, + /* Function section: 1 func, type 0 */ + 0x03, 0x02, 0x01, 0x00, + /* Tag section (id=13): 1 tag, attribute=0, type=0 */ + 0x0D, 0x03, 0x01, 0x00, 0x00, + /* Export: "f" = func 0 */ + 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00, + /* Code section */ + 0x0A, 0x08, 0x01, + 0x06, 0x00, /* body size=6, 0 locals */ + 0x06, 0x40, /* try (void) */ + 0x19, /* catch_all */ + 0x0B, /* end try */ + 0x0B, /* end func */ + }; + + memset(error_buf, 0, sizeof(error_buf)); + wasm_module_t module = wasm_runtime_load( + wasm_eh, sizeof(wasm_eh), error_buf, sizeof(error_buf)); + + ASSERT_NE(module, nullptr) << "Module load failed: " << error_buf; + + wasm_module_inst_t inst = wasm_runtime_instantiate( + module, 8192, 8192, error_buf, sizeof(error_buf)); + ASSERT_NE(inst, nullptr) << "Instantiation failed: " << error_buf; + + wasm_function_inst_t func = + wasm_runtime_lookup_function(inst, "f"); + ASSERT_NE(func, nullptr) << "Function 'f' should be found"; + + wasm_exec_env_t exec_env = + wasm_runtime_create_exec_env(inst, 8192); + ASSERT_NE(exec_env, nullptr) << "Failed to create exec env"; + + bool ok = wasm_runtime_call_wasm(exec_env, func, 0, NULL); + ASSERT_TRUE(ok) << "wasm_runtime_call_wasm failed: " + << wasm_runtime_get_exception(inst); + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(inst); + wasm_runtime_unload(module); +} + +/* + * Verify that the RETHROW handler's tag index validation logic matches + * the THROW handler. Both must handle IS_INVALID_TAGINDEX the same way: + * skip the tags[] access and set cell_num_to_copy = 0. + */ +TEST_F(ExceptionHandlingTest, rethrow_handles_invalid_tagindex_like_throw) +{ + /* Simulate what both handlers should do with INVALID_TAGINDEX */ + uint32_t exception_tag_index = INVALID_TAGINDEX; + uint32_t tag_count = 5; + + /* THROW handler logic (reference - always correct): */ + uint32_t throw_cell_num = 0; + if (IS_INVALID_TAGINDEX(exception_tag_index)) { + throw_cell_num = 0; /* skip tags[] access */ + } + else { + /* would access tags[exception_tag_index] */ + throw_cell_num = 42; /* placeholder */ + } + + /* RETHROW handler logic (after fix - should match THROW): */ + uint32_t rethrow_cell_num = 0; + if (IS_INVALID_TAGINDEX(exception_tag_index)) { + rethrow_cell_num = 0; /* skip tags[] access */ + } + else { + /* would access tags[exception_tag_index] */ + rethrow_cell_num = 42; /* placeholder */ + } + + EXPECT_EQ(throw_cell_num, rethrow_cell_num) + << "RETHROW should handle INVALID_TAGINDEX the same as THROW"; + + EXPECT_EQ(throw_cell_num, 0u) + << "Both handlers should set cell_num = 0 for INVALID_TAGINDEX"; + + /* Without the fix, RETHROW would have tried: + * tags[0xFFFFFFFF] => massive OOB read => crash */ + EXPECT_TRUE(exception_tag_index >= tag_count) + << "INVALID_TAGINDEX should be >= any reasonable tag_count"; +} diff --git a/tests/unit/gc/CMakeLists.txt b/tests/unit/gc/CMakeLists.txt index c8b865a38..327825c04 100644 --- a/tests/unit/gc/CMakeLists.txt +++ b/tests/unit/gc/CMakeLists.txt @@ -11,6 +11,7 @@ set (WAMR_BUILD_GC 1) set (WAMR_BUILD_INTERP 1) set (WAMR_BUILD_AOT 0) set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_SANITIZER "asan") include (../unit_common.cmake) diff --git a/tests/unit/gc/gc_test.cc b/tests/unit/gc/gc_test.cc index 196ddba65..3dc1d303d 100644 --- a/tests/unit/gc/gc_test.cc +++ b/tests/unit/gc/gc_test.cc @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include "test_helper.h" #include "gtest/gtest.h" #include "bh_platform.h" #include "bh_read_file.h" @@ -10,27 +11,10 @@ class WasmGCTest : public testing::Test { - private: - std::string get_binary_path() - { - char cwd[1024] = { 0 }; - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - return NULL; - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); - } - protected: void SetUp() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); memset(&init_args, 0, sizeof(RuntimeInitArgs)); @@ -53,7 +37,7 @@ class WasmGCTest : public testing::Test public: bool load_wasm_file(const char *wasm_file) { - const char *file; + char *file; unsigned char *wasm_file_buf; uint32 wasm_file_size; @@ -61,6 +45,8 @@ class WasmGCTest : public testing::Test wasm_file_buf = (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + free(file); + if (!wasm_file_buf) return false; @@ -100,3 +86,10 @@ TEST_F(WasmGCTest, Test_app1) ASSERT_TRUE(load_wasm_file("func1.wasm")); ASSERT_TRUE(load_wasm_file("func2.wasm")); } + +TEST_F(WasmGCTest, Test_nested_struct) +{ + //FIXME: Revert the change when anyref support is added + ASSERT_FALSE(load_wasm_file("nested_struct_field_any.wasm")); + ASSERT_FALSE(load_wasm_file("nested_array_elem_any.wasm")); +} \ No newline at end of file diff --git a/tests/unit/gc/wasm-apps/nested_array_elem_any.wasm b/tests/unit/gc/wasm-apps/nested_array_elem_any.wasm new file mode 100644 index 000000000..b241cde58 Binary files /dev/null and b/tests/unit/gc/wasm-apps/nested_array_elem_any.wasm differ diff --git a/tests/unit/gc/wasm-apps/nested_array_elem_any.wat b/tests/unit/gc/wasm-apps/nested_array_elem_any.wat new file mode 100644 index 000000000..7866ae254 --- /dev/null +++ b/tests/unit/gc/wasm-apps/nested_array_elem_any.wat @@ -0,0 +1,63 @@ +(module + (type $array_type (array (mut anyref))) + + (global $g_array + (mut (ref $array_type)) + (array.new_fixed $array_type 2 + (ref.i31 (i32.const 10)) + (array.new_fixed $array_type 2 + (ref.i31 (i32.const 20)) + (array.new_default $array_type (i32.const 2)) + ) + ) + ) + + ;; assert_return(invoke "get_elem0"), 10) + (func (export "get_elem0") (result i32) + (i31.get_s (ref.cast i31ref (array.get $array_type (global.get $g_array) (i32.const 0)))) + ) + + ;; assert_return(invoke "get_elem1"), array.new_fixed $array_type ...) + (func (export "get_elem1") (result anyref) + (array.get $array_type (global.get $g_array) (i32.const 1)) + ) + + ;; assert_return(invoke "get_elem1_elem0"), 20) + (func (export "get_elem1_elem0") (result i32) + (i31.get_s (ref.cast i31ref + (array.get $array_type + (ref.cast (ref $array_type) + (array.get $array_type (global.get $g_array) (i32.const 1)) + ) + (i32.const 0) + ) + )) + ) + + ;; assert_return(invoke "get_elem1_elem1"), array.new_default $array_type ...) + (func (export "get_elem1_elem1") (result anyref) + (array.get $array_type + (ref.cast (ref $array_type) + (array.get $array_type (global.get $g_array) (i32.const 1)) + ) + (i32.const 1) + ) + ) + + ;; assert_return(invoke "get_elem1_elem1_elem0"), 0) + (func (export "get_elem1_elem1_elem0") (result i32) + (i31.get_s (ref.cast i31ref + (array.get $array_type + (ref.cast (ref $array_type) + (array.get $array_type + (ref.cast (ref $array_type) + (array.get $array_type (global.get $g_array) (i32.const 1)) + ) + (i32.const 1) + ) + ) + (i32.const 0) + ) + )) + ) +) \ No newline at end of file diff --git a/tests/unit/gc/wasm-apps/nested_struct_field_any.wasm b/tests/unit/gc/wasm-apps/nested_struct_field_any.wasm new file mode 100644 index 000000000..12c3e2cc7 Binary files /dev/null and b/tests/unit/gc/wasm-apps/nested_struct_field_any.wasm differ diff --git a/tests/unit/gc/wasm-apps/nested_struct_field_any.wat b/tests/unit/gc/wasm-apps/nested_struct_field_any.wat new file mode 100644 index 000000000..9346373b3 --- /dev/null +++ b/tests/unit/gc/wasm-apps/nested_struct_field_any.wat @@ -0,0 +1,55 @@ +(module + (type $struct_type (struct (field (mut i32)) (field (mut anyref)))) + + (global $g_struct + (mut (ref $struct_type)) + (struct.new $struct_type + (i32.const 10) + (struct.new $struct_type + (i32.const 20) + (struct.new_default $struct_type) + ) + ) + ) + + ;; assert_return(invoke "get_field1"), 10) + (func (export "get_field1") (result i32) + (struct.get $struct_type 0 (global.get $g_struct)) + ) + + ;; assert_return(invoke "get_field1"), struct.new $struct_type ...) + (func (export "get_field2") (result anyref) + (struct.get $struct_type 1 (global.get $g_struct)) + ) + + ;; assert_return(invoke "get_field2_field1"), 20) + (func (export "get_field2_field1") (result i32) + (struct.get $struct_type 0 + (ref.cast structref + (struct.get $struct_type 1 (global.get $g_struct)) + ) + ) + ) + + ;; assert_return(invoke "get_field2_field2"), struct.new_default $struct_type ...) + (func (export "get_field2_field2") (result anyref) + (struct.get $struct_type 1 + (ref.cast structref + (struct.get $struct_type 1 (global.get $g_struct)) + ) + ) + ) + + ;; assert_return(invoke "get_field2_field2_field1"), 0) + (func (export "get_field2_field2_field1") (result i32) + (struct.get $struct_type 0 + (ref.cast structref + (struct.get $struct_type 1 + (ref.cast structref + (struct.get $struct_type 1 (global.get $g_struct)) + ) + ) + ) + ) + ) +) diff --git a/tests/unit/linear-memory-aot/build_aot.sh b/tests/unit/linear-memory-aot/build_aot.sh index 8f2b29ede..12c10c33f 100755 --- a/tests/unit/linear-memory-aot/build_aot.sh +++ b/tests/unit/linear-memory-aot/build_aot.sh @@ -31,15 +31,42 @@ if [ ! -s "$WAST2WASM" ]; then echo "please install wabt first" && exit -1 fi +# Detect host architecture +HOST_ARCH=$(uname -m) +echo "Detected host architecture: $HOST_ARCH" + # Iterate over the files array -rm -r build +rm -r build 2>/dev/null mkdir build for file_name in "${file_names[@]}"; do # wast to wasm $WAST2WASM "${file_name}.wast" -o "build/${file_name}.wasm" - # compile the aot files, x86-64, x86-32, no_hw_bounds, no_hw_bounds_x32 - $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm" - $WAMRC --target=i386 -o "build/${file_name}_32.aot" "build/${file_name}.wasm" - $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm" - $WAMRC --bounds-checks=1 --target=i386 -o "build/${file_name}_no_hw_bounds_32.aot" "build/${file_name}.wasm" + + # Determine compilation configurations based on host architecture + case "$HOST_ARCH" in + x86_64) + # x86-64 host: compile both x86-64 and x86-32 + $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm" + $WAMRC --target=i386 -o "build/${file_name}_32.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 --target=i386 -o "build/${file_name}_no_hw_bounds_32.aot" "build/${file_name}.wasm" + ;; + i386|i686) + # x86-32 host: compile only x86-32 + $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm" + ;; + aarch64|arm64) + # ARM64 host: compile only aarch64 + $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm" + ;; + *) + echo "Warning: Unsupported architecture '$HOST_ARCH'. Using default target." + $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm" + ;; + esac done + +echo "AOT compilation completed for architecture: $HOST_ARCH" diff --git a/tests/unit/linear-memory-aot/linear_memory_aot_test.cc b/tests/unit/linear-memory-aot/linear_memory_aot_test.cc index 198dfbc91..b365721fe 100644 --- a/tests/unit/linear-memory-aot/linear_memory_aot_test.cc +++ b/tests/unit/linear-memory-aot/linear_memory_aot_test.cc @@ -11,23 +11,6 @@ static std::string CWD; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - #if WASM_DISABLE_HW_BOUND_CHECK != 0 #define TEST_SUITE_NAME linear_memory_test_suite_aot_no_hw_bound #else @@ -45,7 +28,7 @@ class TEST_SUITE_NAME : public testing::Test // Otherwise, this can be skipped. virtual void SetUp() {} - static void SetUpTestCase() { CWD = get_binary_path(); } + static void SetUpTestCase() { CWD = get_test_binary_dir(); } // virtual void TearDown() will be called after each test is run. // You should define it if there is cleanup work to do. Otherwise, diff --git a/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc b/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc index a5db0e033..8a6c20e4f 100644 --- a/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc +++ b/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc @@ -11,23 +11,6 @@ static std::string CWD; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - #if WASM_DISABLE_HW_BOUND_CHECK != 0 #define TEST_SUITE_NAME linear_memory_test_suite_wasm_no_hw_bound #else @@ -45,7 +28,7 @@ class TEST_SUITE_NAME : public testing::Test // Otherwise, this can be skipped. virtual void SetUp() {} - static void SetUpTestCase() { CWD = get_binary_path(); } + static void SetUpTestCase() { CWD = get_test_binary_dir(); } // virtual void TearDown() will be called after each test is run. // You should define it if there is cleanup work to do. Otherwise, @@ -133,23 +116,25 @@ destroy_module_env(struct ret_env module_env) TEST_F(TEST_SUITE_NAME, test_wasm_mem_page_count) { struct ret_env tmp_module_env; - unsigned int num_normal_wasm = 9; - unsigned int num_error_wasm = 10; - const char *wasm_file_normal[num_normal_wasm] = { + const char *wasm_file_normal[9] = { "/wasm_mem_page_01.wasm", "/wasm_mem_page_02.wasm", "/wasm_mem_page_05.wasm", "/wasm_mem_page_07.wasm", "/wasm_mem_page_08.wasm", "/wasm_mem_page_09.wasm", "/wasm_mem_page_10.wasm", "/wasm_mem_page_12.wasm", "/wasm_mem_page_14.wasm" }; + unsigned int num_normal_wasm = + sizeof(wasm_file_normal) / sizeof(wasm_file_normal[0]); - const char *wasm_file_error[num_error_wasm] = { + const char *wasm_file_error[10] = { "/wasm_mem_page_03.wasm", "/wasm_mem_page_04.wasm", "/wasm_mem_page_06.wasm", "/wasm_mem_page_11.wasm", "/wasm_mem_page_13.wasm", "/wasm_mem_page_15.wasm", "/wasm_mem_page_16.wasm", "/wasm_mem_page_17.wasm", "/wasm_mem_page_18.wasm", "/wasm_mem_page_19.wasm" }; + unsigned int num_error_wasm = + sizeof(wasm_file_error) / sizeof(wasm_file_error[0]); // Test normal wasm file. for (int i = 0; i < num_normal_wasm; i++) { diff --git a/tests/unit/linux-perf/CMakeLists.txt b/tests/unit/linux-perf/CMakeLists.txt index e5e2d5692..6e487836e 100644 --- a/tests/unit/linux-perf/CMakeLists.txt +++ b/tests/unit/linux-perf/CMakeLists.txt @@ -24,7 +24,7 @@ set (WAMR_BUILD_DUMP_CALL_STACK 1) include (../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include (${IWASM_DIR}/compilation/iwasm_compl.cmake) @@ -32,9 +32,4 @@ include (${IWASM_DIR}/compilation/iwasm_compl.cmake) add_executable (linux_perf_test test_sort_func_ptrs.cc) target_compile_options(linux_perf_test PUBLIC -fpermissive) target_link_libraries(linux_perf_test ${LLVM_AVAILABLE_LIBS} gtest_main ) -target_link_options(linux_perf_test - PUBLIC - LINKER:--unresolved-symbols=ignore-all -) - gtest_discover_tests(linux_perf_test) diff --git a/tests/unit/linux-perf/test_sort_func_ptrs.cc b/tests/unit/linux-perf/test_sort_func_ptrs.cc index 68f4b850f..45380267f 100644 --- a/tests/unit/linux-perf/test_sort_func_ptrs.cc +++ b/tests/unit/linux-perf/test_sort_func_ptrs.cc @@ -33,7 +33,7 @@ sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size) unsigned i; content_len = (uint64)sizeof(struct func_info) * module->func_count; - sorted_func_ptrs = wasm_runtime_malloc(content_len); + sorted_func_ptrs = (struct func_info *)wasm_runtime_malloc(content_len); if (!sorted_func_ptrs) { snprintf(error_buf, error_buf_size, "allocate memory failed when creating perf map"); @@ -63,23 +63,17 @@ wasm_runtime_free(void* ptr) return free(ptr); } -int -b_memcpy_s(void *s1, unsigned int s1max, const void *s2, unsigned int n) -{ - return memcpy(s1, s2, n); -} } TEST(TestSortFuncPtrs, qsort) { - void *p = sort_func_ptrs; - ASSERT_NE(p, nullptr); + ASSERT_NE(sort_func_ptrs, nullptr); void *funcs[5] = { (void *)0x1024, (void *)0x10, (void *)0x24, (void *)0x102, (void *)0x4, }; - AOTModule module = { 0 }; + AOTModule module = {}; module.func_count = 5; module.func_ptrs = &funcs[0]; diff --git a/tests/unit/memory64/CMakeLists.txt b/tests/unit/memory64/CMakeLists.txt index b19c9d9cf..200e263eb 100644 --- a/tests/unit/memory64/CMakeLists.txt +++ b/tests/unit/memory64/CMakeLists.txt @@ -23,7 +23,7 @@ set(WAMR_BUILD_SHARED_MEMORY 1) include(../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/unit/running-modes/CMakeLists.txt b/tests/unit/running-modes/CMakeLists.txt index 3a5ca4745..4509b1add 100644 --- a/tests/unit/running-modes/CMakeLists.txt +++ b/tests/unit/running-modes/CMakeLists.txt @@ -26,15 +26,19 @@ set(WAMR_BUILD_LIBC_BUILTIN 1) set(WAMR_BUILD_MULTI_MODULE 0) set(WAMR_BUILD_LIBC_WASI 1) set(WAMR_BUILD_APP_FRAMEWORK 0) -set(WAMR_BUILD_JIT 1) -set(WAMR_BUILD_FAST_JIT 1) +set(WAMR_BUILD_AOT 1) +set(WAMR_BUILD_INTERP 1) +if(WAMR_BUILD_TARGET STREQUAL "x86_64") + set(WAMR_BUILD_JIT 1) + sset(WAMR_BUILD_FAST_JIT 1) +endif() set(WAMR_BUILD_REF_TYPES 1) # if only load this CMake other than load it as subdirectory include(../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/unit/running-modes/wasm_running_modes_test.cc b/tests/unit/running-modes/wasm_running_modes_test.cc index 5f370dd64..5dc4803c0 100644 --- a/tests/unit/running-modes/wasm_running_modes_test.cc +++ b/tests/unit/running-modes/wasm_running_modes_test.cc @@ -39,22 +39,6 @@ std::vector running_mode_supported = { Mode_Interp, class wasm_running_modes_test_suite : public testing::TestWithParam { private: - std::string get_binary_path() - { - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); - } - bool load_wasm_file(const char *wasm_file) { const char *file; @@ -199,7 +183,7 @@ class wasm_running_modes_test_suite : public testing::TestWithParam // Otherwise, this can be skipped. virtual void SetUp() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE_1 = strdup((CWD + TEST_WASM1).c_str()); WASM_FILE_2 = strdup((CWD + TEST_WASM2).c_str()); diff --git a/tests/unit/runtime-common/CMakeLists.txt b/tests/unit/runtime-common/CMakeLists.txt index 9ef07ff50..a46079b18 100644 --- a/tests/unit/runtime-common/CMakeLists.txt +++ b/tests/unit/runtime-common/CMakeLists.txt @@ -19,7 +19,7 @@ set (WAMR_BUILD_MULTI_MODULE 1) include(../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/unit/runtime-common/wasm_exec_env_test.cc b/tests/unit/runtime-common/wasm_exec_env_test.cc index 5c5b46499..8ee83053a 100644 --- a/tests/unit/runtime-common/wasm_exec_env_test.cc +++ b/tests/unit/runtime-common/wasm_exec_env_test.cc @@ -7,6 +7,7 @@ #include "gtest/gtest.h" #include "wasm_exec_env.h" +#include "wasm_runtime_common.h" class wasm_exec_env_test_suite : public testing::Test { @@ -43,3 +44,92 @@ TEST_F(wasm_exec_env_test_suite, wasm_exec_env_pop_jmpbuf) exec_env.jmpbuf_stack_top = nullptr; EXPECT_EQ(nullptr, wasm_exec_env_pop_jmpbuf(&exec_env)); } + +/* + * Test: exec_env_tls is cleared on early return from native stack overflow + * + * This test verifies that when wasm_runtime_call_wasm fails early due to + * native stack overflow check, exec_env_tls is properly cleared. Without + * this fix, subsequent calls with a different exec_env would fail with + * "invalid exec env" error. + * + * Bug scenario: + * 1. Call WASM with exec_env_A, TLS set to exec_env_A + * 2. Native stack overflow check fails, early return + * 3. TLS still points to exec_env_A (BUG: not cleared) + * 4. Destroy exec_env_A + * 5. Create exec_env_B, call WASM + * 6. Fails with "invalid exec env" because TLS != exec_env_B + */ +#ifdef OS_ENABLE_HW_BOUND_CHECK +/* Minimal WASM module: (module (func (export "test") (result i32) i32.const + * 42)) */ +static uint8_t test_wasm[] = { 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7f, 0x03, + 0x02, 0x01, 0x00, 0x07, 0x08, 0x01, 0x04, 0x74, + 0x65, 0x73, 0x74, 0x00, 0x00, 0x0a, 0x06, 0x01, + 0x04, 0x00, 0x41, 0x2a, 0x0b }; + +TEST_F(wasm_exec_env_test_suite, exec_env_tls_cleared_on_stack_overflow) +{ + WAMRRuntimeRAII<512 * 1024> runtime; + + /* Load and instantiate module */ + wasm_module_t module = + wasm_runtime_load(test_wasm, sizeof(test_wasm), nullptr, 0); + ASSERT_NE(module, nullptr); + + wasm_module_inst_t inst_a = + wasm_runtime_instantiate(module, 8192, 8192, nullptr, 0); + ASSERT_NE(inst_a, nullptr); + + wasm_exec_env_t exec_env_a = + wasm_runtime_create_exec_env(inst_a, 8192); + ASSERT_NE(exec_env_a, nullptr); + + /* Set native stack boundary high to trigger overflow check failure */ + uint8_t stack_var; + uint8_t *high_boundary = &stack_var + 0x100000; + wasm_runtime_set_native_stack_boundary(exec_env_a, high_boundary); + + /* Call should fail with native stack overflow */ + wasm_function_inst_t func = + wasm_runtime_lookup_function(inst_a, "test"); + ASSERT_NE(func, nullptr); + + uint32_t argv[1] = { 0 }; + bool result = wasm_runtime_call_wasm(exec_env_a, func, 0, argv); + EXPECT_FALSE(result); + + /* Verify TLS is cleared after failed call (this is the fix) */ + WASMExecEnv *tls = wasm_runtime_get_exec_env_tls(); + EXPECT_EQ(tls, nullptr); + + /* Clean up first instance */ + wasm_runtime_destroy_exec_env(exec_env_a); + wasm_runtime_deinstantiate(inst_a); + + /* Create second instance and exec_env */ + wasm_module_inst_t inst_b = + wasm_runtime_instantiate(module, 8192, 8192, nullptr, 0); + ASSERT_NE(inst_b, nullptr); + + wasm_exec_env_t exec_env_b = + wasm_runtime_create_exec_env(inst_b, 8192); + ASSERT_NE(exec_env_b, nullptr); + + /* This call should succeed (would fail without the fix) */ + func = wasm_runtime_lookup_function(inst_b, "test"); + ASSERT_NE(func, nullptr); + + argv[0] = 0; + result = wasm_runtime_call_wasm(exec_env_b, func, 0, argv); + EXPECT_TRUE(result); + EXPECT_EQ(argv[0], 42u); + + /* Clean up */ + wasm_runtime_destroy_exec_env(exec_env_b); + wasm_runtime_deinstantiate(inst_b); + wasm_runtime_unload(module); +} +#endif /* OS_ENABLE_HW_BOUND_CHECK */ diff --git a/tests/unit/runtime-common/wasm_runtime_common_test.cc b/tests/unit/runtime-common/wasm_runtime_common_test.cc index b1282091c..3e2fb1429 100644 --- a/tests/unit/runtime-common/wasm_runtime_common_test.cc +++ b/tests/unit/runtime-common/wasm_runtime_common_test.cc @@ -36,23 +36,6 @@ static std::string MAIN_AOT = "/main.aot"; static char *WASM_FILE_1; static char *AOT_FILE_1; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class wasm_runtime_common_test_suite : public testing::Test { protected: @@ -66,7 +49,7 @@ class wasm_runtime_common_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE_1 = strdup((CWD + MAIN_WASM).c_str()); AOT_FILE_1 = strdup((CWD + MAIN_AOT).c_str()); } diff --git a/tests/unit/runtime-common/wasm_runtime_init_test.cc b/tests/unit/runtime-common/wasm_runtime_init_test.cc index f7ff26ae4..5632ca4cf 100644 --- a/tests/unit/runtime-common/wasm_runtime_init_test.cc +++ b/tests/unit/runtime-common/wasm_runtime_init_test.cc @@ -48,23 +48,6 @@ static NativeSymbol native_symbols[] = { { "(ii)i" // the function prototype signature } }; -static std::string -get_binary_path() -{ - char cwd[1024]; - memset(cwd, 0, 1024); - - if (readlink("/proc/self/exe", cwd, 1024) <= 0) { - } - - char *path_end = strrchr(cwd, '/'); - if (path_end != NULL) { - *path_end = '\0'; - } - - return std::string(cwd); -} - class wasm_runtime_init_test_suite : public testing::Test { protected: @@ -78,7 +61,7 @@ class wasm_runtime_init_test_suite : public testing::Test static void SetUpTestCase() { - CWD = get_binary_path(); + CWD = get_test_binary_dir(); WASM_FILE_1 = strdup((CWD + MAIN_WASM).c_str()); AOT_FILE_1 = strdup((CWD + MAIN_AOT).c_str()); } diff --git a/tests/unit/shared-heap/CMakeLists.txt b/tests/unit/shared-heap/CMakeLists.txt index c275ac638..5de15b442 100644 --- a/tests/unit/shared-heap/CMakeLists.txt +++ b/tests/unit/shared-heap/CMakeLists.txt @@ -16,14 +16,34 @@ set(WAMR_BUILD_MEMORY64 0) set(WAMR_BUILD_SHARED_HEAP 1) # Compile wasm modules -add_subdirectory(wasm-apps) +set(WASI_SDK_DIR "/opt/wasi-sdk") +set(WASISDK_TOOLCHAIN "${WASI_SDK_DIR}/share/cmake/wasi-sdk.cmake") -if (WAMR_BUILD_MEMORY64 EQUAL 1) - add_subdirectory(wasm-apps/memory64) -endif () +include(ExternalProject) +ExternalProject_Add( + shared_heap_wasm_apps + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps + BUILD_ALWAYS YES + CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps -B build + -DWASI_SDK_PREFIX=${WASI_SDK_DIR} + -DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN} + BUILD_COMMAND ${CMAKE_COMMAND} --build build + INSTALL_COMMAND ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR} +) + +ExternalProject_Add( + shared_heap_wasm_apps_bulk_memory + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/bulk-memory + BUILD_ALWAYS YES + CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/bulk-memory -B build + -DWASI_SDK_PREFIX=${WASI_SDK_DIR} + -DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN} + BUILD_COMMAND ${CMAKE_COMMAND} --build build + INSTALL_COMMAND ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR} +) # if only load this CMake other than load it as subdirectory -include(../unit_common.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../unit_common.cmake) include(${IWASM_DIR}/compilation/iwasm_compl.cmake) diff --git a/tests/unit/shared-heap/shared_heap_test.cc b/tests/unit/shared-heap/shared_heap_test.cc index 434b4c389..a66cfc68b 100644 --- a/tests/unit/shared-heap/shared_heap_test.cc +++ b/tests/unit/shared-heap/shared_heap_test.cc @@ -3,13 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include "platform_internal.h" #include "test_helper.h" #include "gtest/gtest.h" #include "bh_read_file.h" #include "wasm_runtime_common.h" +#include "bh_platform.h" #include +#include class shared_heap_test : public testing::Test { @@ -32,13 +35,13 @@ static void destroy_module_env(struct ret_env module_env); static bool -load_wasm(char *wasm_file_tested, unsigned int app_heap_size, +load_wasm(const char *wasm_file_tested, unsigned int app_heap_size, ret_env &ret_module_env) { char *wasm_file = strdup(wasm_file_tested); unsigned int wasm_file_size = 0; unsigned int stack_size = 16 * 1024, heap_size = app_heap_size; - char error_buf[128] = { 0 }; + char error_buf[128] = {}; ret_module_env.wasm_file_buf = (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); @@ -141,11 +144,11 @@ fail0: TEST_F(shared_heap_test, test_shared_heap_basic) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr; - uint32 argv[1] = { 0 }; + uint32 argv[1] = {}; - args.size = 1024; + args.size = os_getpagesize(); shared_heap = wasm_runtime_create_shared_heap(&args); if (!shared_heap) { @@ -164,37 +167,45 @@ TEST_F(shared_heap_test, test_shared_heap_basic) TEST_F(shared_heap_test, test_shared_heap_malloc_fail) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr; - uint32 argv[1] = { 0 }; + uint32 argv[1] = {}; - args.size = 1024; + args.size = os_getpagesize(); shared_heap = wasm_runtime_create_shared_heap(&args); if (!shared_heap) { FAIL() << "Failed to create shared heap"; } - test_shared_heap(shared_heap, "test.wasm", "test_malloc_fail", 0, argv); + argv[0] = os_getpagesize(); + test_shared_heap(shared_heap, "test.wasm", "test_malloc_fail", 1, argv); EXPECT_EQ(1, argv[0]); - test_shared_heap(shared_heap, "test.aot", "test_malloc_fail", 0, argv); + argv[0] = os_getpagesize(); + test_shared_heap(shared_heap, "test.aot", "test_malloc_fail", 1, argv); EXPECT_EQ(1, argv[0]); - test_shared_heap(shared_heap, "test_chain.aot", "test_malloc_fail", 0, + argv[0] = os_getpagesize(); + test_shared_heap(shared_heap, "test_chain.aot", "test_malloc_fail", 1, argv); EXPECT_EQ(1, argv[0]); } TEST_F(shared_heap_test, test_preallocated_shared_heap_malloc_fail) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr; - uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE]; + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); /* create a preallocated shared heap */ - args.pre_allocated_addr = preallocated_buf; + args.pre_allocated_addr = preallocated_buf_ptr; args.size = BUF_SIZE; shared_heap = wasm_runtime_create_shared_heap(&args); if (!shared_heap) { @@ -220,9 +231,9 @@ TEST_F(shared_heap_test, test_preallocated_shared_heap_malloc_fail) TEST_F(shared_heap_test, test_preallocated_shared_runtime_api) { struct ret_env tmp_module_env; - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr; - uint32 argv[1] = { 0 }; + uint32 argv[1] = {}; void *native_ptr; uint64 offset, size; bool ret; @@ -252,7 +263,7 @@ TEST_F(shared_heap_test, test_preallocated_shared_runtime_api) } size = (uint64_t)UINT32_MAX + 0x2000; - printf("offset %lx size: %lx\n", offset, size); + printf("offset %llx size: %llx\n", offset, size); ASSERT_EQ(false, wasm_runtime_validate_app_addr( tmp_module_env.wasm_module_inst, offset, size)); @@ -263,7 +274,7 @@ TEST_F(shared_heap_test, test_preallocated_shared_runtime_api) ASSERT_EQ(true, wasm_runtime_validate_app_addr( tmp_module_env.wasm_module_inst, offset, size)); - ASSERT_EQ(native_ptr + size, + ASSERT_EQ((char *)native_ptr + size, wasm_runtime_addr_app_to_native(tmp_module_env.wasm_module_inst, offset + size)); @@ -277,7 +288,7 @@ static void create_test_shared_heap(uint8 *preallocated_buf, size_t size, WASMSharedHeap **shared_heap_res) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr; args.pre_allocated_addr = preallocated_buf; args.size = size; @@ -297,7 +308,7 @@ create_test_shared_heap_chain(uint8 *preallocated_buf, size_t size, uint8 *preallocated_buf2, size_t size2, WASMSharedHeap **shared_heap_chain) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr; args.pre_allocated_addr = preallocated_buf; args.size = size; @@ -324,11 +335,16 @@ create_test_shared_heap_chain(uint8 *preallocated_buf, size_t size, TEST_F(shared_heap_test, test_shared_heap_rmw) { WASMSharedHeap *shared_heap = nullptr; - uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE] = { 0 }; + uint32 argv[2] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; uint32 start1, end1; - create_test_shared_heap(preallocated_buf, BUF_SIZE, &shared_heap); + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + + create_test_shared_heap(preallocated_buf_ptr, BUF_SIZE, &shared_heap); /* app addr for shared heap */ start1 = UINT32_MAX - BUF_SIZE + 1; @@ -361,15 +377,24 @@ TEST_F(shared_heap_test, test_shared_heap_rmw) TEST_F(shared_heap_test, test_shared_heap_chain_rmw) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap_chain = nullptr; - uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE] = { 0 }, - preallocated_buf2[BUF_SIZE] = { 0 }; + uint32 argv[2] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; uint32 start1, end1, start2, end2; - create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2, - BUF_SIZE, &shared_heap_chain); + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); + + create_test_shared_heap_chain(preallocated_buf_ptr, BUF_SIZE, + preallocated_buf2_ptr, BUF_SIZE, + &shared_heap_chain); /* app addr for shared heap */ start1 = UINT32_MAX - 2 * BUF_SIZE + 1; @@ -410,15 +435,24 @@ TEST_F(shared_heap_test, test_shared_heap_chain_rmw) TEST_F(shared_heap_test, test_shared_heap_chain_rmw_bulk_memory) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap_chain = nullptr; - uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE] = { 0 }, - preallocated_buf2[BUF_SIZE] = { 0 }; + uint32 argv[3] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; uint32 start1, end1, start2, end2; - create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2, - BUF_SIZE, &shared_heap_chain); + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); + + create_test_shared_heap_chain(preallocated_buf_ptr, BUF_SIZE, + preallocated_buf2_ptr, BUF_SIZE, + &shared_heap_chain); /* app addr for shared heap */ start1 = UINT32_MAX - 2 * BUF_SIZE + 1; @@ -466,15 +500,24 @@ TEST_F(shared_heap_test, test_shared_heap_chain_rmw_bulk_memory) TEST_F(shared_heap_test, test_shared_heap_chain_rmw_bulk_memory_oob) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap_chain = nullptr; - uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE] = { 0 }, - preallocated_buf2[BUF_SIZE] = { 0 }; + uint32 argv[3] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; uint32 start1, end1, start2, end2; - create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2, - BUF_SIZE, &shared_heap_chain); + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); + + create_test_shared_heap_chain(preallocated_buf_ptr, BUF_SIZE, + preallocated_buf2_ptr, BUF_SIZE, + &shared_heap_chain); /* app addr for shared heap */ start1 = UINT32_MAX - 2 * BUF_SIZE + 1; @@ -551,11 +594,20 @@ TEST_F(shared_heap_test, test_shared_heap_chain_rmw_bulk_memory_oob) TEST_F(shared_heap_test, test_shared_heap_rmw_oob) { WASMSharedHeap *shared_heap = nullptr; - uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE]; + uint32 argv[2] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; uint32 start1, end1, start2, end2; - create_test_shared_heap(preallocated_buf, BUF_SIZE, &shared_heap); + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); + + create_test_shared_heap(preallocated_buf_ptr, BUF_SIZE, &shared_heap); /* app addr for shared heap */ start1 = UINT32_MAX - BUF_SIZE + 1; @@ -585,12 +637,22 @@ TEST_F(shared_heap_test, test_shared_heap_rmw_oob) TEST_F(shared_heap_test, test_shared_heap_chain_rmw_oob) { WASMSharedHeap *shared_heap_chain = nullptr; - uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE]; + uint32 argv[2] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; uint32 start1, end1, start2, end2; - create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2, - BUF_SIZE, &shared_heap_chain); + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); + + create_test_shared_heap_chain(preallocated_buf_ptr, BUF_SIZE, + preallocated_buf2_ptr, BUF_SIZE, + &shared_heap_chain); /* app addr for shared heap */ start1 = UINT32_MAX - 2 * BUF_SIZE + 1; @@ -618,13 +680,22 @@ TEST_F(shared_heap_test, test_shared_heap_chain_rmw_oob) TEST_F(shared_heap_test, test_shared_heap_chain_memory64_rmw) { WASMSharedHeap *shared_heap_chain = nullptr; - uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE] = { 0 }, - preallocated_buf2[BUF_SIZE] = { 0 }; + uint32 argv[3] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; uint64 start1, end1, start2, end2; - create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2, - BUF_SIZE, &shared_heap_chain); + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); + + create_test_shared_heap_chain(preallocated_buf_ptr, BUF_SIZE, + preallocated_buf2_ptr, BUF_SIZE, + &shared_heap_chain); /* app addr for shared heap */ start1 = UINT64_MAX - 2 * BUF_SIZE + 1; @@ -666,12 +737,22 @@ TEST_F(shared_heap_test, test_shared_heap_chain_memory64_rmw) TEST_F(shared_heap_test, test_shared_heap_chain_memory64_rmw_oob) { WASMSharedHeap *shared_heap_chain = nullptr; - uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE]; + uint32 argv[3] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; uint64 start1, end1, start2, end2; - create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2, - BUF_SIZE, &shared_heap_chain); + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); + + create_test_shared_heap_chain(preallocated_buf_ptr, BUF_SIZE, + preallocated_buf2_ptr, BUF_SIZE, + &shared_heap_chain); /* app addr for shared heap */ start1 = UINT64_MAX - 2 * BUF_SIZE + 1; @@ -726,9 +807,9 @@ static NativeSymbol g_test_native_symbols[] = { TEST_F(shared_heap_test, test_addr_conv) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr; - uint32 argv[1] = { 0 }; + uint32 argv[1] = {}; bool ret = false; ret = wasm_native_register_natives("env", g_test_native_symbols, @@ -755,11 +836,15 @@ TEST_F(shared_heap_test, test_addr_conv) TEST_F(shared_heap_test, test_addr_conv_pre_allocated_oob) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr; - uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(), + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(), app_addr = 0xFFFFFFFF - BUF_SIZE; - uint8 preallocated_buf[BUF_SIZE]; + uint8 *preallocated_buf_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); bool ret = false; /* create a preallocated shared heap */ @@ -769,7 +854,7 @@ TEST_F(shared_heap_test, test_addr_conv_pre_allocated_oob) FAIL() << "Failed to register natives"; } - args.pre_allocated_addr = preallocated_buf; + args.pre_allocated_addr = preallocated_buf_ptr; args.size = BUF_SIZE; shared_heap = wasm_runtime_create_shared_heap(&args); if (!shared_heap) { @@ -795,11 +880,15 @@ TEST_F(shared_heap_test, test_addr_conv_pre_allocated_oob) TEST_F(shared_heap_test, test_shared_heap_chain) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr, *shared_heap_chain = nullptr; - uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE]; + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); bool ret = false; ret = wasm_native_register_natives("env", g_test_native_symbols, @@ -816,7 +905,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain) /* create a preallocated shared heap */ memset(&args, 0, sizeof(args)); - args.pre_allocated_addr = preallocated_buf; + args.pre_allocated_addr = preallocated_buf_ptr; args.size = BUF_SIZE; shared_heap2 = wasm_runtime_create_shared_heap(&args); if (!shared_heap2) { @@ -838,7 +927,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain) TEST_F(shared_heap_test, test_shared_heap_chain_create_fail) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr, *shared_heap_chain = nullptr; @@ -861,11 +950,15 @@ TEST_F(shared_heap_test, test_shared_heap_chain_create_fail) TEST_F(shared_heap_test, test_shared_heap_chain_create_fail2) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr, *shared_heap_chain = nullptr; - uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE]; + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); struct ret_env tmp_module_env; args.size = 1024; @@ -875,7 +968,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain_create_fail2) } memset(&args, 0, sizeof(args)); - args.pre_allocated_addr = preallocated_buf; + args.pre_allocated_addr = preallocated_buf_ptr; args.size = BUF_SIZE; shared_heap2 = wasm_runtime_create_shared_heap(&args); if (!shared_heap2) { @@ -903,11 +996,19 @@ TEST_F(shared_heap_test, test_shared_heap_chain_create_fail2) TEST_F(shared_heap_test, test_shared_heap_chain_create_fail3) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr, *shared_heap3 = nullptr, *shared_heap_chain = nullptr; - uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE]; + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); args.size = 1024; shared_heap = wasm_runtime_create_shared_heap(&args); @@ -916,7 +1017,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain_create_fail3) } memset(&args, 0, sizeof(args)); - args.pre_allocated_addr = preallocated_buf; + args.pre_allocated_addr = preallocated_buf_ptr; args.size = BUF_SIZE; shared_heap2 = wasm_runtime_create_shared_heap(&args); if (!shared_heap2) { @@ -930,7 +1031,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain_create_fail3) } memset(&args, 0, sizeof(args)); - args.pre_allocated_addr = preallocated_buf2; + args.pre_allocated_addr = preallocated_buf2_ptr; args.size = BUF_SIZE; shared_heap3 = wasm_runtime_create_shared_heap(&args); if (!shared_heap3) { @@ -948,11 +1049,19 @@ TEST_F(shared_heap_test, test_shared_heap_chain_create_fail3) TEST_F(shared_heap_test, test_shared_heap_chain_unchain) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr, *shared_heap3 = nullptr, *shared_heap_chain = nullptr; - uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE]; + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + uint8 *preallocated_buf2_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + std::vector preallocated_buf2(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + preallocated_buf2_ptr = preallocated_buf2.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + ASSERT_NE(preallocated_buf2_ptr, nullptr); args.size = 1024; shared_heap = wasm_runtime_create_shared_heap(&args); @@ -961,7 +1070,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain_unchain) } memset(&args, 0, sizeof(args)); - args.pre_allocated_addr = preallocated_buf; + args.pre_allocated_addr = preallocated_buf_ptr; args.size = BUF_SIZE; shared_heap2 = wasm_runtime_create_shared_heap(&args); if (!shared_heap2) { @@ -975,7 +1084,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain_unchain) } memset(&args, 0, sizeof(args)); - args.pre_allocated_addr = preallocated_buf2; + args.pre_allocated_addr = preallocated_buf2_ptr; args.size = BUF_SIZE; shared_heap3 = wasm_runtime_create_shared_heap(&args); if (!shared_heap3) { @@ -998,13 +1107,167 @@ TEST_F(shared_heap_test, test_shared_heap_chain_unchain) wasm_runtime_unchain_shared_heaps(shared_heap_chain, true)); } -TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv) +TEST_F(shared_heap_test, test_shared_heap_chain_reset_runtime_managed) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr, *shared_heap_chain = nullptr; - uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE]; + uint8 buf_size = 64; + uint64 offset = 0, offset_after_reset = 0; + void *native_ptr = nullptr, *native_ptr_after_reset = nullptr; + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + struct ret_env tmp_module_env; + + args.size = 4096; + shared_heap = wasm_runtime_create_shared_heap(&args); + if (!shared_heap) { + FAIL() << "Failed to create shared heap"; + } + + args.size = BUF_SIZE; + args.pre_allocated_addr = preallocated_buf_ptr; + shared_heap2 = wasm_runtime_create_shared_heap(&args); + if (!shared_heap2) { + FAIL() << "Failed to create second shared heap"; + } + + shared_heap_chain = + wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2); + if (!shared_heap_chain) { + FAIL() << "Create shared heap chain failed.\n"; + } + + if (!load_wasm((char *)"test.wasm", 0, tmp_module_env)) { + FAIL() << "Failed to load wasm file\n"; + } + + if (!wasm_runtime_attach_shared_heap(tmp_module_env.wasm_module_inst, + shared_heap_chain)) { + destroy_module_env(tmp_module_env); + FAIL() << "Failed to attach shared heap chain"; + } + + offset = wasm_runtime_shared_heap_malloc(tmp_module_env.wasm_module_inst, + buf_size, &native_ptr); + ASSERT_NE(0u, offset); + ASSERT_NE(nullptr, native_ptr); + + memset(native_ptr, 0x5A, buf_size); + for (uint8 i = 0; i < buf_size; i++) { + EXPECT_EQ(0x5A, *((uint8 *)native_ptr + i)); + } + + wasm_runtime_detach_shared_heap(tmp_module_env.wasm_module_inst); + EXPECT_TRUE(wasm_runtime_reset_shared_heap_chain(shared_heap_chain)); + + if (!load_wasm((char *)"test.wasm", 0, tmp_module_env)) { + FAIL() << "Failed to load wasm file after reset\n"; + } + + if (!wasm_runtime_attach_shared_heap(tmp_module_env.wasm_module_inst, + shared_heap_chain)) { + destroy_module_env(tmp_module_env); + FAIL() << "Failed to attach shared heap chain after reset"; + } + + offset_after_reset = wasm_runtime_shared_heap_malloc( + tmp_module_env.wasm_module_inst, buf_size, &native_ptr_after_reset); + ASSERT_NE(0u, offset_after_reset); + ASSERT_NE(nullptr, native_ptr_after_reset); + + EXPECT_EQ(offset, offset_after_reset); + EXPECT_EQ(native_ptr, native_ptr_after_reset); + + /* Only on some platform, the os_mmap will memset the memory to 0 + for (uint8 i = 0; i < buf_size; i++) { + EXPECT_EQ(0, *((uint8 *)native_ptr_after_reset + i)); + } + */ + + wasm_runtime_detach_shared_heap(tmp_module_env.wasm_module_inst); + destroy_module_env(tmp_module_env); +} + +TEST_F(shared_heap_test, test_shared_heap_chain_reset_preallocated) +{ + SharedHeapInitArgs args = {}; + WASMSharedHeap *shared_heap = nullptr; + uint32 BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); + uint8 set_val = 0xA5; + + args.pre_allocated_addr = preallocated_buf_ptr; + args.size = BUF_SIZE; + shared_heap = wasm_runtime_create_shared_heap(&args); + if (!shared_heap) { + FAIL() << "Create preallocated shared heap failed.\n"; + } + + memset(preallocated_buf_ptr, set_val, BUF_SIZE); + for (uint32 i = 0; i < BUF_SIZE; i++) { + EXPECT_EQ(set_val, preallocated_buf[i]); + } + + EXPECT_TRUE(wasm_runtime_reset_shared_heap_chain(shared_heap)); + + for (uint32 i = 0; i < BUF_SIZE; i++) { + EXPECT_EQ(0, preallocated_buf[i]); + } +} + +TEST_F(shared_heap_test, test_shared_heap_chain_reset_attached_fail) +{ + SharedHeapInitArgs args = {}; + WASMSharedHeap *shared_heap = nullptr; + struct ret_env module_env = {}; + bool ret; + + args.size = 1024; + shared_heap = wasm_runtime_create_shared_heap(&args); + if (!shared_heap) { + FAIL() << "Failed to create shared heap"; + } + + ret = load_wasm((char *)"test.wasm", 0, module_env); + if (!ret) { + FAIL() << "Failed to load wasm"; + } + + ret = wasm_runtime_attach_shared_heap(module_env.wasm_module_inst, + shared_heap); + if (!ret) { + destroy_module_env(module_env); + FAIL() << "Failed to attach shared heap"; + } + + EXPECT_FALSE(wasm_runtime_reset_shared_heap_chain(shared_heap)); + + wasm_runtime_detach_shared_heap(module_env.wasm_module_inst); + destroy_module_env(module_env); + + EXPECT_TRUE(wasm_runtime_reset_shared_heap_chain(shared_heap)); +} + +TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv) +{ + SharedHeapInitArgs args = {}; + WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr, + *shared_heap_chain = nullptr; + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); bool ret = false; ret = wasm_native_register_natives("env", g_test_native_symbols, @@ -1021,7 +1284,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv) /* create a preallocated shared heap */ memset(&args, 0, sizeof(args)); - args.pre_allocated_addr = preallocated_buf; + args.pre_allocated_addr = preallocated_buf_ptr; args.size = BUF_SIZE; shared_heap2 = wasm_runtime_create_shared_heap(&args); if (!shared_heap2) { @@ -1057,11 +1320,15 @@ TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv) TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv_oob) { - SharedHeapInitArgs args = { 0 }; + SharedHeapInitArgs args = {}; WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr, *shared_heap_chain = nullptr; - uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(); - uint8 preallocated_buf[BUF_SIZE]; + uint32 argv[1] = {}, BUF_SIZE = os_getpagesize(); + uint8 *preallocated_buf_ptr = nullptr; + ASSERT_GT(BUF_SIZE, 0u); + std::vector preallocated_buf(BUF_SIZE); + preallocated_buf_ptr = preallocated_buf.data(); + ASSERT_NE(preallocated_buf_ptr, nullptr); bool ret = false; ret = wasm_native_register_natives("env", g_test_native_symbols, @@ -1070,7 +1337,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv_oob) FAIL() << "Failed to register natives"; } - args.size = 4096; + args.size = os_getpagesize(); shared_heap = wasm_runtime_create_shared_heap(&args); if (!shared_heap) { FAIL() << "Failed to create shared heap"; @@ -1078,7 +1345,7 @@ TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv_oob) /* create a preallocated shared heap */ memset(&args, 0, sizeof(args)); - args.pre_allocated_addr = preallocated_buf; + args.pre_allocated_addr = preallocated_buf_ptr; args.size = BUF_SIZE; shared_heap2 = wasm_runtime_create_shared_heap(&args); if (!shared_heap2) { @@ -1092,14 +1359,14 @@ TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv_oob) } /* test wasm */ - argv[0] = 0xFFFFFFFF - BUF_SIZE - 4096; + argv[0] = 0xFFFFFFFF - BUF_SIZE - os_getpagesize(); EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain, "test_addr_conv.wasm", "test_preallocated", 1, argv), "Exception: out of bounds memory access"); /* test aot */ - argv[0] = 0xFFFFFFFF - BUF_SIZE - 4096; + argv[0] = 0xFFFFFFFF - BUF_SIZE - os_getpagesize(); EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain, "test_addr_conv_chain.aot", "test_preallocated", 1, argv), diff --git a/tests/unit/shared-heap/wasm-apps/CMakeLists.txt b/tests/unit/shared-heap/wasm-apps/CMakeLists.txt index 985cf18ae..b0482888f 100644 --- a/tests/unit/shared-heap/wasm-apps/CMakeLists.txt +++ b/tests/unit/shared-heap/wasm-apps/CMakeLists.txt @@ -5,105 +5,67 @@ cmake_minimum_required(VERSION 3.14) project(wasm-apps) set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) -set(WAMRC_ROOT_DIR ${WAMR_ROOT_DIR}/wamr-compiler/build) -set(CMAKE_SYSTEM_PROCESSOR wasm32) -set(CMAKE_SYSROOT ${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot) - -if (NOT DEFINED WASI_SDK_DIR) - set(WASI_SDK_DIR "/opt/wasi-sdk") -endif () - -set(CMAKE_C_FLAGS "-nostdlib -pthread -Qunused-arguments") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -z stack-size=8192 -nostdlib -O0") -set(CMAKE_C_COMPILER_TARGET "wasm32") -set(CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang") - -set(DEFINED_SYMBOLS - "${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt") - -set(CMAKE_EXE_LINKER_FLAGS - "-Wl,--no-entry \ - -Wl,--initial-memory=65536 \ - -Wl,--export-all \ - -Wl,--allow-undefined" - ) +# Find WAMRC +set(WAMRC_ROOT_DIR ${WAMR_ROOT_DIR}/wamr-compiler) +find_program(WAMRC_BIN wamrc HINTS ${WAMRC_ROOT_DIR}/build REQUIRED) +# Set architecture-specific WAMRC flags if (WAMR_BUILD_TARGET STREQUAL "X86_32") - set (WAMR_COMPILER_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap --target=i386) - set (WAMR_COMPILER_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain --target=i386) + set(WAMRC_SHARED_HEAP_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap --target=i386) + set(WAMRC_SHARED_HEAP_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain --target=i386) else () - set (WAMR_COMPILER_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap) - set (WAMR_COMPILER_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain) + set(WAMRC_SHARED_HEAP_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap) + set(WAMRC_SHARED_HEAP_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain) endif () -function(copy_wasm TARGET_NAME) - add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} - ${CMAKE_CURRENT_BINARY_DIR}/../ - COMMENT "Copy ${TARGET_NAME} to the same directory of google test" - ) -endfunction() - -function(compile_and_copy_aot_from TARGET_NAME) - string(REPLACE ".wasm" ".aot" AOT_TARGET ${TARGET_NAME}) - string(REPLACE ".wasm" "_chain.aot" AOT_CHAIN_TARGET ${TARGET_NAME}) - - add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_FLAGS} - -o ${AOT_TARGET} - ${TARGET_NAME} - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/${AOT_TARGET} - ${CMAKE_CURRENT_BINARY_DIR}/../ - COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_CHAIN_FLAGS} - -o ${AOT_CHAIN_TARGET} - ${TARGET_NAME} - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/${AOT_CHAIN_TARGET} - ${CMAKE_CURRENT_BINARY_DIR}/../ - COMMENT "Compile and copy ${AOT_TARGET} to the same directory of google test" - ) -endfunction() - +# +# C -> Wasm +# add_executable(test.wasm test.c) -target_link_libraries(test.wasm) -copy_wasm(test.wasm) -compile_and_copy_aot_from(test.wasm) +target_compile_options(test.wasm PUBLIC -nostdlib -O0 -pthread) +target_link_options(test.wasm PRIVATE + -nostdlib + LINKER:--no-entry + LINKER:--initial-memory=65536 + LINKER:--allow-undefined + LINKER:--export-all + -z stack-size=1024 +) add_executable(test_addr_conv.wasm test_addr_conv.c) -target_link_libraries(test_addr_conv.wasm) -copy_wasm(test_addr_conv.wasm) -compile_and_copy_aot_from(test_addr_conv.wasm) - -# copy and compile aot for bulk memory test -set(SOURCE_WASM ${CMAKE_CURRENT_SOURCE_DIR}/bulk-memory/test_bulk_memory.wasm) -set(BUILD_WASM ${CMAKE_CURRENT_BINARY_DIR}/../test_bulk_memory.wasm) -set(OUTPUT_AOT ${CMAKE_CURRENT_BINARY_DIR}/../test_bulk_memory.aot) -set(OUTPUT_CHAIN_AOT ${CMAKE_CURRENT_BINARY_DIR}/../test_bulk_memory_chain.aot) - -add_custom_command( - OUTPUT ${BUILD_WASM} - COMMAND ${CMAKE_COMMAND} -E copy - ${SOURCE_WASM} - ${BUILD_WASM} - DEPENDS ${SOURCE_WASM} - COMMENT "Copying bulk memory WASM to build directory" +target_compile_options(test_addr_conv.wasm PUBLIC -nostdlib -O0 -pthread) +target_link_options(test_addr_conv.wasm PRIVATE + -nostdlib + LINKER:--no-entry + LINKER:--initial-memory=65536 + LINKER:--allow-undefined + LINKER:--export-all + -z stack-size=1024 ) -add_custom_command( - OUTPUT ${OUTPUT_AOT} - COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_FLAGS} - -o ${OUTPUT_AOT} - ${BUILD_WASM} - COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_CHAIN_FLAGS} - -o ${OUTPUT_CHAIN_AOT} - ${BUILD_WASM} - DEPENDS ${BUILD_WASM} - COMMENT "Compiling bulk memory AOT from copied WASM" +# Compile AOT files (combined target) +add_custom_target(compile_aot ALL + COMMAND ${WAMRC_BIN} ${WAMRC_SHARED_HEAP_FLAGS} -o test.aot test.wasm + COMMAND ${WAMRC_BIN} ${WAMRC_SHARED_HEAP_CHAIN_FLAGS} -o test_chain.aot test.wasm + COMMAND ${WAMRC_BIN} ${WAMRC_SHARED_HEAP_FLAGS} -o test_addr_conv.aot test_addr_conv.wasm + COMMAND ${WAMRC_BIN} ${WAMRC_SHARED_HEAP_CHAIN_FLAGS} -o test_addr_conv_chain.aot test_addr_conv.wasm + DEPENDS test.wasm test_addr_conv.wasm + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) -add_custom_target(compile_bulk_memory_aot ALL - DEPENDS ${OUTPUT_AOT} +# Install WASM files +set(WASM_FILES + ${CMAKE_CURRENT_BINARY_DIR}/test.wasm + ${CMAKE_CURRENT_BINARY_DIR}/test_addr_conv.wasm ) +install(FILES ${WASM_FILES} DESTINATION .) + +# Install AOT files +set(AOT_FILES + ${CMAKE_CURRENT_BINARY_DIR}/test.aot + ${CMAKE_CURRENT_BINARY_DIR}/test_chain.aot + ${CMAKE_CURRENT_BINARY_DIR}/test_addr_conv.aot + ${CMAKE_CURRENT_BINARY_DIR}/test_addr_conv_chain.aot +) +install(FILES ${AOT_FILES} DESTINATION .) diff --git a/tests/unit/shared-heap/wasm-apps/bulk-memory/CMakeLists.txt b/tests/unit/shared-heap/wasm-apps/bulk-memory/CMakeLists.txt new file mode 100644 index 000000000..8dd0deca7 --- /dev/null +++ b/tests/unit/shared-heap/wasm-apps/bulk-memory/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright (C) 2024 Xiaomi Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) +project(wasm-apps-bulk-memory) + +# Find WAMRC +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..) +set(WAMRC_ROOT_DIR ${WAMR_ROOT_DIR}/wamr-compiler) +find_program(WAMRC_BIN wamrc HINTS ${WAMRC_ROOT_DIR}/build REQUIRED) + +# Set architecture-specific WAMRC flags +if (WAMR_BUILD_TARGET STREQUAL "X86_32") + set(WAMRC_SHARED_HEAP_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap --target=i386) + set(WAMRC_SHARED_HEAP_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain --target=i386) +else () + set(WAMRC_SHARED_HEAP_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap) + set(WAMRC_SHARED_HEAP_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain) +endif () + +# Compile AOT files (combined target) +add_custom_target(compile_aot ALL + COMMAND ${WAMRC_BIN} ${WAMRC_SHARED_HEAP_FLAGS} -o test_bulk_memory.aot ${CMAKE_CURRENT_SOURCE_DIR}/test_bulk_memory.wasm + COMMAND ${WAMRC_BIN} ${WAMRC_SHARED_HEAP_CHAIN_FLAGS} -o test_bulk_memory_chain.aot ${CMAKE_CURRENT_SOURCE_DIR}/test_bulk_memory.wasm + DEPENDS test_bulk_memory.wasm + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +# Install WASM file +set(WASM_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/test_bulk_memory.wasm +) +install(FILES ${WASM_FILES} DESTINATION .) + +# Install AOT files +set(AOT_FILES + ${CMAKE_CURRENT_BINARY_DIR}/test_bulk_memory.aot + ${CMAKE_CURRENT_BINARY_DIR}/test_bulk_memory_chain.aot +) +install(FILES ${AOT_FILES} DESTINATION .) diff --git a/tests/unit/shared-heap/wasm-apps/memory64/CMakeLists.txt b/tests/unit/shared-heap/wasm-apps/memory64/CMakeLists.txt index a82788b58..912990a89 100644 --- a/tests/unit/shared-heap/wasm-apps/memory64/CMakeLists.txt +++ b/tests/unit/shared-heap/wasm-apps/memory64/CMakeLists.txt @@ -5,64 +5,45 @@ cmake_minimum_required(VERSION 3.14) project(wasm-apps-wasm64) set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..) -set(WAMRC_ROOT_DIR ${WAMR_ROOT_DIR}/wamr-compiler/build) -set(CMAKE_SYSTEM_PROCESSOR wasm64) -set(CMAKE_SYSROOT ${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot) +# Find WAMRC +set(WAMRC_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) +find_program(WAMRC_BIN wamrc HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../../../../wamr-compiler/build REQUIRED) -if (NOT DEFINED WASI_SDK_DIR) - set(WASI_SDK_DIR "/opt/wasi-sdk") -endif () - -set(CMAKE_C_FLAGS "-nostdlib -pthread -Qunused-arguments") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -z stack-size=8192 -nostdlib -O0 --target=wasm64") -set(CMAKE_C_COMPILER_TARGET "wasm64") -set(CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang") - -set(DEFINED_SYMBOLS - "${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt") - -set(CMAKE_EXE_LINKER_FLAGS - "-Wl,--no-entry \ - -Wl,--initial-memory=65536 \ - -Wl,--export-all \ - -Wl,--allow-undefined" - ) - -set (WAMR_COMPILER_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap) -set (WAMR_COMPILER_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain) - -function(copy_wasm TARGET_NAME) - add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} - ${CMAKE_CURRENT_BINARY_DIR}/../../ - COMMENT "Copy ${TARGET_NAME} to the same directory of google test" - ) -endfunction() - -function(compile_and_copy_aot_from TARGET_NAME) - string(REPLACE ".wasm" ".aot" AOT_TARGET ${TARGET_NAME}) - string(REPLACE ".wasm" "_chain.aot" AOT_CHAIN_TARGET ${TARGET_NAME}) - - add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_FLAGS} - -o ${AOT_TARGET} - ${TARGET_NAME} - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/${AOT_TARGET} - ${CMAKE_CURRENT_BINARY_DIR}/../../ - COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_CHAIN_FLAGS} - -o ${AOT_CHAIN_TARGET} - ${TARGET_NAME} - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/${AOT_CHAIN_TARGET} - ${CMAKE_CURRENT_BINARY_DIR}/../../ - COMMENT "Compile and copy ${AOT_TARGET} ${AOT_CHAIN_TARGET} to the same directory of google test" - ) -endfunction() +# Set WAMRC flags for memory64 +set(WAMRC_SHARED_HEAP_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap) +set(WAMRC_SHARED_HEAP_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain) +# +# C -> Wasm +# add_executable(test64.wasm ../test.c) -target_link_libraries(test64.wasm) -copy_wasm(test64.wasm) -compile_and_copy_aot_from(test64.wasm) +target_compile_options(test64.wasm PUBLIC -nostdlib -O0 -pthread --target=wasm64) +target_link_options(test64.wasm PRIVATE + -nostdlib + LINKER:--no-entry + LINKER:--initial-memory=65536 + LINKER:--export-all + LINKER:--allow-undefined +) + +# Compile AOT files (combined target) +add_custom_target(compile_aot ALL + COMMAND ${WAMRC_BIN} ${WAMRC_SHARED_HEAP_FLAGS} -o test64.aot test64.wasm + COMMAND ${WAMRC_BIN} ${WAMRC_SHARED_HEAP_CHAIN_FLAGS} -o test64_chain.aot test64.wasm + DEPENDS test64.wasm + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +# Install WASM file +set(WASM_FILES + ${CMAKE_CURRENT_BINARY_DIR}/test64.wasm +) +install(FILES ${WASM_FILES} DESTINATION .) + +# Install AOT files +set(AOT_FILES + ${CMAKE_CURRENT_BINARY_DIR}/test64.aot + ${CMAKE_CURRENT_BINARY_DIR}/test64_chain.aot +) +install(FILES ${AOT_FILES} DESTINATION .) diff --git a/tests/unit/shared-heap/wasm-apps/test.c b/tests/unit/shared-heap/wasm-apps/test.c index 66df21c1b..a01bba294 100644 --- a/tests/unit/shared-heap/wasm-apps/test.c +++ b/tests/unit/shared-heap/wasm-apps/test.c @@ -22,9 +22,9 @@ test() } int -test_malloc_fail() +test_malloc_fail(int size) { - int *ptr = (int *)shared_heap_malloc(8192); + int *ptr = (int *)shared_heap_malloc(size + 1); if (ptr == NULL) { return 1; diff --git a/tests/unit/smart-tests/CMakeLists.txt b/tests/unit/smart-tests/CMakeLists.txt new file mode 100644 index 000000000..c61fc0a86 --- /dev/null +++ b/tests/unit/smart-tests/CMakeLists.txt @@ -0,0 +1,4 @@ +# Enhanced Unit Test CMakeLists.txt +cmake_minimum_required(VERSION 3.12) + +add_subdirectory(interpreter) diff --git a/tests/unit/smart-tests/interpreter/CMakeLists.txt b/tests/unit/smart-tests/interpreter/CMakeLists.txt new file mode 100644 index 000000000..34ce97db5 --- /dev/null +++ b/tests/unit/smart-tests/interpreter/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +project (smart-test-interpreter) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) +# add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1) + +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) + +include (../../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} +) + +add_executable (smart_test_classic-interpreter ${unit_test_sources}) +target_compile_definitions(smart_test_classic-interpreter PUBLIC -DWAMR_BUILD_FAST_INTERP=0) +target_link_libraries (smart_test_classic-interpreter gtest_main) + +add_executable (smart_test_fast-interpreter ${unit_test_sources}) +target_compile_definitions(smart_test_fast-interpreter PUBLIC -DWAMR_BUILD_FAST_INTERP=1) +target_link_libraries (smart_test_fast-interpreter gtest_main) + +# Copy WASM files to build directory for classic interpreter +# fast interpreter uses the same WASM files +add_custom_command(TARGET smart_test_classic-interpreter POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/*.wasm + ${CMAKE_CURRENT_BINARY_DIR}/ + COMMENT "Copy test wasm files to the directory of google test" +) + +gtest_discover_tests(smart_test_classic-interpreter) +gtest_discover_tests(smart_test_fast-interpreter) diff --git a/tests/unit/smart-tests/interpreter/interpreter_test_enhance.cc b/tests/unit/smart-tests/interpreter/interpreter_test_enhance.cc new file mode 100644 index 000000000..8f0ccc09f --- /dev/null +++ b/tests/unit/smart-tests/interpreter/interpreter_test_enhance.cc @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2024 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + + #include "test_helper.h" + #include "gtest/gtest.h" + + #include + #include + #include "wasm_runtime_common.h" + #include "wasm_runtime.h" + #include "wasm_interp.h" + #include "wasm_loader.h" + + static std::string CWD; + static std::string WASM_FILE; + static constexpr uint32_t STACK_SIZE = 8092; + static constexpr uint32_t HEAP_SIZE = 8092; + + static int + test_import_add_impl(wasm_exec_env_t exec_env, int32_t a, int32_t b) + { + return a + b; + } + + static int + test_import_mul_impl(wasm_exec_env_t exec_env, int32_t a, int32_t b) + { + return a * b; + } + + static int + malloc_impl(wasm_exec_env_t exec_env, int32_t size) + { + return wasm_runtime_module_malloc( + wasm_runtime_get_module_inst(exec_env), size, NULL); + } + + static void + free_impl(wasm_exec_env_t exec_env, int32_t ptr) + { + wasm_runtime_module_free( + wasm_runtime_get_module_inst(exec_env), ptr); + } + + static int + native_func_impl(wasm_exec_env_t exec_env, int32_t a) + { + return a * 2; + } + + static NativeSymbol native_symbols[] = { + { "test_import_add", (void*)test_import_add_impl, "(ii)i", NULL }, + { "test_import_mul", (void*)test_import_mul_impl, "(ii)i", NULL }, + { "malloc", (void*)malloc_impl, "(i)i", NULL }, + { "free", (void*)free_impl, "(i)", NULL }, + { "native_func", (void*)native_func_impl, "(i)i", NULL } + }; + + /** + * Test fixture for Step 3: Function Invocation and Stack Operations + * Targets 6 functions: call_indirect, wasm_call_indirect, wasm_interp_call_func_import, + * copy_stack_values, execute_malloc_function, execute_free_function + */ + class FunctionInvocationTest : public testing::Test + { + protected: + void SetUp() override + { + char *current_dir = getcwd(NULL, 0); + CWD = std::string(current_dir); + free(current_dir); + WASM_FILE = CWD + "/function_invocation_test.wasm"; + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_System_Allocator; + + ASSERT_TRUE(wasm_runtime_full_init(&init_args)); + + // Register native symbols for import testing + ASSERT_TRUE(wasm_runtime_register_natives("env", native_symbols, + sizeof(native_symbols) / sizeof(NativeSymbol))); + + load_wasm_file(); + instantiate_module(); + } + + void TearDown() override + { + if (exec_env) { + wasm_runtime_destroy_exec_env(exec_env); + } + if (module_inst) { + wasm_runtime_deinstantiate(module_inst); + } + if (module) { + wasm_runtime_unload(module); + } + if (wasm_file_buf) { + delete[] wasm_file_buf; + } + wasm_runtime_destroy(); + } + + void load_wasm_file() + { + std::ifstream wasm_file(WASM_FILE, std::ios::binary); + ASSERT_TRUE(wasm_file.is_open()) << "Failed to open WASM file: " << WASM_FILE; + + std::vector buffer(std::istreambuf_iterator(wasm_file), {}); + wasm_file_size = buffer.size(); + wasm_file_buf = new unsigned char[wasm_file_size]; + std::copy(buffer.begin(), buffer.end(), wasm_file_buf); + + module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + ASSERT_NE(module, nullptr) << "Load module failed: " << error_buf; + } + + void instantiate_module() + { + module_inst = wasm_runtime_instantiate( + module, STACK_SIZE, HEAP_SIZE, error_buf, sizeof(error_buf)); + ASSERT_NE(module_inst, nullptr) << "Instantiate module failed: " << error_buf; + + exec_env = wasm_runtime_create_exec_env(module_inst, STACK_SIZE); + ASSERT_NE(exec_env, nullptr); + } + + RuntimeInitArgs init_args; + wasm_module_t module = nullptr; + wasm_module_inst_t module_inst = nullptr; + wasm_exec_env_t exec_env = nullptr; + unsigned char *wasm_file_buf = nullptr; + uint32_t wasm_file_size = 0; + char error_buf[128] = { 0 }; + }; + + /** + * Test Function 1: call_indirect() - Valid function call + * Target: core/iwasm/interpreter/wasm_runtime.c:call_indirect() + * Expected Coverage: ~15 lines (success path) + */ + TEST_F(FunctionInvocationTest, CallIndirect_ValidFunction_ReturnsCorrectResult) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_call_indirect_valid"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[2]; + wasm_argv[0] = 0; // table index 0 (points to $add_func) + wasm_argv[1] = 15; // parameter value + + bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv); + ASSERT_TRUE(success); + + // $add_func adds 10 to input: 15 + 10 = 25 + ASSERT_EQ(wasm_argv[0], 25); + } + + /** + * Test Function 1: call_indirect() - Invalid index + * Target: core/iwasm/interpreter/wasm_runtime.c:call_indirect() + * Expected Coverage: ~15 lines (error path) + */ + TEST_F(FunctionInvocationTest, CallIndirect_InvalidIndex_FailsGracefully) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_call_indirect_invalid_index"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[1]; + wasm_argv[0] = 42; // input value + + bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv); + ASSERT_FALSE(success); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) != NULL); + } + + /** + * Test Function 2: wasm_call_indirect() - Type mismatch error handling + * Target: core/iwasm/interpreter/wasm_runtime.c:wasm_call_indirect() + * Expected Coverage: ~13 lines (error path) + */ + TEST_F(FunctionInvocationTest, WasmCallIndirect_TypeMismatch_ReturnsFailure) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_call_indirect_type_mismatch"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[1]; + wasm_argv[0] = 100; // input value + + bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv); + ASSERT_FALSE(success); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) != NULL); + } + + /** + * Test Function 3: wasm_interp_call_func_import() - Success path + * Target: core/iwasm/interpreter/wasm_interp_fast.c:wasm_interp_call_func_import() + * Expected Coverage: ~12 lines (success path) + */ + TEST_F(FunctionInvocationTest, CallFuncImport_Success_CallsNativeFunction) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_import_function_call"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[2]; + wasm_argv[0] = 15; // first parameter + wasm_argv[1] = 25; // second parameter + + bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv); + ASSERT_TRUE(success); + + // test_import_add_impl adds two values: 15 + 25 = 40 + ASSERT_EQ(wasm_argv[0], 40); + } + + /** + * Test Function 3: wasm_interp_call_func_import() - Multiple import calls + * Target: core/iwasm/interpreter/wasm_interp_fast.c:wasm_interp_call_func_import() + * Expected Coverage: ~13 lines (additional path) + */ + TEST_F(FunctionInvocationTest, CallFuncImport_MultipleImports_HandlesCorrectly) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_import_function_mul"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[2]; + wasm_argv[0] = 6; // first parameter + wasm_argv[1] = 7; // second parameter + + bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv); + ASSERT_TRUE(success); + + // test_import_mul_impl multiplies two values: 6 * 7 = 42 + ASSERT_EQ(wasm_argv[0], 42); + } + + /** + * Test Function 4: copy_stack_values() - Normal operation + * Target: core/iwasm/interpreter/wasm_interp_fast.c:copy_stack_values() + * Expected Coverage: ~20 lines (normal operation) + */ + TEST_F(FunctionInvocationTest, CopyStackValues_Normal_CopiesValuesCorrectly) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_stack_operations"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[2]; + wasm_argv[0] = 10; // val1 + wasm_argv[1] = 20; // val2 + + bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv); + ASSERT_TRUE(success); + + // Complex calculation: (10+20) + (5+10) + (20*3) = 30 + 15 + 60 = 105 + ASSERT_EQ(wasm_argv[0], 105); + } + + /** + * Test Function 4: copy_stack_values() - Large parameter count + * Target: core/iwasm/interpreter/wasm_interp_fast.c:copy_stack_values() + * Expected Coverage: Additional lines for large stack operations + */ + TEST_F(FunctionInvocationTest, CopyStackValues_LargeParams_HandlesCorrectly) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_large_param_stack"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[8]; + wasm_argv[0] = 1; + wasm_argv[1] = 2; + wasm_argv[2] = 3; + wasm_argv[3] = 4; + wasm_argv[4] = 5; + wasm_argv[5] = 6; + wasm_argv[6] = 7; + wasm_argv[7] = 8; + + bool success = wasm_runtime_call_wasm(exec_env, func, 8, wasm_argv); + ASSERT_TRUE(success); + + // (1+2) + (3+4) + (5+6) + (7+8) = 3 + 7 + 11 + 15 = 36 + ASSERT_EQ(wasm_argv[0], 36); + } + + /** + * Test Function 5: execute_malloc_function() - Success path + * Target: core/iwasm/interpreter/wasm_runtime.c:execute_malloc_function() + * Expected Coverage: ~20 lines (success path) + */ + TEST_F(FunctionInvocationTest, ExecuteMalloc_Success_AllocatesMemory) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_malloc_operation"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[1]; + wasm_argv[0] = 1024; // allocate 1KB + + bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv); + ASSERT_TRUE(success); + + // Should return a valid memory offset (> 0) + ASSERT_GT(wasm_argv[0], 0); + } + + /** + * Test Function 5: execute_malloc_function() - Failure path + * Target: core/iwasm/interpreter/wasm_runtime.c:execute_malloc_function() + * Expected Coverage: ~20 lines (failure path) + */ + TEST_F(FunctionInvocationTest, ExecuteMalloc_Failure_HandlesLargeAllocation) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_malloc_operation"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[1]; + wasm_argv[0] = 0x10000000; // try to allocate large amount (256MB) + + bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv); + // The call should succeed (no crash), but malloc should return 0 + ASSERT_TRUE(success); + ASSERT_EQ(wasm_argv[0], 0); + } + + /** + * Test Function 6: execute_free_function() - Success path + * Target: core/iwasm/interpreter/wasm_runtime.c:execute_free_function() + * Expected Coverage: ~20 lines (success path) + */ + TEST_F(FunctionInvocationTest, ExecuteFree_Success_FreesMemory) + { + // First allocate memory + wasm_function_inst_t malloc_func = wasm_runtime_lookup_function( + module_inst, "test_malloc_operation"); + ASSERT_NE(malloc_func, nullptr); + + uint32_t malloc_argv[1]; + malloc_argv[0] = 512; + + bool success = wasm_runtime_call_wasm(exec_env, malloc_func, 1, malloc_argv); + ASSERT_TRUE(success); + ASSERT_GT(malloc_argv[0], 0); + + // Now free the allocated memory + wasm_function_inst_t free_func = wasm_runtime_lookup_function( + module_inst, "test_free_operation"); + ASSERT_NE(free_func, nullptr); + + uint32_t free_argv[1]; + free_argv[0] = malloc_argv[0]; // use allocated pointer + + success = wasm_runtime_call_wasm(exec_env, free_func, 1, free_argv); + ASSERT_TRUE(success); + } + + /** + * Test Function 6: execute_free_function() - Error handling + * Target: core/iwasm/interpreter/wasm_runtime.c:execute_free_function() + * Expected Coverage: ~20 lines (error path) + */ + TEST_F(FunctionInvocationTest, ExecuteFree_ErrorHandling_HandlesInvalidPointer) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_free_operation"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[1]; + wasm_argv[0] = 0; // try to free NULL pointer + + bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv); + ASSERT_TRUE(success); // free(NULL) is valid and should succeed + } + + /** + * Test malloc/free cycle to exercise both functions together + */ + TEST_F(FunctionInvocationTest, MallocFreeCycle_Complete_WorksCorrectly) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_malloc_free_cycle"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[1]; + wasm_argv[0] = 256; // allocation size + + bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv); + ASSERT_TRUE(success); + + // Should return the value that was stored (42) + ASSERT_EQ(wasm_argv[0], 42); + } + + /** + * Test complex indirect call scenarios + */ + TEST_F(FunctionInvocationTest, ComplexIndirectCalls_MultipleSelectors_HandlesCorrectly) + { + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_complex_indirect_calls"); + ASSERT_NE(func, nullptr); + + // Test selector 0 (add_func) + uint32_t wasm_argv[2]; + wasm_argv[0] = 0; // selector + wasm_argv[1] = 30; // value + + bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv); + ASSERT_TRUE(success); + ASSERT_EQ(wasm_argv[0], 40); // 30 + 10 = 40 + + // Test selector 1 (mul_func) + wasm_argv[0] = 1; // selector + wasm_argv[1] = 15; // value + + success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv); + ASSERT_TRUE(success); + ASSERT_EQ(wasm_argv[0], 30); // 15 * 2 = 30 + + // Test selector 2 (identity_func) + wasm_argv[0] = 2; // selector + wasm_argv[1] = 99; // value + + success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv); + ASSERT_TRUE(success); + ASSERT_EQ(wasm_argv[0], 99); // identity returns same value + } + + /** + * Additional test for function invocation edge cases + */ + TEST_F(FunctionInvocationTest, FunctionInvocation_EdgeCases_HandlesCorrectly) + { + // Test with maximum parameter values + wasm_function_inst_t func = wasm_runtime_lookup_function( + module_inst, "test_stack_operations"); + ASSERT_NE(func, nullptr); + + uint32_t wasm_argv[2]; + wasm_argv[0] = 0xFFFFFFFF; // max uint32 + wasm_argv[1] = 1; + + bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv); + ASSERT_TRUE(success); + } diff --git a/tests/unit/smart-tests/interpreter/wasm-apps/function_invocation_test.wasm b/tests/unit/smart-tests/interpreter/wasm-apps/function_invocation_test.wasm new file mode 100644 index 000000000..db338d804 Binary files /dev/null and b/tests/unit/smart-tests/interpreter/wasm-apps/function_invocation_test.wasm differ diff --git a/tests/unit/smart-tests/interpreter/wasm-apps/function_invocation_test.wat b/tests/unit/smart-tests/interpreter/wasm-apps/function_invocation_test.wat new file mode 100644 index 000000000..b9d1f4055 --- /dev/null +++ b/tests/unit/smart-tests/interpreter/wasm-apps/function_invocation_test.wat @@ -0,0 +1,150 @@ +(module + ;; Import functions + (import "env" "test_import_add" (func $test_import_add (param i32 i32) (result i32))) + (import "env" "test_import_mul" (func $test_import_mul (param i32 i32) (result i32))) + (import "env" "malloc" (func $malloc (param i32) (result i32))) + (import "env" "free" (func $free (param i32))) + (import "env" "native_func" (func $native_func (param i32) (result i32))) + + ;; Type definitions + (type $void_to_void (func)) + (type $i32_to_i32 (func (param i32) (result i32))) + (type $i32_i32_to_i32 (func (param i32 i32) (result i32))) + + ;; Memory and table + (memory 1) + (table 4 funcref) + + ;; Local functions for table + (func $add_func (type $i32_to_i32) (param $x i32) (result i32) + local.get $x + i32.const 10 + i32.add) + + (func $mul_func (type $i32_to_i32) (param $x i32) (result i32) + local.get $x + i32.const 2 + i32.mul) + + (func $identity_func (type $i32_to_i32) (param $x i32) (result i32) + local.get $x) + + (func $void_func (type $void_to_void)) + + ;; Initialize table + (elem (i32.const 0) $add_func $mul_func $identity_func $void_func) + + ;; Test functions matching the C++ test expectations + (func (export "test_call_indirect_valid") (param $idx i32) (param $val i32) (result i32) + local.get $val + local.get $idx + call_indirect (type $i32_to_i32)) + + (func (export "test_call_indirect_invalid_index") (param $val i32) (result i32) + local.get $val + i32.const 10 + call_indirect (type $i32_to_i32)) + + (func (export "test_call_indirect_type_mismatch") (param $val i32) (result i32) + local.get $val + i32.const 3 + call_indirect (type $i32_to_i32)) + + (func (export "test_import_function_call") (param $a i32) (param $b i32) (result i32) + local.get $a + local.get $b + call $test_import_add) + + (func (export "test_import_function_mul") (param $a i32) (param $b i32) (result i32) + local.get $a + local.get $b + call $test_import_mul) + + (func (export "test_native_function_call") (param $a i32) (result i32) + local.get $a + call $native_func) + + (func (export "test_malloc_operation") (param $size i32) (result i32) + local.get $size + call $malloc) + + (func (export "test_free_operation") (param $ptr i32) + local.get $ptr + call $free) + + (func (export "test_malloc_free_cycle") (param $size i32) (result i32) + (local $ptr i32) + local.get $size + call $malloc + local.set $ptr + + local.get $ptr + i32.const 42 + i32.store + + local.get $ptr + i32.load + + local.get $ptr + call $free) + + (func (export "test_stack_operations") (param $val1 i32) (param $val2 i32) (result i32) + local.get $val1 + local.get $val2 + call $test_import_add + + i32.const 5 + call $add_func + i32.add + + local.get $val2 + i32.const 3 + call $test_import_mul + i32.add) + + (func (export "test_complex_indirect_calls") (param $selector i32) (param $value i32) (result i32) + local.get $selector + i32.const 0 + i32.eq + if (result i32) + local.get $value + i32.const 0 + call_indirect (type $i32_to_i32) + else + local.get $selector + i32.const 1 + i32.eq + if (result i32) + local.get $value + i32.const 1 + call_indirect (type $i32_to_i32) + else + local.get $value + i32.const 2 + call_indirect (type $i32_to_i32) + end + end) + + (func (export "test_large_param_stack") + (param $p1 i32) (param $p2 i32) (param $p3 i32) (param $p4 i32) + (param $p5 i32) (param $p6 i32) (param $p7 i32) (param $p8 i32) + (result i32) + local.get $p1 + local.get $p2 + call $test_import_add + + local.get $p3 + local.get $p4 + call $test_import_add + i32.add + + local.get $p5 + local.get $p6 + call $test_import_add + i32.add + + local.get $p7 + local.get $p8 + call $test_import_add + i32.add) +) \ No newline at end of file diff --git a/tests/unit/tid-allocator/CMakeLists.txt b/tests/unit/tid-allocator/CMakeLists.txt index be62340a3..87cf08654 100644 --- a/tests/unit/tid-allocator/CMakeLists.txt +++ b/tests/unit/tid-allocator/CMakeLists.txt @@ -13,10 +13,6 @@ if (NOT DEFINED WAMR_BUILD_INTERP) set (WAMR_BUILD_INTERP 1) endif () -if (NOT DEFINED WAMR_BUILD_PLATFORM) - string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) -endif () - include (../unit_common.cmake) add_library (tid_allocator_vmlib ${WAMR_RUNTIME_LIB_SOURCE}) diff --git a/tests/unit/unit_common.cmake b/tests/unit/unit_common.cmake index 53e9ae50d..b6692c62e 100644 --- a/tests/unit/unit_common.cmake +++ b/tests/unit/unit_common.cmake @@ -1,27 +1,11 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -if (NOT DEFINED WAMR_BUILD_PLATFORM) - set (WAMR_BUILD_PLATFORM "linux") -endif () - enable_language (ASM) # Usually, test cases should identify their unique # complation flags to implement their test plan -# Set WAMR_BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" -if (NOT DEFINED WAMR_BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform - set (WAMR_BUILD_TARGET "X86_64") - else () - # Build as X86_32 by default in 32-bit platform - set (WAMR_BUILD_TARGET "X86_32") - endif () -endif () - set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) # include the build config template file diff --git a/tests/unit/wasm-c-api/CMakeLists.txt b/tests/unit/wasm-c-api/CMakeLists.txt index 3150c9325..d4d83d0ec 100644 --- a/tests/unit/wasm-c-api/CMakeLists.txt +++ b/tests/unit/wasm-c-api/CMakeLists.txt @@ -4,8 +4,6 @@ cmake_minimum_required (VERSION 3.14) project (wasm_c_api_test) -set(WAMR_BUILD_PLATFORM "linux") - # WAMR features switch if (NOT DEFINED WAMR_BUILD_TARGET) set(WAMR_BUILD_TARGET "X86_64") diff --git a/tests/unit/wasm-vm/CMakeLists.txt b/tests/unit/wasm-vm/CMakeLists.txt index aeaac0b3f..3cc45f5c2 100644 --- a/tests/unit/wasm-vm/CMakeLists.txt +++ b/tests/unit/wasm-vm/CMakeLists.txt @@ -20,7 +20,7 @@ add_definitions (-Dattr_container_free=free) include (../unit_common.cmake) find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch index e333dd933..663d90aec 100644 --- a/tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch +++ b/tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch @@ -138,10 +138,30 @@ index bc1cc324..14af14ae 100644 (assert_return (invoke "call_imported_elem") (i32.const 42)) +;;) diff --git a/test/core/gc/array.wast b/test/core/gc/array.wast -index 6ad95c08..a184435d 100644 +index 6ad95c08..17672d33 100644 --- a/test/core/gc/array.wast +++ b/test/core/gc/array.wast -@@ -95,7 +95,10 @@ +@@ -7,7 +7,8 @@ + (type (array i64)) + (type (array f32)) + (type (array f64)) +- (type (array anyref)) ++ ;; Disable because `anyref` in fileds of composite types is not supported yet ++ ;; (type (array anyref)) + (type (array (ref struct))) + (type (array (ref 0))) + (type (array (ref null 1))) +@@ -17,7 +18,8 @@ + (type (array (mut i64))) + (type (array (mut i32))) + (type (array (mut i64))) +- (type (array (mut anyref))) ++ ;; Disable because `anyref` in fileds of composite types is not supported yet ++ ;; (type (array (mut anyref))) + (type (array (mut (ref struct)))) + (type (array (mut (ref 0)))) + (type (array (mut (ref null i31)))) +@@ -95,7 +97,10 @@ ) (assert_return (invoke "new") (ref.array)) @@ -153,7 +173,7 @@ index 6ad95c08..a184435d 100644 (assert_return (invoke "get" (i32.const 0)) (f32.const 0)) (assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7)) (assert_return (invoke "len") (i32.const 3)) -@@ -140,7 +143,10 @@ +@@ -140,7 +145,10 @@ ) (assert_return (invoke "new") (ref.array)) @@ -165,7 +185,7 @@ index 6ad95c08..a184435d 100644 (assert_return (invoke "get" (i32.const 0)) (f32.const 1)) (assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7)) (assert_return (invoke "len") (i32.const 2)) -@@ -192,7 +198,10 @@ +@@ -192,7 +200,10 @@ ) (assert_return (invoke "new") (ref.array)) @@ -177,7 +197,7 @@ index 6ad95c08..a184435d 100644 (assert_return (invoke "get_u" (i32.const 2)) (i32.const 0xff)) (assert_return (invoke "get_s" (i32.const 2)) (i32.const -1)) (assert_return (invoke "set_get" (i32.const 1) (i32.const 7)) (i32.const 7)) -@@ -202,6 +211,7 @@ +@@ -202,6 +213,7 @@ (assert_trap (invoke "get_s" (i32.const 10)) "out of bounds array access") (assert_trap (invoke "set_get" (i32.const 10) (i32.const 7)) "out of bounds array access") @@ -185,7 +205,7 @@ index 6ad95c08..a184435d 100644 (module (type $bvec (array i8)) (type $vec (array (ref $bvec))) -@@ -260,6 +270,7 @@ +@@ -260,6 +272,7 @@ (assert_trap (invoke "get" (i32.const 10) (i32.const 0)) "out of bounds array access") (assert_trap (invoke "set_get" (i32.const 10) (i32.const 0) (i32.const 0)) "out of bounds array access") @@ -309,6 +329,100 @@ index 6309e72b..39f35692 100644 (assert_return (invoke "get" (i32.const 3)) (i32.const 789)) + ;; + ;;) +diff --git a/test/core/gc/struct.wast b/test/core/gc/struct.wast +index 6151fe10..d501cd3c 100644 +--- a/test/core/gc/struct.wast ++++ b/test/core/gc/struct.wast +@@ -6,8 +6,9 @@ + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) +- (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) +- (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) ++ ;; Disable because `anyref` in fileds of composite types is not supported yet ++ ;; (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) ++ ;; (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + ) + +diff --git a/test/core/gc/type-subtyping.wast b/test/core/gc/type-subtyping.wast +index f2b33d7c..a61560c2 100644 +--- a/test/core/gc/type-subtyping.wast ++++ b/test/core/gc/type-subtyping.wast +@@ -4,7 +4,8 @@ + (type $e0 (sub (array i32))) + (type $e1 (sub $e0 (array i32))) + +- (type $e2 (sub (array anyref))) ++ ;; Disable because `anyref` in fileds of composite types is not supported yet ++ ;; (type $e2 (sub (array anyref))) + (type $e3 (sub (array (ref null $e0)))) + (type $e4 (sub (array (ref $e1)))) + +@@ -32,35 +33,36 @@ + ) + + ++;; Disable because `anyref` in fileds of composite types is not supported yet + ;; Recursive definitions + +-(module +- (type $t (sub (struct (field anyref)))) +- (rec (type $r (sub $t (struct (field (ref $r)))))) +- (type $t' (sub $r (struct (field (ref $r) i32)))) +-) +- +-(module +- (rec +- (type $r1 (sub (struct (field i32 (ref $r1))))) +- ) +- (rec +- (type $r2 (sub $r1 (struct (field i32 (ref $r3))))) +- (type $r3 (sub $r1 (struct (field i32 (ref $r2))))) +- ) +-) +- +-(module +- (rec +- (type $a1 (sub (struct (field i32 (ref $a2))))) +- (type $a2 (sub (struct (field i64 (ref $a1))))) +- ) +- (rec +- (type $b1 (sub $a2 (struct (field i64 (ref $a1) i32)))) +- (type $b2 (sub $a1 (struct (field i32 (ref $a2) i32)))) +- (type $b3 (sub $a2 (struct (field i64 (ref $b2) i32)))) +- ) +-) ++;; (module ++;; (type $t (sub (struct (field anyref)))) ++;; (rec (type $r (sub $t (struct (field (ref $r)))))) ++;; (type $t' (sub $r (struct (field (ref $r) i32)))) ++;; ) ++ ++;; (module ++;; (rec ++;; (type $r1 (sub (struct (field i32 (ref $r1))))) ++;; ) ++;; (rec ++;; (type $r2 (sub $r1 (struct (field i32 (ref $r3))))) ++;; (type $r3 (sub $r1 (struct (field i32 (ref $r2))))) ++;; ) ++;; ) ++ ++;; (module ++;; (rec ++;; (type $a1 (sub (struct (field i32 (ref $a2))))) ++;; (type $a2 (sub (struct (field i64 (ref $a1))))) ++;; ) ++;; (rec ++;; (type $b1 (sub $a2 (struct (field i64 (ref $a1) i32)))) ++;; (type $b2 (sub $a1 (struct (field i32 (ref $a2) i32)))) ++;; (type $b3 (sub $a2 (struct (field i64 (ref $b2) i32)))) ++;; ) ++;; ) + + + ;; Subsumption diff --git a/test/core/global.wast b/test/core/global.wast index 8c47fde2..8d3d8228 100644 --- a/test/core/global.wast diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 513fd0049..7d7b82437 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -176,7 +176,7 @@ if (NOT WAMR_BUILD_WITH_CUSTOM_LLVM) endif () find_package(LLVM REQUIRED CONFIG) -include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") @@ -184,8 +184,8 @@ message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") if (WAMR_BUILD_DEBUG_AOT EQUAL 1) if(LLVM_BUILD_MAIN_SRC_DIR) - include_directories(${LLVM_BUILD_MAIN_SRC_DIR}/../lldb/include) - include_directories(${LLVM_BUILD_BINARY_DIR}/tools/lldb/include) + include_directories(SYSTEM ${LLVM_BUILD_MAIN_SRC_DIR}/../lldb/include) + include_directories(SYSTEM ${LLVM_BUILD_BINARY_DIR}/tools/lldb/include) endif() link_directories(${LLVM_LIBRARY_DIRS}) find_library(lib_lldb NAMES lldb HINTS ${LLVM_LIBRARY_DIRS} REQUIRED) @@ -328,7 +328,7 @@ endif () #TODO: sync up WAMR_BUILD_SANITIZER in config_common.cmake # set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang" OR MSVC)) + if (CMAKE_C_COMPILER_ID MATCHES ".*GNU") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WAMR_BUILD_JIT EQUAL 1) diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index f0675a351..9b582d589 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -178,7 +178,7 @@ print_help() printf(" A comma-separated list of features when generating call stacks.\n"); printf(" By default, all features are enabled. To disable all features,\n"); printf(" provide an empty list (i.e. --call-stack-features=). This flag\n"); - printf(" only only takes effect when --enable-dump-call-stack is set.\n"); + printf(" only takes effect when --enable-dump-call-stack is set.\n"); printf(" Available features: bounds-checks, ip, func-idx, trap-ip, values.\n"); printf(" --enable-perf-profiling Enable function performance profiling\n"); printf(" --enable-memory-profiling Enable memory usage profiling\n"); @@ -246,7 +246,7 @@ print_help() * Based on: http://stackoverflow.com/a/11198630/471795 */ static char ** -split_string(char *str, int *count, const char *delimer) +split_string(char *str, int *count, const char *delimiter) { char **res = NULL, **res1; char *p; @@ -254,7 +254,7 @@ split_string(char *str, int *count, const char *delimer) /* split string and append tokens to 'res' */ do { - p = strtok(str, delimer); + p = strtok(str, delimiter); str = NULL; res1 = res; res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));