diff --git a/.github/ISSUE_TEMPLATE/blank_issue.md b/.github/ISSUE_TEMPLATE/blank_issue.md new file mode 100644 index 0000000000..57febe7d5f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/blank_issue.md @@ -0,0 +1,5 @@ +--- +name: Blank Issue +about: Create a blank issue. +title: '' +--- diff --git a/.github/ISSUE_TEMPLATE/improvement.md b/.github/ISSUE_TEMPLATE/improvement.md new file mode 100644 index 0000000000..ffdf0906ff --- /dev/null +++ b/.github/ISSUE_TEMPLATE/improvement.md @@ -0,0 +1,28 @@ +--- +name: Improvement +about: A feature request or code improvement. +title: '' +labels: '' +assignees: '' +--- + +Thanks for filing a feature request! Please fill out the TODOs below. + +#### Feature + +TODO: Brief description of the feature/improvement you'd like to see in WAMR + +#### Benefit + +TODO: What is the value of adding this in WAMR? What problems does it solve? + +#### Implementation + +TODO: Do you have an implementation plan, and/or ideas for data structures or +algorithms to use? + +#### Alternatives + +TODO: What are the alternative implementation approaches or alternative ways to +solve the problem that this feature would solve? How do these alternatives +compare to this proposal? diff --git a/.github/ISSUE_TEMPLATE/report_bug.md b/.github/ISSUE_TEMPLATE/report_bug.md new file mode 100644 index 0000000000..d3058c9ca1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/report_bug.md @@ -0,0 +1,36 @@ +--- +name: WAMR bug or defect report +about: Report a bug or defect in WAMR +title: '' +--- + +Thanks for filing a bug or defect report! Please fill out the TODOs below. + +### Subject of the issue + +Describe the bug or defect here. + +### Test case + +Upload the related wasm file, wast file or the source files if you can. + +### Your environment + +* Host OS +* WAMR version, platform, cpu architecture, running mode, etc. + +### Steps to reproduce + +Tell us how to reproduce this bug or defect. + +### Expected behavior + +Tell us what should happen + +### Actual behavior + +Tell us what happens instead + +### Extra Info + +Anything else you'd like to add? diff --git a/.github/workflows/build_llvm_libraries.yml b/.github/workflows/build_llvm_libraries.yml index 18b90e5687..67eaf614d1 100644 --- a/.github/workflows/build_llvm_libraries.yml +++ b/.github/workflows/build_llvm_libraries.yml @@ -33,10 +33,16 @@ jobs: - name: checkout uses: actions/checkout@v4 - - name: install dependencies + - name: install dependencies for non macos-14 + if: inputs.os != 'macos-14' 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' + run: /usr/bin/env python3 -m pip install -r requirements.txt --break-system-packages + working-directory: build-scripts + - name: retrive the last commit ID id: get_last_commit run: echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py --llvm-ver)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..8656b326ce --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,114 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +name: "CodeQL" + +on: + #pull_request: + # types: + # - opened + # branches: '*' + #push: + # branches: [ "main" ] + # midnight UTC + schedule: + - cron: '0 0 * * *' + # allow to be triggered manually + workflow_dispatch: + +jobs: + analyze: + if: github.repository == 'bytecodealliance/wasm-micro-runtime' + name: Analyze + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-20.04' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: recursive + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + 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 + # queries: security-extended,security-and-quality + queries: security-and-quality + + # Command-line programs to run using the OS shell. + # See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + - run: | + ./.github/workflows/codeql_buildscript.sh + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" + upload: false + id: step1 + + # Filter out rules with low severity or high false positve rate + # Also filter out warnings in third-party code + - name: Filter out unwanted errors and warnings + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -**:cpp/path-injection + -**:cpp/world-writable-file-creation + -**:cpp/poorly-documented-function + -**:cpp/potentially-dangerous-function + -**:cpp/use-of-goto + -**:cpp/integer-multiplication-cast-to-long + -**:cpp/comparison-with-wider-type + -**:cpp/leap-year/* + -**:cpp/ambiguously-signed-bit-field + -**:cpp/suspicious-pointer-scaling + -**:cpp/suspicious-pointer-scaling-void + -**:cpp/unsigned-comparison-zero + -**/cmake*/Modules/** + input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif + output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif + + - name: Upload CodeQL results to code scanning + uses: github/codeql-action/upload-sarif@v2 + 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@v3 + with: + name: codeql-results + path: ${{ steps.step1.outputs.sarif-output }} + retention-days: 10 + + - name: Fail if an error is found + run: | + ./.github/workflows/codeql_fail_on_error.py \ + ${{ steps.step1.outputs.sarif-output }}/cpp.sarif diff --git a/.github/workflows/codeql_buildscript.sh b/.github/workflows/codeql_buildscript.sh new file mode 100755 index 0000000000..ed717734ea --- /dev/null +++ b/.github/workflows/codeql_buildscript.sh @@ -0,0 +1,277 @@ +#!/usr/bin/env bash + +sudo apt update + +sudo apt install -y build-essential cmake g++-multilib libgcc-11-dev lib32gcc-11-dev ccache ninja-build ccache + +WAMR_DIR=${PWD} + +# TODO: use pre-built llvm binary to build wamrc to +# avoid static code analysing for llvm +: ' +# build wamrc +cd ${WAMR_DIR}/wamr-compiler +./build_llvm.sh +rm -fr build && mkdir build && cd build +cmake .. +make -j +if [[ $? != 0 ]]; then + echo "Failed to build wamrc!" + exit 1; +fi +' + +# build iwasm with default features enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -fr build && mkdir build && cd build +cmake .. +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with default features enabled!" + exit 1; +fi + +# build iwasm with default features enabled on x86_32 +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -fr build && mkdir build && cd build +cmake .. -DWAMR_BUILD_TARGET=X86_32 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with default features enabled on x86_32!" + exit 1; +fi + +# build iwasm with classic interpreter enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_INTERP=0 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with classic interpreter enabled!" + exit 1; +fi + +# build iwasm with extra features enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -fr build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug \ + -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1 \ + -DWAMR_BUILD_MULTI_MODULE=1 -DWAMR_BUILD_SIMD=1 \ + -DWAMR_BUILD_TAIL_CALL=1 -DWAMR_BUILD_REF_TYPES=1 \ + -DWAMR_BUILD_CUSTOM_NAME_SECTION=1 -DWAMR_BUILD_MEMORY_PROFILING=1 \ + -DWAMR_BUILD_PERF_PROFILING=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \ + -DWAMR_BUILD_LOAD_CUSTOM_SECTION=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build wamrc iwasm with extra features enabled!" + exit 1; +fi + +# build iwasm with global heap pool enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -fr build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug \ + -DWAMR_BUILD_ALLOC_WITH_USER_DATA=1 \ + -DWAMR_DISABLE_STACK_HW_BOUND_CHECK=1 \ + -DWAMR_BUILD_GLOBAL_HEAP_POOL=1 \ + -DWAMR_BUILD_GLOBAL_HEAP_SIZE=131072 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with global heap pool enabled!" + exit 1; +fi + +# build iwasm with wasi-threads enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -fr build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LIB_WASI_THREADS=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with wasi-threads enabled!" + exit 1; +fi + +# build iwasm with GC enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_GC=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with GC enabled!" + exit 1; +fi + +# build iwasm with exception handling enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_EXCE_HANDLING=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with exception handling enabled!" + exit 1; +fi + +# build iwasm with memory64 enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MEMORY64=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with memory64 enabled!" + exit 1; +fi + +# build iwasm with hardware boundary check disabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_DISABLE_HW_BOUND_CHECK=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with hardware boundary check disabled!" + exit 1; +fi + +# build iwasm with quick AOT entry disabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_QUICK_AOT_ENTRY=0 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with quick AOT entry disabled!" + exit 1; +fi + +# build iwasm with wakeup of blocking operations disabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_DISABLE_WAKEUP_BLOCKING_OP=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with wakeup of blocking operations disabled!" + exit 1; +fi + +# build iwasm with module instance context disabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MODULE_INST_CONTEXT=0 \ + -DWAMR_BUILD_LIBC_BUILTIN=0 -DWAMR_BUILD_LIBC_WASI=0 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with module instance context disabled!" + exit 1; +fi + +# build iwasm with libc-uvwasi enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -fr build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LIBC_UVWASI=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with libc-uvwasi enabled!" + exit 1; +fi + +# build iwasm with fast jit lazy mode enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with fast jit lazy mode enabled!" + exit 1; +fi + +# build iwasm with fast jit eager mode enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with fast jit eager mode enabled!" + exit 1; +fi + +# TODO: use pre-built llvm binary to build llvm-jit and multi-tier-jit +: ' +# build iwasm with llvm jit lazy mode enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_JIT=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build llvm jit lazy mode enabled!" + exit 1; +fi + +# build iwasm with llvm jit eager mode enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build llvm jit eager mode enabled!" + exit 1; +fi + +# build iwasm with multi-tier jit enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \ + -DWAMR_BUILD_FAST_JIT_DUMP=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with multi-tier jit enabled!" + exit 1; +fi +' + +# build iwasm with wasm mini-loader enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MINI_LOADER=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build with wasm mini-loader enabled!" + exit 1; +fi + +# build iwasm with source debugging enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_DEBUG_INTERP=1 -DWAMR_BUILD_DEBUG_AOT=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with source debugging enabled!" + exit 1; +fi + +# build iwasm with AOT static PGO enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_STATIC_PGO=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with AOT static PGO enabled!" + exit 1; +fi + +# build iwasm with configurable bounds checks enabled +cd ${WAMR_DIR}/product-mini/platforms/linux +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_CONFIGUABLE_BOUNDS_CHECKS=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with configurable bounds checks enabled!" + exit 1; +fi + +# build iwasm with linux perf support enabled +cd ${WAMR_DIR}/product-mini/platforms/linux/ +rm -rf build && mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LINUX_PERF=1 +make -j +if [[ $? != 0 ]]; then + echo "Failed to build iwasm with linux perf support enabled!" + exit 1; +fi diff --git a/.github/workflows/codeql_fail_on_error.py b/.github/workflows/codeql_fail_on_error.py new file mode 100755 index 0000000000..29791742b2 --- /dev/null +++ b/.github/workflows/codeql_fail_on_error.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import json +import sys + +# Return whether SARIF file contains error-level results +def codeql_sarif_contain_error(filename): + with open(filename, 'r') as f: + s = json.load(f) + + for run in s.get('runs', []): + rules_metadata = run['tool']['driver']['rules'] + if not rules_metadata: + rules_metadata = run['tool']['extensions'][0]['rules'] + + for res in run.get('results', []): + if 'ruleIndex' in res: + rule_index = res['ruleIndex'] + elif 'rule' in res and 'index' in res['rule']: + rule_index = res['rule']['index'] + else: + continue + try: + rule_level = rules_metadata[rule_index]['defaultConfiguration']['level'] + except IndexError as e: + print(e, rule_index, len(rules_metadata)) + else: + if rule_level == 'error': + return True + return False + +if __name__ == "__main__": + if codeql_sarif_contain_error(sys.argv[1]): + sys.exit(1) diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index d1d464d4d8..f1e437774d 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -65,6 +65,7 @@ env: WASI_TEST_OPTIONS: "-s wasi_certification -w" WAMR_COMPILER_TEST_OPTIONS: "-s wamr_compiler -S -b -P" GC_TEST_OPTIONS: "-s spec -G -b -P" + MEMORY64_TEST_OPTIONS: "-s spec -W -b -P" jobs: build_llvm_libraries_on_ubuntu_2204: @@ -144,6 +145,7 @@ jobs: "-DWAMR_BUILD_SIMD=1", "-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1", + "-DWAMR_BUILD_MEMORY64=1", ] os: [ubuntu-22.04] platform: [android, linux] @@ -202,11 +204,32 @@ jobs: make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - # Fast-JIT and Multi-Tier-JIT mode don't support android(X86-32) + # Memory64 only on CLASSIC INTERP mode, and only on 64-bit platform + - make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + platform: android + - make_options_run_mode: $AOT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + # Fast-JIT and Multi-Tier-JIT mode don't support android - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS platform: android - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS platform: android + # LLVM JIT pre-built binary wasn't compiled by Android NDK + # and isn't available for android + - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS + platform: android + - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS + platform: android include: - os: ubuntu-22.04 llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} @@ -232,13 +255,23 @@ jobs: if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true') run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - - name: Build iwasm + - name: Build iwasm for linux + if: matrix.platform == 'linux' run: | mkdir build && cd build cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} cmake --build . --config Release --parallel 4 working-directory: product-mini/platforms/${{ matrix.platform }} + - name: Build iwasm for android + if: matrix.platform == 'android' + run: | + mkdir build && cd build + cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} \ + -DWAMR_BUILD_TARGET=X86_64 + cmake --build . --config Release --parallel 4 + working-directory: product-mini/platforms/${{ matrix.platform }} + - name: Build and run unit tests run: | mkdir build-unittests && cd build-unittests @@ -448,6 +481,16 @@ jobs: ./build.sh ./run.sh + - name: Build Sample [debug-tools] + run: | + cd samples/debug-tools + mkdir build && cd build + cmake .. + cmake --build . --config Debug --parallel 4 + ./iwasm wasm-apps/trap.wasm | grep "#" > call_stack.txt + ./iwasm wasm-apps/trap.aot | grep "#" > call_stack_aot.txt + bash -x ../symbolicate.sh + test: needs: [ @@ -477,6 +520,7 @@ jobs: $THREADS_TEST_OPTIONS, $WASI_TEST_OPTIONS, $GC_TEST_OPTIONS, + $MEMORY64_TEST_OPTIONS, ] wasi_sdk_release: [ @@ -515,19 +559,30 @@ jobs: test_option: $GC_TEST_OPTIONS - running_mode: "multi-tier-jit" test_option: $GC_TEST_OPTIONS + # aot, fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Memory64 + - running_mode: "aot" + test_option: $MEMORY64_TEST_OPTIONS + - running_mode: "fast-interp" + test_option: $MEMORY64_TEST_OPTIONS + - running_mode: "fast-jit" + test_option: $MEMORY64_TEST_OPTIONS + - running_mode: "jit" + test_option: $MEMORY64_TEST_OPTIONS + - running_mode: "multi-tier-jit" + test_option: $MEMORY64_TEST_OPTIONS steps: - name: checkout uses: actions/checkout@v4 - name: Set-up OCaml uses: ocaml/setup-ocaml@v2 - if: matrix.test_option == '$GC_TEST_OPTIONS' + if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS' with: ocaml-compiler: 4.13 - name: Set-up Ocamlbuild - if: matrix.test_option == '$GC_TEST_OPTIONS' - run: opam install ocamlbuild dune + if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS' + run: opam install ocamlbuild dune menhir - name: download and install wasi-sdk if: matrix.test_option == '$WASI_TEST_OPTIONS' @@ -546,7 +601,6 @@ jobs: make -j AR=/opt/wasi-sdk/bin/llvm-ar NM=/opt/wasi-sdk/bin/llvm-nm CC=/opt/wasi-sdk/bin/clang THREAD_MODEL=posix echo "SYSROOT_PATH=$PWD/sysroot" >> $GITHUB_ENV - - name: set env variable(if llvm are used) if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit' run: echo "USE_LLVM=true" >> $GITHUB_ENV @@ -592,13 +646,13 @@ jobs: - name: run tests timeout-minutes: 30 - if: matrix.test_option != '$GC_TEST_OPTIONS' + if: matrix.test_option != '$GC_TEST_OPTIONS' && matrix.test_option != '$MEMORY64_TEST_OPTIONS' run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites - - name: run gc tests + - name: run gc or memory64 tests timeout-minutes: 20 - if: matrix.test_option == '$GC_TEST_OPTIONS' + if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS' run: | eval $(opam env) ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index 7bea5175eb..4f59f2386e 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -242,7 +242,7 @@ jobs: run: | cmake -S . -B build ${{ matrix.make_options }} cmake --build build --config Release --parallel 4 - ctest --test-dir build + ctest --test-dir build --output-on-failure working-directory: samples/wasm-c-api build_samples_others: @@ -369,3 +369,13 @@ jobs: cd samples/terminate ./build.sh ./run.sh + + - name: Build Sample [debug-tools] + run: | + cd samples/debug-tools + mkdir build && cd build + cmake .. + cmake --build . --config Debug --parallel 4 + ./iwasm wasm-apps/trap.wasm | grep "#" > call_stack.txt + ./iwasm wasm-apps/trap.aot | grep "#" > call_stack_aot.txt + bash -x ../symbolicate.sh diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index cfc910ea28..341194df8e 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -130,6 +130,7 @@ jobs: "-DWAMR_BUILD_SIMD=1", "-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1", + "-DWAMR_BUILD_MEMORY64=1", ] os: [ubuntu-20.04] platform: [android, linux] @@ -188,11 +189,32 @@ jobs: make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - # Fast-JIT and Multi-Tier-JIT mode don't support android(X86-32) + # Memory64 only on CLASSIC INTERP mode, and only on 64-bit platform + - make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + platform: android + - make_options_run_mode: $AOT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + # Fast-JIT and Multi-Tier-JIT mode don't support android - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS platform: android - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS platform: android + # LLVM JIT pre-built binary wasn't compiled by Android NDK + # and isn't available for android + - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS + platform: android + - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS + platform: android include: - os: ubuntu-20.04 llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} @@ -219,13 +241,23 @@ jobs: if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true') run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - - name: Build iwasm + - name: Build iwasm for linux + if: matrix.platform == 'linux' run: | mkdir build && cd build cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} cmake --build . --config Release --parallel 4 working-directory: product-mini/platforms/${{ matrix.platform }} + - name: Build iwasm for android + if: matrix.platform == 'android' + run: | + mkdir build && cd build + cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} \ + -DWAMR_BUILD_TARGET=X86_64 + cmake --build . --config Release --parallel 4 + working-directory: product-mini/platforms/${{ matrix.platform }} + build_iwasm_linux_gcc4_8: runs-on: ubuntu-latest container: @@ -255,6 +287,7 @@ jobs: "-DWAMR_BUILD_SIMD=1", "-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1", + "-DWAMR_BUILD_MEMORY64=1", ] exclude: # uncompatiable feature and platform @@ -283,6 +316,11 @@ jobs: # MINI_LOADER only on INTERP mode - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + # Memory64 only on CLASSIC INTERP mode + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MEMORY64=1" steps: - name: checkout uses: actions/checkout@v3 @@ -626,7 +664,9 @@ jobs: run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV - name: set additional tsan options - run: echo "TSAN_OPTIONS=suppressions=$PWD/tsan_suppressions.txt" >> $GITHUB_ENV + run: | + echo "TSAN_OPTIONS=suppressions=$PWD/tsan_suppressions.txt" >> $GITHUB_ENV + sudo sysctl vm.mmap_rnd_bits=28 working-directory: tests/wamr-test-suites #only download llvm libraries in jit and aot mode diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index b249f7b02b..2c83d66748 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -60,11 +60,11 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the ### llvm -[LICENSE](./core/deps/llvm/llvm/LICENCE.txt) +[LICENSE](./LICENCE.txt) ### wasm-c-api -[LICENSE](https://github.com/bytecodealliance/wamr-app-framework/blob/main/samples/wasm-c-api/src/LICENSE) +[LICENSE](./samples/wasm-c-api/src/LICENSE) ### wasmtime @@ -78,10 +78,6 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the [LICENSE](https://github.com/bytecodealliance/wamr-app-framework/blob/main/samples/gui/wasm-runtime-wgl/src/platform/zephyr/LICENSE) -### wac - -[LICENSE](./tests/wamr-test-suites/spec-test-script/LICENSE) - ### libuv [LICENSE](./core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c87994945..8df86ddd0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,7 +151,7 @@ if (WAMR_BUILD_WASM_CACHE EQUAL 1) endif () if (MINGW) - target_link_libraries (iwasm_shared -lWs2_32) + target_link_libraries (iwasm_shared INTERFACE -lWs2_32 -lwsock32) endif () install (TARGETS iwasm_shared LIBRARY DESTINATION lib) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9210b3deb1..0e04101d29 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ We Use Github Flow, So All Code Changes Happen Through Pull Requests. Pull reque Coding Style =============================== Please use [K&R](https://en.wikipedia.org/wiki/Indentation_style#K.26R) coding style, such as 4 spaces for indentation rather than tabs etc. -We suggest use Eclipse like IDE or stable coding format tools to make your code compliant to K&R format. +We suggest using VS Code like IDE or stable coding format tools, like clang-format, to make your code compliant to the customized format(in .clang-format). Report bugs =================== diff --git a/README.md b/README.md index 13f777a2f4..cb91c22ce4 100644 --- a/README.md +++ b/README.md @@ -35,25 +35,24 @@ WebAssembly Micro Runtime (WAMR) is a lightweight standalone WebAssembly (Wasm) - [XIP (Execution In Place) support](./doc/xip.md), ref to [document](./doc/xip.md) - [Berkeley/Posix Socket support](./doc/socket_api.md), ref to [document](./doc/socket_api.md) and [sample](./samples/socket-api) - [Multi-tier JIT](./product-mini#linux) and [Running mode control](https://bytecodealliance.github.io/wamr.dev/blog/introduction-to-wamr-running-modes/) -- Language bindings: [Go](./language-bindings/go/README.md), [Python](./language-bindings/python/README.md) +- Language bindings: [Go](./language-bindings/go/README.md), [Python](./language-bindings/python/README.md), [Rust](./language-bindings/rust/README.md) ### Wasm post-MVP features - [wasm-c-api](https://github.com/WebAssembly/wasm-c-api), ref to [document](doc/wasm_c_api.md) and [sample](samples/wasm-c-api) - [128-bit SIMD](https://github.com/WebAssembly/simd), ref to [samples/workload](samples/workload) - [Reference Types](https://github.com/WebAssembly/reference-types), ref to [document](doc/ref_types.md) and [sample](samples/ref-types) -- [Non-trapping float-to-int conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions) -- [Sign-extension operators](https://github.com/WebAssembly/sign-extension-ops), [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations) -- [Multi-value](https://github.com/WebAssembly/multi-value), [Tail-call](https://github.com/WebAssembly/tail-call), [Shared memory](https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#shared-linear-memory) +- [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations), [Shared memory](https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#shared-linear-memory), [Memory64](https://github.com/WebAssembly/memory64) +- [Tail-call](https://github.com/WebAssembly/tail-call), [Garbage Collection](https://github.com/WebAssembly/gc), [Exception Handling](https://github.com/WebAssembly/exception-handling) ### Supported architectures and platforms -The WAMR VMcore supports the following architectures: +The WAMR VMcore supports the following architectures: - X86-64, X86-32 - ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested) - AArch64 (Cortex-A57 and Cortex-A53 are tested) - RISCV64, RISCV32 (RISC-V LP64 and RISC-V LP64D are tested) - XTENSA, MIPS, ARC -The following platforms are supported, click each link below for how to build iwasm on that platform. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. +The following platforms are supported, click each link below for how to build iwasm on that platform. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. - [Linux](./product-mini/README.md#linux), [Linux SGX (Intel Software Guard Extension)](./doc/linux_sgx.md), [MacOS](./product-mini/README.md#macos), [Android](./product-mini/README.md#android), [Windows](./product-mini/README.md#windows), [Windows (MinGW)](./product-mini/README.md#mingw) - [Zephyr](./product-mini/README.md#zephyr), [AliOS-Things](./product-mini/README.md#alios-things), [VxWorks](./product-mini/README.md#vxworks), [NuttX](./product-mini/README.md#nuttx), [RT-Thread](./product-mini/README.md#RT-Thread), [ESP-IDF](./product-mini/README.md#esp-idf) @@ -67,7 +66,7 @@ The following platforms are supported, click each link below for how to build iw - [Build Wasm applications](./doc/build_wasm_app.md) - [Port WAMR to a new platform](./doc/port_wamr.md) - [VS Code development container](./doc/devcontainer.md) -- [Samples](./samples) and [Benchmarks](./tests/benchmarks) +- [Samples](./samples) and [Benchmarks](./tests/benchmarks) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index d97ad82227..1f0fbab85e 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -248,6 +248,15 @@ if (WAMR_BUILD_SHARED_MEMORY EQUAL 1) else () add_definitions (-DWASM_ENABLE_SHARED_MEMORY=0) endif () +if (WAMR_BUILD_MEMORY64 EQUAL 1) + # if native is 32-bit or cross-compiled to 32-bit + if (NOT WAMR_BUILD_TARGET MATCHES ".*64.*") + message (FATAL_ERROR "-- Memory64 is only available on the 64-bit platform/target") + endif() + add_definitions (-DWASM_ENABLE_MEMORY64=1) + set (WAMR_DISABLE_HW_BOUND_CHECK 1) + message (" Memory64 memory enabled") +endif () if (WAMR_BUILD_THREAD_MGR EQUAL 1) message (" Thread manager enabled") endif () @@ -434,6 +443,10 @@ if (WAMR_BUILD_WASI_NN EQUAL 1) if (DEFINED WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH) add_definitions (-DWASM_WASI_NN_EXTERNAL_DELEGATE_PATH="${WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH}") endif () + if (WAMR_BUILD_WASI_EPHEMERAL_NN EQUAL 1) + message (" WASI-NN: WASI-Ephemeral-NN enabled") + add_definitions (-DWASM_ENABLE_WASI_EPHEMERAL_NN=1) + endif() endif () if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1) add_definitions(-DWASM_MEM_ALLOC_WITH_USER_DATA=1) @@ -529,3 +542,19 @@ else () # Disable quick aot/jit entries for interp and fast-jit add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=0) endif () +if (WAMR_BUILD_AOT EQUAL 1) + if (NOT DEFINED WAMR_BUILD_AOT_INTRINSICS) + # Enable aot intrinsics by default + set (WAMR_BUILD_AOT_INTRINSICS 1) + endif () + if (WAMR_BUILD_AOT_INTRINSICS EQUAL 1) + add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=1) + message (" AOT intrinsics enabled") + else () + add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0) + message (" AOT intrinsics disabled") + endif () +else () + # Disable aot intrinsics for interp, fast-jit and llvm-jit + add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0) +endif () diff --git a/build-scripts/esp-idf/wamr/CMakeLists.txt b/build-scripts/esp-idf/wamr/CMakeLists.txt index 5ac04ddc92..47ccb055f3 100644 --- a/build-scripts/esp-idf/wamr/CMakeLists.txt +++ b/build-scripts/esp-idf/wamr/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # Set WAMR's build options -if("${IDF_TARGET}" STREQUAL "esp32c3") +if("${IDF_TARGET}" STREQUAL "esp32c3" OR "${IDF_TARGET}" STREQUAL "esp32c6") set(WAMR_BUILD_TARGET "RISCV32") else() set(WAMR_BUILD_TARGET "XTENSA") diff --git a/core/config.h b/core/config.h index 7cb770de19..442e813b01 100644 --- a/core/config.h +++ b/core/config.h @@ -152,6 +152,10 @@ #define WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE 0 #endif +#ifndef WASM_ENABLE_WASI_EPHEMERAL_NN +#define WASM_ENABLE_WASI_EPHEMERAL_NN 0 +#endif + /* Default disable libc emcc */ #ifndef WASM_ENABLE_LIBC_EMCC #define WASM_ENABLE_LIBC_EMCC 0 @@ -416,7 +420,7 @@ #else #define DEFAULT_WASM_STACK_SIZE (12 * 1024) #endif -/* Min auxilliary stack size of each wasm thread */ +/* Min auxiliary stack size of each wasm thread */ #define WASM_THREAD_AUX_STACK_SIZE_MIN (256) /* Default/min native stack size of each app thread */ @@ -565,12 +569,25 @@ #endif /* Support registering quick AOT/JIT function entries of some func types - to speedup the calling process of invoking the AOT/JIT functions of + to speed up the calling process of invoking the AOT/JIT functions of these types from the host embedder */ #ifndef WASM_ENABLE_QUICK_AOT_ENTRY #define WASM_ENABLE_QUICK_AOT_ENTRY 1 #endif +/* Support AOT intrinsic functions which can be called from the AOT code + when `--disable-llvm-intrinsics` flag or + `--enable-builtin-intrinsics=` is used by wamrc to + generate the AOT file */ +#ifndef WASM_ENABLE_AOT_INTRINSICS +#define WASM_ENABLE_AOT_INTRINSICS 1 +#endif + +/* Disable memory64 by default */ +#ifndef WASM_ENABLE_MEMORY64 +#define WASM_ENABLE_MEMORY64 0 +#endif + #ifndef WASM_TABLE_MAX_SIZE #define WASM_TABLE_MAX_SIZE 1024 #endif diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 189b43b09b..7b455cbb05 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -5,86 +5,6 @@ #include "aot_intrinsic.h" -typedef struct { - const char *llvm_intrinsic; - const char *native_intrinsic; - uint64 flag; -} aot_intrinsic; - -/* clang-format off */ -static const aot_intrinsic g_intrinsic_mapping[] = { - { "llvm.experimental.constrained.fadd.f32", "aot_intrinsic_fadd_f32", AOT_INTRINSIC_FLAG_F32_FADD }, - { "llvm.experimental.constrained.fadd.f64", "aot_intrinsic_fadd_f64", AOT_INTRINSIC_FLAG_F64_FADD }, - { "llvm.experimental.constrained.fsub.f32", "aot_intrinsic_fsub_f32", AOT_INTRINSIC_FLAG_F32_FSUB }, - { "llvm.experimental.constrained.fsub.f64", "aot_intrinsic_fsub_f64", AOT_INTRINSIC_FLAG_F64_FSUB }, - { "llvm.experimental.constrained.fmul.f32", "aot_intrinsic_fmul_f32", AOT_INTRINSIC_FLAG_F32_FMUL }, - { "llvm.experimental.constrained.fmul.f64", "aot_intrinsic_fmul_f64", AOT_INTRINSIC_FLAG_F64_FMUL }, - { "llvm.experimental.constrained.fdiv.f32", "aot_intrinsic_fdiv_f32", AOT_INTRINSIC_FLAG_F32_FDIV }, - { "llvm.experimental.constrained.fdiv.f64", "aot_intrinsic_fdiv_f64", AOT_INTRINSIC_FLAG_F64_FDIV }, - { "llvm.fabs.f32", "aot_intrinsic_fabs_f32", AOT_INTRINSIC_FLAG_F32_FABS }, - { "llvm.fabs.f64", "aot_intrinsic_fabs_f64", AOT_INTRINSIC_FLAG_F64_FABS }, - { "llvm.ceil.f32", "aot_intrinsic_ceil_f32", AOT_INTRINSIC_FLAG_F32_CEIL }, - { "llvm.ceil.f64", "aot_intrinsic_ceil_f64", AOT_INTRINSIC_FLAG_F64_CEIL }, - { "llvm.floor.f32", "aot_intrinsic_floor_f32", AOT_INTRINSIC_FLAG_F32_FLOOR }, - { "llvm.floor.f64", "aot_intrinsic_floor_f64", AOT_INTRINSIC_FLAG_F64_FLOOR }, - { "llvm.trunc.f32", "aot_intrinsic_trunc_f32", AOT_INTRINSIC_FLAG_F32_TRUNC }, - { "llvm.trunc.f64", "aot_intrinsic_trunc_f64", AOT_INTRINSIC_FLAG_F64_TRUNC }, - { "llvm.rint.f32", "aot_intrinsic_rint_f32", AOT_INTRINSIC_FLAG_F32_RINT }, - { "llvm.rint.f64", "aot_intrinsic_rint_f64", AOT_INTRINSIC_FLAG_F64_RINT }, - { "llvm.sqrt.f32", "aot_intrinsic_sqrt_f32", AOT_INTRINSIC_FLAG_F32_SQRT }, - { "llvm.sqrt.f64", "aot_intrinsic_sqrt_f64", AOT_INTRINSIC_FLAG_F64_SQRT }, - { "llvm.copysign.f32", "aot_intrinsic_copysign_f32", AOT_INTRINSIC_FLAG_F32_COPYSIGN }, - { "llvm.copysign.f64", "aot_intrinsic_copysign_f64", AOT_INTRINSIC_FLAG_F64_COPYSIGN }, - { "llvm.minnum.f32", "aot_intrinsic_fmin_f32", AOT_INTRINSIC_FLAG_F32_MIN }, - { "llvm.minnum.f64", "aot_intrinsic_fmin_f64", AOT_INTRINSIC_FLAG_F64_MIN }, - { "llvm.maxnum.f32", "aot_intrinsic_fmax_f32", AOT_INTRINSIC_FLAG_F32_MAX }, - { "llvm.maxnum.f64", "aot_intrinsic_fmax_f64", AOT_INTRINSIC_FLAG_F64_MAX }, - { "llvm.ctlz.i32", "aot_intrinsic_clz_i32", AOT_INTRINSIC_FLAG_I32_CLZ }, - { "llvm.ctlz.i64", "aot_intrinsic_clz_i64", AOT_INTRINSIC_FLAG_I64_CLZ }, - { "llvm.cttz.i32", "aot_intrinsic_ctz_i32", AOT_INTRINSIC_FLAG_I32_CTZ }, - { "llvm.cttz.i64", "aot_intrinsic_ctz_i64", AOT_INTRINSIC_FLAG_I64_CTZ }, - { "llvm.ctpop.i32", "aot_intrinsic_popcnt_i32", AOT_INTRINSIC_FLAG_I32_POPCNT }, - { "llvm.ctpop.i64", "aot_intrinsic_popcnt_i64", AOT_INTRINSIC_FLAG_I64_POPCNT }, - { "f64_convert_i32_s", "aot_intrinsic_i32_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 }, - { "f64_convert_i32_u", "aot_intrinsic_u32_to_f64", AOT_INTRINSIC_FLAG_U32_TO_F64 }, - { "f32_convert_i32_s", "aot_intrinsic_i32_to_f32", AOT_INTRINSIC_FLAG_I32_TO_F32 }, - { "f32_convert_i32_u", "aot_intrinsic_u32_to_f32", AOT_INTRINSIC_FLAG_U32_TO_F32 }, - { "f64_convert_i64_s", "aot_intrinsic_i64_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 }, - { "f64_convert_i64_u", "aot_intrinsic_u64_to_f64", AOT_INTRINSIC_FLAG_U64_TO_F64 }, - { "f32_convert_i64_s", "aot_intrinsic_i64_to_f32", AOT_INTRINSIC_FLAG_I64_TO_F32 }, - { "f32_convert_i64_u", "aot_intrinsic_u64_to_f32", AOT_INTRINSIC_FLAG_U64_TO_F32 }, - { "i32_trunc_f32_u", "aot_intrinsic_f32_to_u32", AOT_INTRINSIC_FLAG_F32_TO_U32 }, - { "i32_trunc_f32_s", "aot_intrinsic_f32_to_i32", AOT_INTRINSIC_FLAG_F32_TO_I32 }, - { "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 }, - { "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 }, - { "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 }, - { "i64_trunc_f32_s", "aot_intrinsic_f32_to_i64", AOT_INTRINSIC_FLAG_F32_TO_I64 }, - { "i64_trunc_f32_u", "aot_intrinsic_f32_to_u64", AOT_INTRINSIC_FLAG_F32_TO_U64 }, - { "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 }, - { "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 }, - { "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 }, - { "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP }, - { "f64_cmp", "aot_intrinsic_f64_cmp", AOT_INTRINSIC_FLAG_F64_CMP }, - { "i32.const", NULL, AOT_INTRINSIC_FLAG_I32_CONST }, - { "i64.const", NULL, AOT_INTRINSIC_FLAG_I64_CONST }, - { "f32.const", NULL, AOT_INTRINSIC_FLAG_F32_CONST }, - { "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST }, - { "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S}, - { "i32.div_s", "aot_intrinsic_i32_div_s", AOT_INTRINSIC_FLAG_I32_DIV_S}, - { "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U}, - { "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S}, - { "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U}, - { "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U}, - { "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S}, - { "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U}, - { "i64.or", "aot_intrinsic_i64_bit_or", AOT_INTRINSIC_FLAG_I64_BIT_OR}, - { "i64.and", "aot_intrinsic_i64_bit_and", AOT_INTRINSIC_FLAG_I64_BIT_AND}, -}; -/* clang-format on */ - -static const uint32 g_intrinsic_count = - sizeof(g_intrinsic_mapping) / sizeof(aot_intrinsic); - float32 aot_intrinsic_fadd_f32(float32 a, float32 b) { @@ -565,6 +485,88 @@ aot_intrinsic_i64_bit_and(uint64 l, uint64 r) return l & r; } +#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 + +typedef struct { + const char *llvm_intrinsic; + const char *native_intrinsic; + uint64 flag; +} aot_intrinsic; + +/* clang-format off */ +static const aot_intrinsic g_intrinsic_mapping[] = { + { "llvm.experimental.constrained.fadd.f32", "aot_intrinsic_fadd_f32", AOT_INTRINSIC_FLAG_F32_FADD }, + { "llvm.experimental.constrained.fadd.f64", "aot_intrinsic_fadd_f64", AOT_INTRINSIC_FLAG_F64_FADD }, + { "llvm.experimental.constrained.fsub.f32", "aot_intrinsic_fsub_f32", AOT_INTRINSIC_FLAG_F32_FSUB }, + { "llvm.experimental.constrained.fsub.f64", "aot_intrinsic_fsub_f64", AOT_INTRINSIC_FLAG_F64_FSUB }, + { "llvm.experimental.constrained.fmul.f32", "aot_intrinsic_fmul_f32", AOT_INTRINSIC_FLAG_F32_FMUL }, + { "llvm.experimental.constrained.fmul.f64", "aot_intrinsic_fmul_f64", AOT_INTRINSIC_FLAG_F64_FMUL }, + { "llvm.experimental.constrained.fdiv.f32", "aot_intrinsic_fdiv_f32", AOT_INTRINSIC_FLAG_F32_FDIV }, + { "llvm.experimental.constrained.fdiv.f64", "aot_intrinsic_fdiv_f64", AOT_INTRINSIC_FLAG_F64_FDIV }, + { "llvm.fabs.f32", "aot_intrinsic_fabs_f32", AOT_INTRINSIC_FLAG_F32_FABS }, + { "llvm.fabs.f64", "aot_intrinsic_fabs_f64", AOT_INTRINSIC_FLAG_F64_FABS }, + { "llvm.ceil.f32", "aot_intrinsic_ceil_f32", AOT_INTRINSIC_FLAG_F32_CEIL }, + { "llvm.ceil.f64", "aot_intrinsic_ceil_f64", AOT_INTRINSIC_FLAG_F64_CEIL }, + { "llvm.floor.f32", "aot_intrinsic_floor_f32", AOT_INTRINSIC_FLAG_F32_FLOOR }, + { "llvm.floor.f64", "aot_intrinsic_floor_f64", AOT_INTRINSIC_FLAG_F64_FLOOR }, + { "llvm.trunc.f32", "aot_intrinsic_trunc_f32", AOT_INTRINSIC_FLAG_F32_TRUNC }, + { "llvm.trunc.f64", "aot_intrinsic_trunc_f64", AOT_INTRINSIC_FLAG_F64_TRUNC }, + { "llvm.rint.f32", "aot_intrinsic_rint_f32", AOT_INTRINSIC_FLAG_F32_RINT }, + { "llvm.rint.f64", "aot_intrinsic_rint_f64", AOT_INTRINSIC_FLAG_F64_RINT }, + { "llvm.sqrt.f32", "aot_intrinsic_sqrt_f32", AOT_INTRINSIC_FLAG_F32_SQRT }, + { "llvm.sqrt.f64", "aot_intrinsic_sqrt_f64", AOT_INTRINSIC_FLAG_F64_SQRT }, + { "llvm.copysign.f32", "aot_intrinsic_copysign_f32", AOT_INTRINSIC_FLAG_F32_COPYSIGN }, + { "llvm.copysign.f64", "aot_intrinsic_copysign_f64", AOT_INTRINSIC_FLAG_F64_COPYSIGN }, + { "llvm.minnum.f32", "aot_intrinsic_fmin_f32", AOT_INTRINSIC_FLAG_F32_MIN }, + { "llvm.minnum.f64", "aot_intrinsic_fmin_f64", AOT_INTRINSIC_FLAG_F64_MIN }, + { "llvm.maxnum.f32", "aot_intrinsic_fmax_f32", AOT_INTRINSIC_FLAG_F32_MAX }, + { "llvm.maxnum.f64", "aot_intrinsic_fmax_f64", AOT_INTRINSIC_FLAG_F64_MAX }, + { "llvm.ctlz.i32", "aot_intrinsic_clz_i32", AOT_INTRINSIC_FLAG_I32_CLZ }, + { "llvm.ctlz.i64", "aot_intrinsic_clz_i64", AOT_INTRINSIC_FLAG_I64_CLZ }, + { "llvm.cttz.i32", "aot_intrinsic_ctz_i32", AOT_INTRINSIC_FLAG_I32_CTZ }, + { "llvm.cttz.i64", "aot_intrinsic_ctz_i64", AOT_INTRINSIC_FLAG_I64_CTZ }, + { "llvm.ctpop.i32", "aot_intrinsic_popcnt_i32", AOT_INTRINSIC_FLAG_I32_POPCNT }, + { "llvm.ctpop.i64", "aot_intrinsic_popcnt_i64", AOT_INTRINSIC_FLAG_I64_POPCNT }, + { "f64_convert_i32_s", "aot_intrinsic_i32_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 }, + { "f64_convert_i32_u", "aot_intrinsic_u32_to_f64", AOT_INTRINSIC_FLAG_U32_TO_F64 }, + { "f32_convert_i32_s", "aot_intrinsic_i32_to_f32", AOT_INTRINSIC_FLAG_I32_TO_F32 }, + { "f32_convert_i32_u", "aot_intrinsic_u32_to_f32", AOT_INTRINSIC_FLAG_U32_TO_F32 }, + { "f64_convert_i64_s", "aot_intrinsic_i64_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 }, + { "f64_convert_i64_u", "aot_intrinsic_u64_to_f64", AOT_INTRINSIC_FLAG_U64_TO_F64 }, + { "f32_convert_i64_s", "aot_intrinsic_i64_to_f32", AOT_INTRINSIC_FLAG_I64_TO_F32 }, + { "f32_convert_i64_u", "aot_intrinsic_u64_to_f32", AOT_INTRINSIC_FLAG_U64_TO_F32 }, + { "i32_trunc_f32_u", "aot_intrinsic_f32_to_u32", AOT_INTRINSIC_FLAG_F32_TO_U32 }, + { "i32_trunc_f32_s", "aot_intrinsic_f32_to_i32", AOT_INTRINSIC_FLAG_F32_TO_I32 }, + { "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 }, + { "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 }, + { "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 }, + { "i64_trunc_f32_s", "aot_intrinsic_f32_to_i64", AOT_INTRINSIC_FLAG_F32_TO_I64 }, + { "i64_trunc_f32_u", "aot_intrinsic_f32_to_u64", AOT_INTRINSIC_FLAG_F32_TO_U64 }, + { "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 }, + { "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 }, + { "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 }, + { "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP }, + { "f64_cmp", "aot_intrinsic_f64_cmp", AOT_INTRINSIC_FLAG_F64_CMP }, + { "i32.const", NULL, AOT_INTRINSIC_FLAG_I32_CONST }, + { "i64.const", NULL, AOT_INTRINSIC_FLAG_I64_CONST }, + { "f32.const", NULL, AOT_INTRINSIC_FLAG_F32_CONST }, + { "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST }, + { "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S}, + { "i32.div_s", "aot_intrinsic_i32_div_s", AOT_INTRINSIC_FLAG_I32_DIV_S}, + { "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U}, + { "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S}, + { "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U}, + { "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U}, + { "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S}, + { "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U}, + { "i64.or", "aot_intrinsic_i64_bit_or", AOT_INTRINSIC_FLAG_I64_BIT_OR}, + { "i64.and", "aot_intrinsic_i64_bit_and", AOT_INTRINSIC_FLAG_I64_BIT_AND}, +}; +/* clang-format on */ + +static const uint32 g_intrinsic_count = + sizeof(g_intrinsic_mapping) / sizeof(aot_intrinsic); + const char * aot_intrinsic_get_symbol(const char *llvm_intrinsic) { @@ -577,8 +579,6 @@ aot_intrinsic_get_symbol(const char *llvm_intrinsic) return NULL; } -#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 - static void add_intrinsic_capability(AOTCompContext *comp_ctx, uint64 flag) { diff --git a/core/iwasm/aot/aot_intrinsic.h b/core/iwasm/aot/aot_intrinsic.h index 2123058b95..6a456efdac 100644 --- a/core/iwasm/aot/aot_intrinsic.h +++ b/core/iwasm/aot/aot_intrinsic.h @@ -287,10 +287,10 @@ aot_intrinsic_i64_bit_or(uint64 l, uint64 r); uint64 aot_intrinsic_i64_bit_and(uint64 l, uint64 r); +#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 const char * aot_intrinsic_get_symbol(const char *llvm_intrinsic); -#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 bool aot_intrinsic_check_capability(const AOTCompContext *comp_ctx, const char *llvm_intrinsic); diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 85fa1f89dd..df487039cb 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -16,6 +16,10 @@ #include "debug/jit_debug.h" #endif +#if WASM_ENABLE_LINUX_PERF != 0 +#include "aot_perf_map.h" +#endif + #define YMM_PLT_PREFIX "__ymm@" #define XMM_PLT_PREFIX "__xmm@" #define REAL_PLT_PREFIX "__real@" @@ -289,55 +293,6 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) return mem; } -static char * -const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, -#if (WASM_ENABLE_WORD_ALIGN_READ != 0) - bool is_vram_word_align, -#endif - char *error_buf, uint32 error_buf_size) -{ - HashMap *set = module->const_str_set; - char *c_str, *value; - - /* Create const string set if it isn't created */ - if (!set - && !(set = module->const_str_set = bh_hash_map_create( - 32, false, (HashFunc)wasm_string_hash, - (KeyEqualFunc)wasm_string_equal, NULL, wasm_runtime_free))) { - set_error_buf(error_buf, error_buf_size, - "create const string set failed"); - return NULL; - } - - /* Lookup const string set, use the string if found */ - if (!(c_str = loader_malloc((uint32)len, error_buf, error_buf_size))) { - return NULL; - } -#if (WASM_ENABLE_WORD_ALIGN_READ != 0) - if (is_vram_word_align) { - bh_memcpy_wa(c_str, (uint32)len, str, (uint32)len); - } - else -#endif - { - bh_memcpy_s(c_str, len, str, (uint32)len); - } - - if ((value = bh_hash_map_find(set, c_str))) { - wasm_runtime_free(c_str); - return value; - } - - if (!bh_hash_map_insert(set, c_str, c_str)) { - set_error_buf(error_buf, error_buf_size, - "insert string to hash map failed"); - wasm_runtime_free(c_str); - return NULL; - } - - return c_str; -} - static char * load_string(uint8 **p_buf, const uint8 *buf_end, AOTModule *module, bool is_load_from_file_buf, @@ -359,9 +314,9 @@ load_string(uint8 **p_buf, const uint8 *buf_end, AOTModule *module, } #if (WASM_ENABLE_WORD_ALIGN_READ != 0) else if (is_vram_word_align) { - if (!(str = const_str_set_insert((uint8 *)p, str_len, module, - is_vram_word_align, error_buf, - error_buf_size))) { + if (!(str = aot_const_str_set_insert((uint8 *)p, str_len, module, + is_vram_word_align, error_buf, + error_buf_size))) { goto fail; } } @@ -378,11 +333,11 @@ load_string(uint8 **p_buf, const uint8 *buf_end, AOTModule *module, after loading, we must create another string and insert it into const string set */ bh_assert(p[str_len - 1] == '\0'); - if (!(str = const_str_set_insert((uint8 *)p, str_len, module, + if (!(str = aot_const_str_set_insert((uint8 *)p, str_len, module, #if (WASM_ENABLE_WORD_ALIGN_READ != 0) - is_vram_word_align, + is_vram_word_align, #endif - error_buf, error_buf_size))) { + error_buf, error_buf_size))) { goto fail; } } @@ -1479,9 +1434,20 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, read_uint64(buf, buf_end, init_expr_value); #if WASM_ENABLE_GC != 0 if (wasm_is_type_multi_byte_type(elem_type)) { - /* TODO: check ref_type */ - read_uint16(buf, buf_end, reftype.ref_ht_common.ref_type); - read_uint16(buf, buf_end, reftype.ref_ht_common.nullable); + uint16 ref_type, nullable; + read_uint16(buf, buf_end, ref_type); + if (elem_type != ref_type) { + set_error_buf(error_buf, error_buf_size, "invalid elem type"); + return false; + } + reftype.ref_ht_common.ref_type = (uint8)ref_type; + read_uint16(buf, buf_end, nullable); + if (nullable != 0 && nullable != 1) { + set_error_buf(error_buf, error_buf_size, + "invalid nullable value"); + return false; + } + reftype.ref_ht_common.nullable = (uint8)nullable; read_uint32(buf, buf_end, reftype.ref_ht_common.heap_type); } else @@ -2423,13 +2389,22 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end, } read_uint32(p, p_end, module->aux_data_end_global_index); - read_uint32(p, p_end, module->aux_data_end); + read_uint64(p, p_end, module->aux_data_end); read_uint32(p, p_end, module->aux_heap_base_global_index); - read_uint32(p, p_end, module->aux_heap_base); + read_uint64(p, p_end, module->aux_heap_base); read_uint32(p, p_end, module->aux_stack_top_global_index); - read_uint32(p, p_end, module->aux_stack_bottom); + read_uint64(p, p_end, module->aux_stack_bottom); read_uint32(p, p_end, module->aux_stack_size); + if (module->aux_data_end >= MAX_LINEAR_MEMORY_SIZE + || module->aux_heap_base >= MAX_LINEAR_MEMORY_SIZE + || module->aux_stack_bottom >= MAX_LINEAR_MEMORY_SIZE) { + set_error_buf( + error_buf, error_buf_size, + "invalid range of aux_date_end/aux_heap_base/aux_stack_bottom"); + return false; + } + if (!load_object_data_sections_info(&p, p_end, module, is_load_from_file_buf, error_buf, error_buf_size)) @@ -2908,6 +2883,17 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group, } symbol_addr = module->func_ptrs[func_index]; } + else if (!strncmp(symbol, "_" AOT_FUNC_INTERNAL_PREFIX, + strlen("_" AOT_FUNC_INTERNAL_PREFIX))) { + p = symbol + strlen("_" AOT_FUNC_INTERNAL_PREFIX); + if (*p == '\0' + || (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; + } + symbol_addr = module->func_ptrs[func_index]; + } #endif else if (is_text_section(symbol)) { symbol_addr = module->code; @@ -3619,104 +3605,6 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, return ret; } -#if WASM_ENABLE_LINUX_PERF != 0 -struct func_info { - uint32 idx; - void *ptr; -}; - -static uint32 -get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs, - uint32 idx) -{ - uint32 func_sz; - - if (idx == module->func_count - 1) - func_sz = (uintptr_t)module->code + module->code_size - - (uintptr_t)(sorted_func_ptrs[idx].ptr); - else - func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr) - - (uintptr_t)(sorted_func_ptrs[idx].ptr); - - return func_sz; -} - -static int -compare_func_ptrs(const void *f1, const void *f2) -{ - return (intptr_t)((struct func_info *)f1)->ptr - - (intptr_t)((struct func_info *)f2)->ptr; -} - -static struct func_info * -sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size) -{ - uint64 content_len; - struct func_info *sorted_func_ptrs; - unsigned i; - - content_len = (uint64)sizeof(struct func_info) * module->func_count; - sorted_func_ptrs = loader_malloc(content_len, error_buf, error_buf_size); - if (!sorted_func_ptrs) - return NULL; - - for (i = 0; i < module->func_count; i++) { - sorted_func_ptrs[i].idx = i; - sorted_func_ptrs[i].ptr = module->func_ptrs[i]; - } - - qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info), - compare_func_ptrs); - - return sorted_func_ptrs; -} - -static bool -create_perf_map(const AOTModule *module, char *error_buf, uint32 error_buf_size) -{ - struct func_info *sorted_func_ptrs = NULL; - char perf_map_info[128] = { 0 }; - FILE *perf_map = NULL; - uint32 i; - pid_t pid = getpid(); - bool ret = false; - - sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size); - if (!sorted_func_ptrs) - goto quit; - - snprintf(perf_map_info, 128, "/tmp/perf-%d.map", pid); - perf_map = fopen(perf_map_info, "w"); - if (!perf_map) { - LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid, - strerror(errno)); - goto quit; - } - - for (i = 0; i < module->func_count; i++) { - memset(perf_map_info, 0, 128); - snprintf(perf_map_info, 128, "%lx %x aot_func#%u\n", - (uintptr_t)sorted_func_ptrs[i].ptr, - get_func_size(module, sorted_func_ptrs, i), - sorted_func_ptrs[i].idx); - - fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map); - } - - LOG_VERBOSE("generate /tmp/perf-%d.map", pid); - ret = true; - -quit: - if (sorted_func_ptrs) - free(sorted_func_ptrs); - - if (perf_map) - fclose(perf_map); - - return ret; -} -#endif /* WASM_ENABLE_LINUX_PERF != 0*/ - static bool load_from_sections(AOTModule *module, AOTSection *sections, bool is_load_from_file_buf, char *error_buf, @@ -3907,7 +3795,7 @@ load_from_sections(AOTModule *module, AOTSection *sections, } static AOTModule * -create_module(char *error_buf, uint32 error_buf_size) +create_module(char *name, char *error_buf, uint32 error_buf_size) { AOTModule *module = loader_malloc(sizeof(AOTModule), error_buf, error_buf_size); @@ -3919,6 +3807,8 @@ create_module(char *error_buf, uint32 error_buf_size) module->module_type = Wasm_Module_AoT; + module->name = name; + #if WASM_ENABLE_MULTI_MODULE != 0 module->import_module_list = &module->import_module_list_head; ret = bh_list_init(module->import_module_list); @@ -3953,7 +3843,7 @@ AOTModule * aot_load_from_sections(AOTSection *section_list, char *error_buf, uint32 error_buf_size) { - AOTModule *module = create_module(error_buf, error_buf_size); + AOTModule *module = create_module("", error_buf, error_buf_size); if (!module) return NULL; @@ -4199,7 +4089,7 @@ load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf, #if WASM_ENABLE_LINUX_PERF != 0 if (wasm_runtime_get_linux_perf()) - if (!create_perf_map(module, error_buf, error_buf_size)) + if (!aot_create_perf_map(module, error_buf, error_buf_size)) goto fail; #endif @@ -4209,10 +4099,10 @@ load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf, } AOTModule * -aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf, - uint32 error_buf_size) +aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args, + char *error_buf, uint32 error_buf_size) { - AOTModule *module = create_module(error_buf, error_buf_size); + AOTModule *module = create_module(args->name, error_buf, error_buf_size); if (!module) return NULL; @@ -4406,7 +4296,7 @@ aot_unload(AOTModule *module) } if (module->string_literal_ptrs) { - wasm_runtime_free(module->string_literal_ptrs); + wasm_runtime_free((void *)module->string_literal_ptrs); } } #endif diff --git a/core/iwasm/aot/aot_perf_map.c b/core/iwasm/aot/aot_perf_map.c new file mode 100644 index 0000000000..22700dcdd6 --- /dev/null +++ b/core/iwasm/aot/aot_perf_map.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_perf_map.h" +#include "bh_log.h" +#include "bh_platform.h" + +#if WASM_ENABLE_LINUX_PERF != 0 +struct func_info { + uint32 idx; + void *ptr; +}; + +static uint32 +get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs, + uint32 idx) +{ + uint32 func_sz; + + if (idx == module->func_count - 1) + func_sz = (uintptr_t)module->code + module->code_size + - (uintptr_t)(sorted_func_ptrs[idx].ptr); + else + func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr) + - (uintptr_t)(sorted_func_ptrs[idx].ptr); + + return func_sz; +} + +static int +compare_func_ptrs(const void *f1, const void *f2) +{ + return (intptr_t)((struct func_info *)f1)->ptr + - (intptr_t)((struct func_info *)f2)->ptr; +} + +static struct func_info * +sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size) +{ + uint64 content_len; + struct func_info *sorted_func_ptrs; + unsigned i; + + content_len = (uint64)sizeof(struct func_info) * module->func_count; + sorted_func_ptrs = wasm_runtime_malloc(content_len); + if (!sorted_func_ptrs) { + snprintf(error_buf, error_buf_size, + "allocate memory failed when creating perf map"); + return NULL; + } + + for (i = 0; i < module->func_count; i++) { + sorted_func_ptrs[i].idx = i; + sorted_func_ptrs[i].ptr = module->func_ptrs[i]; + } + + qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info), + compare_func_ptrs); + + return sorted_func_ptrs; +} + +bool +aot_create_perf_map(const AOTModule *module, char *error_buf, + uint32 error_buf_size) +{ + struct func_info *sorted_func_ptrs = NULL; + char perf_map_path[64] = { 0 }; + char perf_map_info[128] = { 0 }; + FILE *perf_map = NULL; + uint32 i; + pid_t pid = getpid(); + bool ret = false; + + sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size); + if (!sorted_func_ptrs) + goto quit; + + snprintf(perf_map_path, sizeof(perf_map_path) - 1, "/tmp/perf-%d.map", pid); + perf_map = fopen(perf_map_path, "a"); + if (!perf_map) { + LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid, + strerror(errno)); + goto quit; + } + + const char *module_name = aot_get_module_name((AOTModule *)module); + for (i = 0; i < module->func_count; i++) { + memset(perf_map_info, 0, 128); + if (strlen(module_name) > 0) + snprintf(perf_map_info, 128, "%lx %x [%s]#aot_func#%u\n", + (uintptr_t)sorted_func_ptrs[i].ptr, + get_func_size(module, sorted_func_ptrs, i), module_name, + sorted_func_ptrs[i].idx); + else + snprintf(perf_map_info, 128, "%lx %x aot_func#%u\n", + (uintptr_t)sorted_func_ptrs[i].ptr, + get_func_size(module, sorted_func_ptrs, i), + sorted_func_ptrs[i].idx); + + /* fwrite() is thread safe */ + fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map); + } + + LOG_VERBOSE("write map information from %s into /tmp/perf-%d.map", + module_name, pid); + ret = true; + +quit: + if (sorted_func_ptrs) + wasm_runtime_free(sorted_func_ptrs); + + if (perf_map) + fclose(perf_map); + + return ret; +} +#endif /* WASM_ENABLE_LINUX_PERF != 0 */ \ No newline at end of file diff --git a/core/iwasm/aot/aot_perf_map.h b/core/iwasm/aot/aot_perf_map.h new file mode 100644 index 0000000000..3e6583c5cd --- /dev/null +++ b/core/iwasm/aot/aot_perf_map.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_PERF_MAP_H_ +#define _AOT_PERF_MAP_H_ + +#include "aot_runtime.h" + +bool +aot_create_perf_map(const AOTModule *module, char *error_buf, + uint32 error_buf_size); + +#endif /* _AOT_PERF_MAP_H_ */ \ No newline at end of file diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index dbbe4e52d6..6ae2b92b5d 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -52,15 +52,15 @@ bh_static_assert(offsetof(AOTModuleInstance, func_type_indexes) == 6 * sizeof(uint64)); bh_static_assert(offsetof(AOTModuleInstance, cur_exception) == 13 * sizeof(uint64)); +bh_static_assert(offsetof(AOTModuleInstance, c_api_func_imports) + == 13 * sizeof(uint64) + 128 + 7 * sizeof(uint64)); bh_static_assert(offsetof(AOTModuleInstance, global_table_data) - == 13 * sizeof(uint64) + 128 + 11 * sizeof(uint64)); + == 13 * sizeof(uint64) + 128 + 14 * sizeof(uint64)); -bh_static_assert(sizeof(AOTMemoryInstance) == 104); +bh_static_assert(sizeof(AOTMemoryInstance) == 120); bh_static_assert(offsetof(AOTTableInstance, elems) == 24); bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0); -bh_static_assert(offsetof(AOTModuleInstanceExtra, common.c_api_func_imports) - == sizeof(uint64)); bh_static_assert(sizeof(CApiFuncImport) == sizeof(uintptr_t) * 3); @@ -793,15 +793,19 @@ static AOTMemoryInstance * memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, AOTModule *module, AOTMemoryInstance *memory_inst, AOTMemory *memory, uint32 memory_idx, uint32 heap_size, - char *error_buf, uint32 error_buf_size) + uint32 max_memory_pages, char *error_buf, + uint32 error_buf_size) { void *heap_handle; uint32 num_bytes_per_page = memory->num_bytes_per_page; uint32 init_page_count = memory->mem_init_page_count; - uint32 max_page_count = memory->mem_max_page_count; - uint32 inc_page_count, aux_heap_base, global_idx; + uint32 max_page_count = + wasm_runtime_get_max_mem(max_memory_pages, memory->mem_init_page_count, + memory->mem_max_page_count); + uint32 inc_page_count, global_idx; uint32 bytes_of_last_page, bytes_to_page_end; - uint32 heap_offset = num_bytes_per_page * init_page_count; + uint64 aux_heap_base, + heap_offset = (uint64)num_bytes_per_page * init_page_count; uint64 memory_data_size, max_memory_data_size; uint8 *p = NULL, *global_addr; @@ -827,6 +831,15 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, heap_size = 0; } + /* If initial memory is the largest size allowed, disallowing insert host + * managed heap */ + if (heap_size > 0 && heap_offset == MAX_LINEAR_MEMORY_SIZE) { + set_error_buf(error_buf, error_buf_size, + "failed to insert app heap into linear memory, " + "try using `--heap-size=0` option"); + return NULL; + } + if (init_page_count == max_page_count && init_page_count == 1) { /* If only one page and at most one page, we just append the app heap to the end of linear memory, enlarge the @@ -850,7 +863,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, } else if (module->aux_heap_base_global_index != (uint32)-1 && module->aux_heap_base - < num_bytes_per_page * init_page_count) { + < (uint64)num_bytes_per_page * init_page_count) { /* Insert app heap before __heap_base */ aux_heap_base = module->aux_heap_base; bytes_of_last_page = aux_heap_base % num_bytes_per_page; @@ -877,15 +890,15 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, - module->import_global_count; global_addr = module_inst->global_data + module->globals[global_idx].data_offset; - *(uint32 *)global_addr = aux_heap_base; - LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base); + *(uint32 *)global_addr = (uint32)aux_heap_base; + LOG_VERBOSE("Reset __heap_base global to %" PRIu64, aux_heap_base); } else { /* Insert app heap before new page */ inc_page_count = (heap_size + num_bytes_per_page - 1) / num_bytes_per_page; - heap_offset = num_bytes_per_page * init_page_count; - heap_size = num_bytes_per_page * inc_page_count; + heap_offset = (uint64)num_bytes_per_page * init_page_count; + heap_size = (uint64)num_bytes_per_page * inc_page_count; if (heap_size > 0) heap_size -= 1 * BH_KB; } @@ -897,34 +910,26 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, "try using `--heap-size=0` option"); return NULL; } - else if (init_page_count == DEFAULT_MAX_PAGES) { - num_bytes_per_page = UINT32_MAX; - init_page_count = max_page_count = 1; - } if (max_page_count > DEFAULT_MAX_PAGES) max_page_count = DEFAULT_MAX_PAGES; } - else { /* heap_size == 0 */ - if (init_page_count == DEFAULT_MAX_PAGES) { - num_bytes_per_page = UINT32_MAX; - init_page_count = max_page_count = 1; - } - } LOG_VERBOSE("Memory instantiate:"); LOG_VERBOSE(" page bytes: %u, init pages: %u, max pages: %u", num_bytes_per_page, init_page_count, max_page_count); - LOG_VERBOSE(" data offset: %u, stack size: %d", module->aux_data_end, - module->aux_stack_size); - LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size); + LOG_VERBOSE(" data offset: %" PRIu64 ", stack size: %d", + module->aux_data_end, module->aux_stack_size); + LOG_VERBOSE(" heap offset: %" PRIu64 ", heap size: %d\n", heap_offset, + heap_size); max_memory_data_size = (uint64)num_bytes_per_page * max_page_count; - bh_assert(max_memory_data_size <= 4 * (uint64)BH_GB); + bh_assert(max_memory_data_size <= MAX_LINEAR_MEMORY_SIZE); (void)max_memory_data_size; - if (wasm_allocate_linear_memory(&p, is_shared_memory, num_bytes_per_page, - init_page_count, max_page_count, - &memory_data_size) + /* TODO: memory64 uses is_memory64 flag */ + if (wasm_allocate_linear_memory(&p, is_shared_memory, false, + num_bytes_per_page, init_page_count, + max_page_count, &memory_data_size) != BHT_OK) { set_error_buf(error_buf, error_buf_size, "allocate linear memory failed"); @@ -935,11 +940,11 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, memory_inst->num_bytes_per_page = num_bytes_per_page; memory_inst->cur_page_count = init_page_count; memory_inst->max_page_count = max_page_count; - memory_inst->memory_data_size = (uint32)memory_data_size; + memory_inst->memory_data_size = memory_data_size; /* Init memory info */ memory_inst->memory_data = p; - memory_inst->memory_data_end = p + (uint32)memory_data_size; + memory_inst->memory_data_end = p + memory_data_size; /* Initialize heap info */ memory_inst->heap_data = p + heap_offset; @@ -995,7 +1000,8 @@ aot_get_default_memory(AOTModuleInstance *module_inst) static bool memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, - AOTModule *module, uint32 heap_size, char *error_buf, + AOTModule *module, uint32 heap_size, + uint32 max_memory_pages, char *error_buf, uint32 error_buf_size) { uint32 global_index, global_data_offset, base_offset, length; @@ -1016,9 +1022,9 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, memories = module_inst->global_table_data.memory_instances; for (i = 0; i < memory_count; i++, memories++) { - memory_inst = memory_instantiate(module_inst, parent, module, memories, - &module->memories[i], i, heap_size, - error_buf, error_buf_size); + memory_inst = memory_instantiate( + module_inst, parent, module, memories, &module->memories[i], i, + heap_size, max_memory_pages, error_buf, error_buf_size); if (!memory_inst) { return false; } @@ -1088,8 +1094,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, /* Check memory data */ /* check offset since length might negative */ if (base_offset > memory_inst->memory_data_size) { - LOG_DEBUG("base_offset(%d) > memory_data_size(%d)", base_offset, - memory_inst->memory_data_size); + LOG_DEBUG("base_offset(%d) > memory_data_size(%" PRIu64 ")", + base_offset, memory_inst->memory_data_size); #if WASM_ENABLE_REF_TYPES != 0 set_error_buf(error_buf, error_buf_size, "out of bounds memory access"); @@ -1103,7 +1109,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, /* check offset + length(could be zero) */ length = data_seg->byte_count; if (base_offset + length > memory_inst->memory_data_size) { - LOG_DEBUG("base_offset(%d) + length(%d) > memory_data_size(%d)", + LOG_DEBUG("base_offset(%d) + length(%d) > memory_data_size(%" PRIu64 + ")", base_offset, length, memory_inst->memory_data_size); #if WASM_ENABLE_REF_TYPES != 0 set_error_buf(error_buf, error_buf_size, @@ -1117,7 +1124,7 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, if (memory_inst->memory_data) { bh_memcpy_s((uint8 *)memory_inst->memory_data + base_offset, - memory_inst->memory_data_size - base_offset, + (uint32)memory_inst->memory_data_size - base_offset, data_seg->bytes, length); } } @@ -1292,7 +1299,7 @@ lookup_post_instantiate_func(AOTModuleInstance *module_inst, AOTFunctionInstance *func; AOTFuncType *func_type; - if (!(func = aot_lookup_function(module_inst, func_name, NULL))) + if (!(func = aot_lookup_function(module_inst, func_name))) /* Not found */ return NULL; @@ -1484,7 +1491,7 @@ check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size) AOTModuleInstance * aot_instantiate(AOTModule *module, AOTModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size) + uint32 max_memory_pages, char *error_buf, uint32 error_buf_size) { AOTModuleInstance *module_inst; #if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0 @@ -1574,7 +1581,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, &((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list_head; ret = wasm_runtime_sub_module_instantiate( (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst, - stack_size, heap_size, error_buf, error_buf_size); + stack_size, heap_size, max_memory_pages, error_buf, error_buf_size); if (!ret) { LOG_DEBUG("build a sub module list failed"); goto fail; @@ -1636,8 +1643,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, goto fail; /* Initialize memory space */ - if (!memories_instantiate(module_inst, parent, module, heap_size, error_buf, - error_buf_size)) + if (!memories_instantiate(module_inst, parent, module, heap_size, + max_memory_pages, error_buf, error_buf_size)) goto fail; /* Initialize function pointers */ @@ -1928,9 +1935,8 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) if (module_inst->func_type_indexes) wasm_runtime_free(module_inst->func_type_indexes); - if (common->c_api_func_imports) - wasm_runtime_free(((AOTModuleInstanceExtra *)module_inst->e) - ->common.c_api_func_imports); + if (module_inst->c_api_func_imports) + wasm_runtime_free(module_inst->c_api_func_imports); #if WASM_ENABLE_GC != 0 if (!is_sub_inst) { @@ -1962,8 +1968,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) } AOTFunctionInstance * -aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, - const char *signature) +aot_lookup_function(const AOTModuleInstance *module_inst, const char *name) { uint32 i; AOTFunctionInstance *export_funcs = @@ -1972,7 +1977,6 @@ aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, for (i = 0; i < module_inst->export_func_count; i++) if (!strcmp(export_funcs[i].func_name, name)) return &export_funcs[i]; - (void)signature; return NULL; } @@ -2178,8 +2182,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, hw bound check is enabled */ #endif - /* Set exec env so it can be later retrieved from instance */ - ((AOTModuleInstanceExtra *)module_inst->e)->common.cur_exec_env = exec_env; + /* Set exec env, so it can be later retrieved from instance */ + module_inst->cur_exec_env = exec_env; if (ext_ret_count > 0) { uint32 cell_num = 0, i; @@ -2494,9 +2498,9 @@ execute_free_function(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, return ret; } -uint32 +uint64 aot_module_malloc_internal(AOTModuleInstance *module_inst, - WASMExecEnv *exec_env, uint32 size, + WASMExecEnv *exec_env, uint64 size, void **p_native_addr) { AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst); @@ -2504,38 +2508,37 @@ aot_module_malloc_internal(AOTModuleInstance *module_inst, uint8 *addr = NULL; uint32 offset = 0; + /* TODO: Memory64 size check based on memory idx type */ + bh_assert(size <= UINT32_MAX); + if (!memory_inst) { aot_set_exception(module_inst, "uninitialized memory"); return 0; } if (memory_inst->heap_handle) { - addr = mem_allocator_malloc(memory_inst->heap_handle, size); + addr = mem_allocator_malloc(memory_inst->heap_handle, (uint32)size); } else if (module->malloc_func_index != (uint32)-1 && module->free_func_index != (uint32)-1) { AOTFunctionInstance *malloc_func, *retain_func = NULL; char *malloc_func_name; - char *malloc_func_sig; if (module->retain_func_index != (uint32)-1) { malloc_func_name = "__new"; - malloc_func_sig = "(ii)i"; - retain_func = aot_lookup_function(module_inst, "__retain", "(i)i"); + retain_func = aot_lookup_function(module_inst, "__retain"); if (!retain_func) - retain_func = aot_lookup_function(module_inst, "__pin", "(i)i"); + retain_func = aot_lookup_function(module_inst, "__pin"); bh_assert(retain_func); } else { malloc_func_name = "malloc"; - malloc_func_sig = "(i)i"; } - malloc_func = - aot_lookup_function(module_inst, malloc_func_name, malloc_func_sig); + malloc_func = aot_lookup_function(module_inst, malloc_func_name); if (!malloc_func || !execute_malloc_function(module_inst, exec_env, malloc_func, - retain_func, size, &offset)) { + retain_func, (uint32)size, &offset)) { return 0; } addr = offset ? (uint8 *)memory_inst->memory_data + offset : NULL; @@ -2548,23 +2551,28 @@ aot_module_malloc_internal(AOTModuleInstance *module_inst, aot_set_exception(module_inst, "app heap corrupted"); } else { - LOG_WARNING("warning: allocate %u bytes memory failed", size); + LOG_WARNING("warning: allocate %" PRIu64 " bytes memory failed", + size); } return 0; } if (p_native_addr) *p_native_addr = addr; - return (uint32)(addr - memory_inst->memory_data); + return (uint64)(addr - memory_inst->memory_data); } -uint32 +uint64 aot_module_realloc_internal(AOTModuleInstance *module_inst, - WASMExecEnv *exec_env, uint32 ptr, uint32 size, + WASMExecEnv *exec_env, uint64 ptr, uint64 size, void **p_native_addr) { AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst); uint8 *addr = NULL; + /* TODO: Memory64 ptr and size check based on memory idx type */ + bh_assert(ptr <= UINT32_MAX); + bh_assert(size <= UINT32_MAX); + if (!memory_inst) { aot_set_exception(module_inst, "uninitialized memory"); return 0; @@ -2573,7 +2581,8 @@ aot_module_realloc_internal(AOTModuleInstance *module_inst, if (memory_inst->heap_handle) { addr = mem_allocator_realloc( memory_inst->heap_handle, - ptr ? memory_inst->memory_data + ptr : NULL, size); + (uint32)ptr ? memory_inst->memory_data + (uint32)ptr : NULL, + (uint32)size); } /* Only support realloc in WAMR's app heap */ @@ -2592,12 +2601,12 @@ aot_module_realloc_internal(AOTModuleInstance *module_inst, if (p_native_addr) *p_native_addr = addr; - return (uint32)(addr - memory_inst->memory_data); + return (uint64)(addr - memory_inst->memory_data); } void aot_module_free_internal(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, - uint32 ptr) + uint64 ptr) { AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst); AOTModule *module = (AOTModule *)module_inst->module; @@ -2606,8 +2615,11 @@ aot_module_free_internal(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, return; } + /* TODO: Memory64 ptr and size check based on memory idx type */ + bh_assert(ptr <= UINT32_MAX); + if (ptr) { - uint8 *addr = memory_inst->memory_data + ptr; + uint8 *addr = memory_inst->memory_data + (uint32)ptr; uint8 *memory_data_end; /* memory->memory_data_end may be changed in memory grow */ @@ -2632,26 +2644,26 @@ aot_module_free_internal(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, else { free_func_name = "free"; } - free_func = - aot_lookup_function(module_inst, free_func_name, "(i)i"); + free_func = aot_lookup_function(module_inst, free_func_name); if (!free_func && module->retain_func_index != (uint32)-1) - free_func = aot_lookup_function(module_inst, "__unpin", "(i)i"); + free_func = aot_lookup_function(module_inst, "__unpin"); if (free_func) - execute_free_function(module_inst, exec_env, free_func, ptr); + execute_free_function(module_inst, exec_env, free_func, + (uint32)ptr); } } } -uint32 -aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, +uint64 +aot_module_malloc(AOTModuleInstance *module_inst, uint64 size, void **p_native_addr) { return aot_module_malloc_internal(module_inst, NULL, size, p_native_addr); } -uint32 -aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size, +uint64 +aot_module_realloc(AOTModuleInstance *module_inst, uint64 ptr, uint64 size, void **p_native_addr) { return aot_module_realloc_internal(module_inst, NULL, ptr, size, @@ -2659,23 +2671,27 @@ aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size, } void -aot_module_free(AOTModuleInstance *module_inst, uint32 ptr) +aot_module_free(AOTModuleInstance *module_inst, uint64 ptr) { aot_module_free_internal(module_inst, NULL, ptr); } -uint32 +uint64 aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, - uint32 size) + uint64 size) { char *buffer; - uint32 buffer_offset = - aot_module_malloc(module_inst, size, (void **)&buffer); + uint64 buffer_offset; + + /* TODO: Memory64 size check based on memory idx type */ + bh_assert(size <= UINT32_MAX); + + buffer_offset = aot_module_malloc(module_inst, size, (void **)&buffer); if (buffer_offset != 0) { buffer = wasm_runtime_addr_app_to_native( (WASMModuleInstanceCommon *)module_inst, buffer_offset); - bh_memcpy_s(buffer, size, src, size); + bh_memcpy_s(buffer, (uint32)size, src, (uint32)size); } return buffer_offset; } @@ -2693,11 +2709,9 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, AOTModuleInstance *module_inst = (AOTModuleInstance *)wasm_runtime_get_module_inst(exec_env); AOTModule *aot_module = (AOTModule *)module_inst->module; - AOTModuleInstanceExtra *module_inst_extra = - (AOTModuleInstanceExtra *)module_inst->e; CApiFuncImport *c_api_func_import = - module_inst_extra->common.c_api_func_imports - ? module_inst_extra->common.c_api_func_imports + func_idx + module_inst->c_api_func_imports + ? module_inst->c_api_func_imports + func_idx : NULL; uint32 *func_type_indexes = module_inst->func_type_indexes; uint32 func_type_idx = func_type_indexes[func_idx]; @@ -2832,7 +2846,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, } #if WASM_ENABLE_GC == 0 - func_idx = tbl_elem_val; + func_idx = (uint32)tbl_elem_val; #else func_idx = wasm_func_obj_get_func_idx_bound((WASMFuncObjectRef)tbl_elem_val); @@ -2968,7 +2982,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, bool aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str, - uint32 app_buf_addr, uint32 app_buf_size, + uint64 app_buf_addr, uint64 app_buf_size, void **p_native_addr) { bool ret; @@ -3032,7 +3046,7 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset, } if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst, - dst, len)) + (uint64)dst, (uint64)len)) return false; if ((uint64)offset + (uint64)len > seg_len) { @@ -3041,10 +3055,11 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset, } maddr = wasm_runtime_addr_app_to_native( - (WASMModuleInstanceCommon *)module_inst, dst); + (WASMModuleInstanceCommon *)module_inst, (uint64)dst); SHARED_MEMORY_LOCK(memory_inst); - bh_memcpy_s(maddr, memory_inst->memory_data_size - dst, data + offset, len); + bh_memcpy_s(maddr, (uint32)(memory_inst->memory_data_size - dst), + data + offset, len); SHARED_MEMORY_UNLOCK(memory_inst); return true; } @@ -3063,14 +3078,14 @@ aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index) #if WASM_ENABLE_THREAD_MGR != 0 bool -aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) +aot_set_aux_stack(WASMExecEnv *exec_env, uint64 start_offset, uint32 size) { AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; AOTModule *module = (AOTModule *)module_inst->module; uint32 stack_top_idx = module->aux_stack_top_global_index; - uint32 data_end = module->aux_data_end; - uint32 stack_bottom = module->aux_stack_bottom; + uint64 data_end = module->aux_data_end; + uint64 stack_bottom = module->aux_stack_bottom; bool is_stack_before_data = stack_bottom < data_end ? true : false; /* Check the aux stack space, currently we don't allocate space in heap */ @@ -3083,12 +3098,13 @@ aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) set the initial value for the global */ uint32 global_offset = module->globals[stack_top_idx].data_offset; uint8 *global_addr = module_inst->global_data + global_offset; - *(int32 *)global_addr = start_offset; + /* TODO: Memory64 the type i32/i64 depends on memory idx type*/ + *(int32 *)global_addr = (uint32)start_offset; /* The aux stack boundary is a constant value, set the value to exec_env */ - exec_env->aux_stack_boundary.boundary = start_offset - size; - exec_env->aux_stack_bottom.bottom = start_offset; + exec_env->aux_stack_boundary = (uintptr_t)start_offset - size; + exec_env->aux_stack_bottom = (uintptr_t)start_offset; return true; } @@ -3096,14 +3112,14 @@ aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) } bool -aot_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size) +aot_get_aux_stack(WASMExecEnv *exec_env, uint64 *start_offset, uint32 *size) { AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; AOTModule *module = (AOTModule *)module_inst->module; /* The aux stack information is resolved in loader and store in module */ - uint32 stack_bottom = module->aux_stack_bottom; + uint64 stack_bottom = module->aux_stack_bottom; uint32 total_aux_stack_size = module->aux_stack_size; if (stack_bottom != 0 && total_aux_stack_size != 0) { @@ -3593,10 +3609,10 @@ aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index) if (exec_env->call_chain_size == 0) { // TODO: fix memory leak exec_env->restore_call_chain = NULL; - } + } LOG_DEBUG("restore call chain %zu==%u, %p, %p, %d\n", - ((AOTFrame *)exec_env->cur_frame)->func_index, func_index, - exec_env, exec_env->restore_call_chain, exec_env->handle); + ((AOTFrame *)exec_env->cur_frame)->func_index, func_index, + exec_env, exec_env->restore_call_chain, exec_env->handle); if (((AOTFrame *)exec_env->cur_frame)->func_index != func_index) { LOG_DEBUG("NOT MATCH!!!\n"); exit(1); @@ -3759,14 +3775,14 @@ aot_create_call_stack(struct WASMExecEnv *exec_env) frame.instance = module_inst; frame.module_offset = 0; - frame.func_index = cur_frame->func_index; - frame.func_offset = cur_frame->ip_offset; - frame.func_name_wp = - get_func_name_from_index(module_inst, cur_frame->func_index); + frame.func_index = (uint32)cur_frame->func_index; + frame.func_offset = (uint32)cur_frame->ip_offset; + frame.func_name_wp = get_func_name_from_index( + module_inst, (uint32)cur_frame->func_index); if (cur_frame->func_index >= module->import_func_count) { uint32 aot_func_idx = - cur_frame->func_index - module->import_func_count; + (uint32)(cur_frame->func_index - module->import_func_count); max_local_cell_num = module->max_local_cell_nums[aot_func_idx]; max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx]; } @@ -4726,3 +4742,74 @@ aot_traverse_gc_rootset(WASMExecEnv *exec_env, void *heap) return true; } #endif /* end of WASM_ENABLE_GC != 0 */ + +char * +aot_const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, +#if (WASM_ENABLE_WORD_ALIGN_READ != 0) + bool is_vram_word_align, +#endif + char *error_buf, uint32 error_buf_size) +{ + HashMap *set = module->const_str_set; + char *c_str, *value; + + /* Create const string set if it isn't created */ + if (!set + && !(set = module->const_str_set = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, NULL, wasm_runtime_free))) { + set_error_buf(error_buf, error_buf_size, + "create const string set failed"); + return NULL; + } + + /* Lookup const string set, use the string if found */ + if (!(c_str = runtime_malloc((uint32)len, error_buf, error_buf_size))) { + return NULL; + } +#if (WASM_ENABLE_WORD_ALIGN_READ != 0) + if (is_vram_word_align) { + bh_memcpy_wa(c_str, (uint32)len, str, (uint32)len); + } + else +#endif + { + bh_memcpy_s(c_str, len, str, (uint32)len); + } + + if ((value = bh_hash_map_find(set, c_str))) { + wasm_runtime_free(c_str); + return value; + } + + if (!bh_hash_map_insert(set, c_str, c_str)) { + set_error_buf(error_buf, error_buf_size, + "insert string to hash map failed"); + wasm_runtime_free(c_str); + return NULL; + } + + return c_str; +} + +bool +aot_set_module_name(AOTModule *module, const char *name, char *error_buf, + uint32_t error_buf_size) +{ + if (!name) + return false; + + module->name = aot_const_str_set_insert((const uint8 *)name, + (uint32)(strlen(name) + 1), module, +#if (WASM_ENABLE_WORD_ALIGN_READ != 0) + false, +#endif + error_buf, error_buf_size); + return module->name != NULL; +} + +const char * +aot_get_module_name(AOTModule *module) +{ + return module->name; +} diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 259cf09f7f..f2791ce601 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -246,19 +246,19 @@ typedef struct AOTModule { -1 means unexported */ uint32 aux_data_end_global_index; /* auxiliary __data_end exported by wasm app */ - uint32 aux_data_end; + uint64 aux_data_end; /* the index of auxiliary __heap_base global, -1 means unexported */ uint32 aux_heap_base_global_index; /* auxiliary __heap_base exported by wasm app */ - uint32 aux_heap_base; + uint64 aux_heap_base; /* the index of auxiliary stack top global, -1 means unexported */ uint32 aux_stack_top_global_index; /* auxiliary stack bottom resolved */ - uint32 aux_stack_bottom; + uint64 aux_stack_bottom; /* auxiliary stack size resolved */ uint32 aux_stack_size; @@ -307,6 +307,9 @@ typedef struct AOTModule { #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 WASMCustomSection *custom_section_list; #endif + + /* user defined name */ + char *name; } AOTModule; #define AOTMemoryInstance WASMMemoryInstance @@ -441,8 +444,8 @@ typedef struct LLVMProfileData_64 { * @return return AOT module loaded, NULL if failed */ AOTModule * -aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf, - uint32 error_buf_size); +aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args, + char *error_buf, uint32 error_buf_size); /** * Load a AOT module from a specified AOT section list. @@ -482,7 +485,8 @@ aot_unload(AOTModule *module); AOTModuleInstance * aot_instantiate(AOTModule *module, AOTModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size); + uint32 max_memory_pages, char *error_buf, + uint32 error_buf_size); /** * Deinstantiate a AOT module instance, destroy the resources. @@ -498,14 +502,12 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst); * * @param module_inst the module instance * @param name the name of the function - * @param signature the signature of the function, use "i32"/"i64"/"f32"/"f64" - * to represent the type of i32/i64/f32/f64, e.g. "(i32i64)" "(i32)f32" * * @return the function instance found */ AOTFunctionInstance * -aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, - const char *signature); +aot_lookup_function(const AOTModuleInstance *module_inst, const char *name); + /** * Call the given AOT function of a AOT module instance with * arguments. @@ -557,32 +559,32 @@ aot_get_exception(AOTModuleInstance *module_inst); bool aot_copy_exception(AOTModuleInstance *module_inst, char *exception_buf); -uint32 +uint64 aot_module_malloc_internal(AOTModuleInstance *module_inst, WASMExecEnv *env, - uint32 size, void **p_native_addr); + uint64 size, void **p_native_addr); -uint32 +uint64 aot_module_realloc_internal(AOTModuleInstance *module_inst, WASMExecEnv *env, - uint32 ptr, uint32 size, void **p_native_addr); + uint64 ptr, uint64 size, void **p_native_addr); void aot_module_free_internal(AOTModuleInstance *module_inst, WASMExecEnv *env, - uint32 ptr); + uint64 ptr); -uint32 -aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, +uint64 +aot_module_malloc(AOTModuleInstance *module_inst, uint64 size, void **p_native_addr); -uint32 -aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size, +uint64 +aot_module_realloc(AOTModuleInstance *module_inst, uint64 ptr, uint64 size, void **p_native_addr); void -aot_module_free(AOTModuleInstance *module_inst, uint32 ptr); +aot_module_free(AOTModuleInstance *module_inst, uint64 ptr); -uint32 +uint64 aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, - uint32 size); + uint64 size); bool aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count); @@ -604,7 +606,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, */ bool aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str, - uint32 app_buf_addr, uint32 app_buf_size, + uint64 app_buf_addr, uint64 app_buf_size, void **p_native_addr); uint32 @@ -633,10 +635,10 @@ aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index); #if WASM_ENABLE_THREAD_MGR != 0 bool -aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size); +aot_set_aux_stack(WASMExecEnv *exec_env, uint64 start_offset, uint32 size); bool -aot_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size); +aot_get_aux_stack(WASMExecEnv *exec_env, uint64 *start_offset, uint32 *size); #endif void @@ -765,6 +767,20 @@ bool aot_traverse_gc_rootset(WASMExecEnv *exec_env, void *heap); #endif /* end of WASM_ENABLE_GC != 0 */ +char * +aot_const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, +#if (WASM_ENABLE_WORD_ALIGN_READ != 0) + bool is_vram_word_align, +#endif + char *error_buf, uint32 error_buf_size); + +bool +aot_set_module_name(AOTModule *module, const char *name, char *error_buf, + uint32_t error_buf_size); + +const char * +aot_get_module_name(AOTModule *module); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/common/gc/gc_object.c b/core/iwasm/common/gc/gc_object.c index 57743a35d5..333effcf6f 100644 --- a/core/iwasm/common/gc/gc_object.c +++ b/core/iwasm/common/gc/gc_object.c @@ -189,6 +189,16 @@ wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj, } } +uint32 +wasm_struct_obj_get_field_count(const WASMStructObjectRef struct_obj) +{ + WASMRttTypeRef rtt_type = + (WASMRttTypeRef)wasm_object_header((WASMObjectRef)struct_obj); + WASMStructType *struct_type = (WASMStructType *)rtt_type->defined_type; + + return struct_type->field_count; +} + WASMArrayObjectRef wasm_array_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type, uint32 length, WASMValue *init_value) diff --git a/core/iwasm/common/gc/gc_object.h b/core/iwasm/common/gc/gc_object.h index 4c0cc4538b..2d13368816 100644 --- a/core/iwasm/common/gc/gc_object.h +++ b/core/iwasm/common/gc/gc_object.h @@ -157,6 +157,16 @@ void wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj, uint32 field_idx, bool sign_extend, WASMValue *value); +/** + * Return the field count of the WASM struct object. + * + * @param struct_obj the WASM struct object + * + * @return the field count of the WASM struct object + */ +uint32 +wasm_struct_obj_get_field_count(const WASMStructObjectRef struct_obj); + WASMArrayObjectRef wasm_array_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type, uint32 length, WASMValue *init_value); diff --git a/core/iwasm/common/gc/gc_type.c b/core/iwasm/common/gc/gc_type.c index 0c9271c873..60f0e7e7a0 100644 --- a/core/iwasm/common/gc/gc_type.c +++ b/core/iwasm/common/gc/gc_type.c @@ -148,7 +148,7 @@ wasm_dump_func_type(const WASMFuncType *type) os_printf("] -> ["); - for (; i < type->param_count + type->result_count; i++) { + for (; i < (uint32)(type->param_count + type->result_count); i++) { if (wasm_is_type_multi_byte_type(type->types[i])) { bh_assert(j < type->ref_type_map_count); bh_assert(i == type->ref_type_maps[j].index); @@ -264,7 +264,7 @@ wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2, || type1->ref_type_map_count != type2->ref_type_map_count) return false; - for (i = 0; i < type1->param_count + type1->result_count; i++) { + for (i = 0; i < (uint32)(type1->param_count + type1->result_count); i++) { if (type1->types[i] != type2->types[i]) return false; @@ -399,7 +399,7 @@ wasm_func_type_is_subtype_of(const WASMFuncType *type1, } } - for (; i < type1->param_count + type1->result_count; i++) { + for (; i < (uint32)(type1->param_count + type1->result_count); i++) { if (wasm_is_type_multi_byte_type(type1->types[i])) { bh_assert(j1 < type1->ref_type_map_count); ref_type1 = type1->ref_type_maps[j1++].ref_type; diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 4e5d17deb6..13ad2b1a6a 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -61,7 +61,7 @@ static union { * Implementation of wasm_application_execute_main() */ static bool -check_main_func_type(const WASMFuncType *type) +check_main_func_type(const WASMFuncType *type, bool is_memory64) { if (!(type->param_count == 0 || type->param_count == 2) || type->result_count > 1) { @@ -72,7 +72,8 @@ check_main_func_type(const WASMFuncType *type) if (type->param_count == 2 && !(type->types[0] == VALUE_TYPE_I32 - && type->types[1] == VALUE_TYPE_I32)) { + && type->types[1] + == (is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32))) { LOG_ERROR( "WASM execute application failed: invalid main function type.\n"); return false; @@ -94,14 +95,18 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) WASMFunctionInstanceCommon *func; WASMFuncType *func_type = NULL; WASMExecEnv *exec_env = NULL; - uint32 argc1 = 0, argv1[2] = { 0 }; + uint32 argc1 = 0, argv1[3] = { 0 }; uint32 total_argv_size = 0; uint64 total_size; - uint32 argv_buf_offset = 0; + uint64 argv_buf_offset = 0; int32 i; char *argv_buf, *p, *p_end; uint32 *argv_offsets, module_type; - bool ret, is_import_func = true; + bool ret, is_import_func = true, is_memory64 = false; +#if WASM_ENABLE_MEMORY64 != 0 + WASMModuleInstance *wasm_module_inst = (WASMModuleInstance *)module_inst; + is_memory64 = wasm_module_inst->memories[0]->is_memory64; +#endif exec_env = wasm_runtime_get_exec_env_singleton(module_inst); if (!exec_env) { @@ -147,10 +152,10 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) } #endif /* end of WASM_ENABLE_LIBC_WASI */ - if (!(func = wasm_runtime_lookup_function(module_inst, "main", NULL)) - && !(func = wasm_runtime_lookup_function(module_inst, - "__main_argc_argv", NULL)) - && !(func = wasm_runtime_lookup_function(module_inst, "_main", NULL))) { + if (!(func = wasm_runtime_lookup_function(module_inst, "main")) + && !(func = + wasm_runtime_lookup_function(module_inst, "__main_argc_argv")) + && !(func = wasm_runtime_lookup_function(module_inst, "_main"))) { #if WASM_ENABLE_LIBC_WASI != 0 wasm_runtime_set_exception( module_inst, "lookup the entry point symbol (like _start, main, " @@ -187,7 +192,7 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) return false; } - if (!check_main_func_type(func_type)) { + if (!check_main_func_type(func_type, is_memory64)) { wasm_runtime_set_exception(module_inst, "invalid function type of main function"); return false; @@ -202,7 +207,7 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) if (total_size >= UINT32_MAX || !(argv_buf_offset = wasm_runtime_module_malloc( - module_inst, (uint32)total_size, (void **)&argv_buf))) { + module_inst, total_size, (void **)&argv_buf))) { wasm_runtime_set_exception(module_inst, "allocate memory failed"); return false; } @@ -214,14 +219,25 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) for (i = 0; i < argc; i++) { bh_memcpy_s(p, (uint32)(p_end - p), argv[i], (uint32)(strlen(argv[i]) + 1)); - argv_offsets[i] = argv_buf_offset + (uint32)(p - argv_buf); + argv_offsets[i] = (uint32)argv_buf_offset + (uint32)(p - argv_buf); p += strlen(argv[i]) + 1; } - argc1 = 2; argv1[0] = (uint32)argc; - argv1[1] = - (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets); +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) { + argc1 = 3; + uint64 app_addr = + wasm_runtime_addr_native_to_app(module_inst, argv_offsets); + PUT_I64_TO_ADDR(&argv[1], app_addr); + } + else +#endif + { + argc1 = 2; + argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst, + argv_offsets); + } } ret = wasm_runtime_call_wasm(exec_env, func, argc1, argv1); @@ -336,8 +352,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, bh_assert(argc >= 0); LOG_DEBUG("call a function \"%s\" with %d arguments", name, argc); - if (!(target_func = - wasm_runtime_lookup_function(module_inst, name, NULL))) { + if (!(target_func = wasm_runtime_lookup_function(module_inst, name))) { snprintf(buf, sizeof(buf), "lookup function %s failed", name); wasm_runtime_set_exception(module_inst, buf); goto fail; diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index bffa870cf7..456ce505e2 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -2234,7 +2234,8 @@ try_reuse_loaded_module(wasm_store_t *store, char *binary_hash) #endif /* WASM_ENABLE_WASM_CACHE != 0 */ wasm_module_t * -wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) +wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary, + const LoadArgs *args) { char error_buf[128] = { 0 }; wasm_module_ex_t *module_ex = NULL; @@ -2290,8 +2291,8 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) if (!module_ex->binary->data) goto free_binary; - module_ex->module_comm_rt = wasm_runtime_load( - (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, + module_ex->module_comm_rt = wasm_runtime_load_ex( + (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, args, error_buf, (uint32)sizeof(error_buf)); if (!(module_ex->module_comm_rt)) { LOG_ERROR("%s", error_buf); @@ -2337,6 +2338,14 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) return NULL; } +wasm_module_t * +wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) +{ + LoadArgs args = { 0 }; + args.name = ""; + return wasm_module_new_ex(store, binary, &args); +} + bool wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) { @@ -2949,6 +2958,34 @@ wasm_shared_module_delete(own wasm_shared_module_t *shared_module) wasm_module_delete_internal((wasm_module_t *)shared_module); } +bool +wasm_module_set_name(wasm_module_t *module, const char *name) +{ + char error_buf[256] = { 0 }; + wasm_module_ex_t *module_ex = NULL; + + if (!module) + return false; + + module_ex = module_to_module_ext(module); + bool ret = wasm_runtime_set_module_name(module_ex->module_comm_rt, name, + error_buf, sizeof(error_buf) - 1); + if (!ret) + LOG_WARNING("set module name failed: %s", error_buf); + return ret; +} + +const char * +wasm_module_get_name(wasm_module_t *module) +{ + wasm_module_ex_t *module_ex = NULL; + if (!module) + return ""; + + module_ex = module_to_module_ext(module); + return wasm_runtime_get_module_name(module_ex->module_comm_rt); +} + static wasm_func_t * wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type, wasm_func_callback_t func_callback) @@ -3959,7 +3996,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index) if (index >= table_interp->cur_size) { return NULL; } - ref_idx = table_interp->elems[index]; + ref_idx = (uint32)table_interp->elems[index]; } #endif @@ -3970,7 +4007,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index) if (index >= table_aot->cur_size) { return NULL; } - ref_idx = table_aot->elems[index]; + ref_idx = (uint32)table_aot->elems[index]; } #endif @@ -4872,6 +4909,19 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, const wasm_extern_vec_t *imports, own wasm_trap_t **trap, const uint32 stack_size, const uint32 heap_size) +{ + InstantiationArgs inst_args = { 0 }; + inst_args.default_stack_size = stack_size; + inst_args.host_managed_heap_size = heap_size; + return wasm_instance_new_with_args_ex(store, module, imports, trap, + &inst_args); +} + +wasm_instance_t * +wasm_instance_new_with_args_ex(wasm_store_t *store, const wasm_module_t *module, + const wasm_extern_vec_t *imports, + own wasm_trap_t **trap, + const InstantiationArgs *inst_args) { char sub_error_buf[128] = { 0 }; char error_buf[256] = { 0 }; @@ -4911,8 +4961,8 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, * will do the linking result check at the end of wasm_runtime_instantiate */ - instance->inst_comm_rt = wasm_runtime_instantiate( - *module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf)); + instance->inst_comm_rt = wasm_runtime_instantiate_ex( + *module, inst_args, sub_error_buf, sizeof(sub_error_buf)); if (!instance->inst_comm_rt) { goto failed; } @@ -4926,19 +4976,17 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, /* create the c-api func import list */ #if WASM_ENABLE_INTERP != 0 if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { - WASMModuleInstanceExtra *e = - ((WASMModuleInstance *)instance->inst_comm_rt)->e; - p_func_imports = &(e->common.c_api_func_imports); + WASMModuleInstance *wasm_module_inst = + (WASMModuleInstance *)instance->inst_comm_rt; + p_func_imports = &(wasm_module_inst->c_api_func_imports); import_func_count = MODULE_INTERP(module)->import_function_count; } #endif #if WASM_ENABLE_AOT != 0 if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) { - AOTModuleInstanceExtra *e = - (AOTModuleInstanceExtra *)((AOTModuleInstance *) - instance->inst_comm_rt) - ->e; - p_func_imports = &(e->common.c_api_func_imports); + AOTModuleInstance *aot_module_inst = + (AOTModuleInstance *)instance->inst_comm_rt; + p_func_imports = &(aot_module_inst->c_api_func_imports); import_func_count = MODULE_AOT(module)->import_func_count; } #endif @@ -4952,7 +5000,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, goto failed; } - /* fill in module_inst->e->c_api_func_imports */ + /* fill in module_inst->c_api_func_imports */ for (i = 0; imports && i < imports->num_elems; i++) { wasm_func_t *func_host = NULL; wasm_extern_t *in = imports->data[i]; diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index ef881b6a29..ebd9f2048b 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -154,9 +154,9 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, /* Set the aux_stack_boundary and aux_stack_bottom */ if (module_inst->module_type == Wasm_Module_Bytecode) { WASMModule *module = ((WASMModuleInstance *)module_inst)->module; - exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom; - exec_env->aux_stack_boundary.boundary = - module->aux_stack_bottom - module->aux_stack_size; + exec_env->aux_stack_bottom = (uintptr_t)module->aux_stack_bottom; + exec_env->aux_stack_boundary = + (uintptr_t)module->aux_stack_bottom - module->aux_stack_size; #if WASM_ENABLE_GC != 0 gc_heap_handle = ((WASMModuleInstance *)module_inst)->e->common.gc_heap_pool; @@ -168,9 +168,9 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, if (module_inst->module_type == Wasm_Module_AoT) { AOTModule *module = (AOTModule *)((AOTModuleInstance *)module_inst)->module; - exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom; - exec_env->aux_stack_boundary.boundary = - module->aux_stack_bottom - module->aux_stack_size; + exec_env->aux_stack_bottom = (uintptr_t)module->aux_stack_bottom; + exec_env->aux_stack_boundary = + (uintptr_t)module->aux_stack_bottom - module->aux_stack_size; #if WASM_ENABLE_GC != 0 gc_heap_handle = ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e) @@ -179,7 +179,6 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, } #endif - #if WASM_ENABLE_THREAD_MGR != 0 /* Create a new cluster for this exec_env */ if (!(cluster = wasm_cluster_create(exec_env))) { diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index 4447c3e50c..11bbf77d23 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -62,16 +62,10 @@ typedef struct WASMExecEnv { WASMSuspendFlags suspend_flags; /* Auxiliary stack boundary */ - union { - uint32 boundary; - uintptr_t __padding__; - } aux_stack_boundary; + uintptr_t aux_stack_boundary; /* Auxiliary stack bottom */ - union { - uint32 bottom; - uintptr_t __padding__; - } aux_stack_bottom; + uintptr_t aux_stack_bottom; #if WASM_ENABLE_AOT != 0 /* Native symbol list, reserved */ @@ -123,6 +117,9 @@ typedef struct WASMExecEnv { /* whether current thread is detached */ bool thread_is_detached; + + /* whether the aux stack is allocated */ + bool is_aux_stack_allocated; #endif #if WASM_ENABLE_GC != 0 @@ -201,8 +198,7 @@ wasm_exec_env_destroy(WASMExecEnv *exec_env); static inline bool wasm_exec_env_is_aux_stack_managed_by_runtime(WASMExecEnv *exec_env) { - return exec_env->aux_stack_boundary.boundary != 0 - || exec_env->aux_stack_bottom.bottom != 0; + return exec_env->aux_stack_boundary != 0 || exec_env->aux_stack_bottom != 0; } /** diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index c50e6b744a..d0e153d04a 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -41,12 +41,12 @@ static void (*free_func)(void *ptr) = NULL; static unsigned int global_pool_size; -static uint32 +static uint64 align_as_and_cast(uint64 size, uint64 alignment) { uint64 aligned_size = (size + alignment - 1) & ~(alignment - 1); - return aligned_size > UINT32_MAX ? UINT32_MAX : (uint32)aligned_size; + return aligned_size; } static bool @@ -280,13 +280,13 @@ wasm_runtime_get_mem_alloc_info(mem_alloc_info_t *mem_alloc_info) return false; } - bool wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm, - uint32 app_offset, uint32 size) + uint64 app_offset, uint64 size) { WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst; + uint64 max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); @@ -300,8 +300,13 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm, goto fail; } - /* integer overflow check */ - if (app_offset > UINT32_MAX - size) { +#if WASM_ENABLE_MEMORY64 != 0 + if (memory_inst->is_memory64) + max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE; +#endif + /* boundary overflow check */ + if (size > max_linear_memory_size + || app_offset > max_linear_memory_size - size) { goto fail; } @@ -321,10 +326,10 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm, bool wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm, - uint32 app_str_offset) + uint64 app_str_offset) { WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; - uint32 app_end_offset; + uint64 app_end_offset, max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE; char *str, *str_end; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode @@ -338,6 +343,16 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm, &app_end_offset)) goto fail; +#if WASM_ENABLE_MEMORY64 != 0 + if (module_inst->memories[0]->is_memory64) + max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE; +#endif + /* boundary overflow check, max start offset can only be size - 1, while end + * offset can be size */ + if (app_str_offset >= max_linear_memory_size + || app_end_offset > max_linear_memory_size) + goto fail; + str = wasm_runtime_addr_app_to_native(module_inst_comm, app_str_offset); str_end = str + (app_end_offset - app_str_offset); while (str < str_end && *str != '\0') @@ -353,11 +368,12 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm, bool wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm, - void *native_ptr, uint32 size) + void *native_ptr, uint64 size) { WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst; uint8 *addr = (uint8 *)native_ptr; + uint64 max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); @@ -371,8 +387,12 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm, goto fail; } - /* integer overflow check */ - if ((uintptr_t)addr > UINTPTR_MAX - size) { +#if WASM_ENABLE_MEMORY64 != 0 + if (memory_inst->is_memory64) + max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE; +#endif + /* boundary overflow check */ + if (size > max_linear_memory_size || (uintptr_t)addr > UINTPTR_MAX - size) { goto fail; } @@ -393,7 +413,7 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm, void * wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm, - uint32 app_offset) + uint64 app_offset) { WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst; @@ -412,7 +432,7 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm, SHARED_MEMORY_LOCK(memory_inst); - addr = memory_inst->memory_data + app_offset; + addr = memory_inst->memory_data + (uintptr_t)app_offset; if (bounds_checks) { if (memory_inst->memory_data <= addr @@ -420,18 +440,16 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm, SHARED_MEMORY_UNLOCK(memory_inst); return addr; } - } - /* If bounds checks is disabled, return the address directly */ - else if (app_offset != 0) { SHARED_MEMORY_UNLOCK(memory_inst); - return addr; + return NULL; } + /* If bounds checks is disabled, return the address directly */ SHARED_MEMORY_UNLOCK(memory_inst); - return NULL; + return addr; } -uint32 +uint64 wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm, void *native_ptr) { @@ -439,7 +457,7 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm, WASMMemoryInstance *memory_inst; uint8 *addr = (uint8 *)native_ptr; bool bounds_checks; - uint32 ret; + uint64 ret; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); @@ -456,14 +474,14 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm, if (bounds_checks) { if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end) { - ret = (uint32)(addr - memory_inst->memory_data); + ret = (uint64)(addr - memory_inst->memory_data); SHARED_MEMORY_UNLOCK(memory_inst); return ret; } } /* If bounds checks is disabled, return the offset directly */ else if (addr != NULL) { - ret = (uint32)(addr - memory_inst->memory_data); + ret = (uint64)(addr - memory_inst->memory_data); SHARED_MEMORY_UNLOCK(memory_inst); return ret; } @@ -474,12 +492,12 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm, bool wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm, - uint32 app_offset, uint32 *p_app_start_offset, - uint32 *p_app_end_offset) + uint64 app_offset, uint64 *p_app_start_offset, + uint64 *p_app_end_offset) { WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst; - uint32 memory_data_size; + uint64 memory_data_size; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); @@ -542,21 +560,21 @@ wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst_comm, bool wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, - uint32 app_buf_addr, uint32 app_buf_size, + uint64 app_buf_addr, uint64 app_buf_size, void **p_native_addr) { WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst); uint8 *native_addr; bool bounds_checks; + bh_assert(app_buf_addr <= UINTPTR_MAX && app_buf_size <= UINTPTR_MAX); + if (!memory_inst) { wasm_set_exception(module_inst, "out of bounds memory access"); return false; } - SHARED_MEMORY_LOCK(memory_inst); - - native_addr = memory_inst->memory_data + app_buf_addr; + native_addr = memory_inst->memory_data + (uintptr_t)app_buf_addr; bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst); @@ -569,32 +587,32 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, /* No need to check the app_offset and buf_size if memory access boundary check with hardware trap is enabled */ -// #ifndef OS_ENABLE_HW_BOUND_CHECK -// SHARED_MEMORY_LOCK(memory_inst); - -// if (app_buf_addr >= memory_inst->memory_data_size) { -// goto fail; -// } - -// if (!is_str) { -// if (app_buf_size > memory_inst->memory_data_size - app_buf_addr) { -// goto fail; -// } -// } -// else { -// const char *str, *str_end; - -// /* The whole string must be in the linear memory */ -// str = (const char *)native_addr; -// str_end = (const char *)memory_inst->memory_data_end; -// while (str < str_end && *str != '\0') -// str++; -// if (str == str_end) -// goto fail; -// } - -// SHARED_MEMORY_UNLOCK(memory_inst); -// #endif +#ifndef OS_ENABLE_HW_BOUND_CHECK + SHARED_MEMORY_LOCK(memory_inst); + + if (app_buf_addr >= memory_inst->memory_data_size) { + goto fail; + } + + if (!is_str) { + if (app_buf_size > memory_inst->memory_data_size - app_buf_addr) { + goto fail; + } + } + else { + const char *str, *str_end; + + /* The whole string must be in the linear memory */ + str = (const char *)native_addr; + str_end = (const char *)memory_inst->memory_data_end; + while (str < str_end && *str != '\0') + str++; + if (str == str_end) + goto fail; + } + + SHARED_MEMORY_UNLOCK(memory_inst); +#endif SHARED_MEMORY_UNLOCK(memory_inst); @@ -700,9 +718,9 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) { WASMMemoryInstance *memory = wasm_get_default_memory(module); uint8 *memory_data_old, *memory_data_new, *heap_data_old; - uint32 num_bytes_per_page, heap_size, total_size_old = 0; + uint32 num_bytes_per_page, heap_size; uint32 cur_page_count, max_page_count, total_page_count; - uint64 total_size_new; + uint64 total_size_old = 0, total_size_new; bool ret = true, full_size_mmaped; enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR; @@ -746,18 +764,13 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) goto return_func; } - bh_assert(total_size_new <= 4 * (uint64)BH_GB); - if (total_size_new > UINT32_MAX) { - /* Resize to 1 page with size 4G-1 */ - num_bytes_per_page = UINT32_MAX; - total_page_count = max_page_count = 1; - total_size_new = UINT32_MAX; - } + bh_assert(total_size_new + <= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)); if (full_size_mmaped) { #ifdef BH_PLATFORM_WINDOWS if (!os_mem_commit(memory->memory_data_end, - (uint32)total_size_new - total_size_old, + (mem_offset_t)(total_size_new - total_size_old), MMAP_PROT_READ | MMAP_PROT_WRITE)) { ret = false; goto return_func; @@ -765,12 +778,12 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) #endif if (os_mprotect(memory->memory_data_end, - (uint32)total_size_new - total_size_old, + (mem_offset_t)(total_size_new - total_size_old), MMAP_PROT_READ | MMAP_PROT_WRITE) != 0) { #ifdef BH_PLATFORM_WINDOWS os_mem_decommit(memory->memory_data_end, - (uint32)total_size_new - total_size_old); + (mem_offset_t)(total_size_new - total_size_old)); #endif ret = false; goto return_func; @@ -785,9 +798,9 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) } } - if (!(memory_data_new = wasm_mremap_linear_memory( - memory_data_old, total_size_old, (uint32)total_size_new, - (uint32)total_size_new))) { + if (!(memory_data_new = + wasm_mremap_linear_memory(memory_data_old, total_size_old, + total_size_new, total_size_new))) { ret = false; goto return_func; } @@ -816,8 +829,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = total_page_count; memory->max_page_count = max_page_count; - SET_LINEAR_MEMORY_SIZE(memory, (uint32)total_size_new); - memory->memory_data_end = memory->memory_data + (uint32)total_size_new; + SET_LINEAR_MEMORY_SIZE(memory, total_size_new); + memory->memory_data_end = memory->memory_data + total_size_new; wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new); @@ -827,13 +840,11 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) - exec_env = - ((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env; + exec_env = ((WASMModuleInstance *)module)->cur_exec_env; #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) - exec_env = - ((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env; + exec_env = ((AOTModuleInstance *)module)->cur_exec_env; #endif enlarge_memory_error_cb(inc_page_count, total_size_old, 0, @@ -901,8 +912,9 @@ wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst) int wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, - uint64 num_bytes_per_page, uint64 init_page_count, - uint64 max_page_count, uint64 *memory_data_size) + bool is_memory64, uint64 num_bytes_per_page, + uint64 init_page_count, uint64 max_page_count, + uint64 *memory_data_size) { uint64 map_size, page_size; @@ -931,8 +943,17 @@ wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, page_size = os_getpagesize(); *memory_data_size = init_page_count * num_bytes_per_page; - bh_assert(*memory_data_size <= UINT32_MAX); - align_as_and_cast(*memory_data_size, page_size); + +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) { + bh_assert(*memory_data_size <= MAX_LINEAR_MEM64_MEMORY_SIZE); + } + else +#endif + { + bh_assert(*memory_data_size <= MAX_LINEAR_MEMORY_SIZE); + } + *memory_data_size = align_as_and_cast(*memory_data_size, page_size); if (map_size > 0) { if (!(*data = wasm_mmap_linear_memory(map_size, *memory_data_size))) { @@ -941,4 +962,4 @@ wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, } return BHT_OK; -} \ No newline at end of file +} diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index 381266b61d..a5dfefae99 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -9,16 +9,33 @@ #include "bh_common.h" #include "../include/wasm_export.h" #include "../interpreter/wasm_runtime.h" +#include "../common/wasm_shared_memory.h" #ifdef __cplusplus extern "C" { #endif -#if WASM_ENABLE_SHARED_MEMORY != 0 +#if WASM_ENABLE_SHARED_MEMORY != 0 && BH_ATOMIC_64_IS_ATOMIC != 0 #define GET_LINEAR_MEMORY_SIZE(memory) \ - BH_ATOMIC_32_LOAD(memory->memory_data_size) + BH_ATOMIC_64_LOAD(memory->memory_data_size) #define SET_LINEAR_MEMORY_SIZE(memory, size) \ - BH_ATOMIC_32_STORE(memory->memory_data_size, size) + BH_ATOMIC_64_STORE(memory->memory_data_size, size) +#elif WASM_ENABLE_SHARED_MEMORY != 0 +static inline uint64 +GET_LINEAR_MEMORY_SIZE(const WASMMemoryInstance *memory) +{ + SHARED_MEMORY_LOCK(memory); + uint64 memory_data_size = BH_ATOMIC_64_LOAD(memory->memory_data_size); + SHARED_MEMORY_UNLOCK(memory); + return memory_data_size; +} +static inline void +SET_LINEAR_MEMORY_SIZE(WASMMemoryInstance *memory, uint64 size) +{ + SHARED_MEMORY_LOCK(memory); + BH_ATOMIC_64_STORE(memory->memory_data_size, size); + SHARED_MEMORY_UNLOCK(memory); +} #else #define GET_LINEAR_MEMORY_SIZE(memory) memory->memory_data_size #define SET_LINEAR_MEMORY_SIZE(memory, size) memory->memory_data_size = size @@ -47,8 +64,9 @@ wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst); int wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, - uint64 num_bytes_per_page, uint64 init_page_count, - uint64 max_page_count, uint64 *memory_data_size); + bool is_memory64, uint64 num_bytes_per_page, + uint64 init_page_count, uint64 max_page_count, + uint64 *memory_data_size); #ifdef __cplusplus } diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 3cf7451e35..14b295ee7f 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -567,7 +567,12 @@ wasm_native_init() #if WASM_ENABLE_WASI_NN != 0 n_native_symbols = get_wasi_nn_export_apis(&native_symbols); - if (!wasm_native_register_natives("wasi_nn", native_symbols, +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 +#define wasi_nn_module_name "wasi_ephemeral_nn" +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ +#define wasi_nn_module_name "wasi_nn" +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ + if (!wasm_native_register_natives(wasi_nn_module_name, native_symbols, n_native_symbols)) goto fail; #endif diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 4617f739ad..42a42d6189 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -71,7 +71,7 @@ #if WASM_ENABLE_MULTI_MODULE != 0 /** * A safety insurance to prevent - * circular depencies which leads stack overflow + * circular dependencies which leads stack overflow * try to break early */ typedef struct LoadingModule { @@ -281,11 +281,11 @@ decode_insn(uint8 *insn) buffer, sizeof(buffer), runtime_address); +#if 0 /* Print current instruction */ - /* os_printf("%012" PRIX64 " ", runtime_address); puts(buffer); - */ +#endif return instruction.length; } @@ -570,8 +570,20 @@ wasm_runtime_exec_env_check(WASMExecEnv *exec_env) && exec_env->wasm_stack.top <= exec_env->wasm_stack.top_boundary; } -bool -wasm_runtime_init() +#if defined(OS_THREAD_MUTEX_INITIALIZER) +/** + * lock for wasm_runtime_init/wasm_runtime_full_init and runtime_ref_count + * Note: if the platform has mutex initializer, we use a global lock to + * lock the operations of runtime init/full_init, otherwise when there are + * operations happening simultaneously in multiple threads, developer + * must create the lock by himself, and use it to lock the operations + */ +static korp_mutex runtime_lock = OS_THREAD_MUTEX_INITIALIZER; +#endif +static int32 runtime_ref_count = 0; + +static bool +wasm_runtime_init_internal() { if (!wasm_runtime_memory_init(Alloc_With_System_Allocator, NULL)) return false; @@ -584,8 +596,32 @@ wasm_runtime_init() return true; } -void -wasm_runtime_destroy() +bool +wasm_runtime_init() +{ + bool ret = true; + +#if defined(OS_THREAD_MUTEX_INITIALIZER) + os_mutex_lock(&runtime_lock); +#endif + + bh_assert(runtime_ref_count >= 0); + if (runtime_ref_count == 0) { + ret = wasm_runtime_init_internal(); + } + if (ret) { + runtime_ref_count++; + } + +#if defined(OS_THREAD_MUTEX_INITIALIZER) + os_mutex_unlock(&runtime_lock); +#endif + + return ret; +} + +static void +wasm_runtime_destroy_internal() { #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 wasm_externref_map_destroy(); @@ -646,6 +682,24 @@ wasm_runtime_destroy() wasm_runtime_memory_destroy(); } +void +wasm_runtime_destroy() +{ +#if defined(OS_THREAD_MUTEX_INITIALIZER) + os_mutex_lock(&runtime_lock); +#endif + + bh_assert(runtime_ref_count > 0); + runtime_ref_count--; + if (runtime_ref_count == 0) { + wasm_runtime_destroy_internal(); + } + +#if defined(OS_THREAD_MUTEX_INITIALIZER) + os_mutex_unlock(&runtime_lock); +#endif +} + RunningMode wasm_runtime_get_default_running_mode(void) { @@ -668,8 +722,8 @@ wasm_runtime_get_gc_heap_size_default(void) } #endif -bool -wasm_runtime_full_init(RuntimeInitArgs *init_args) +static bool +wasm_runtime_full_init_internal(RuntimeInitArgs *init_args) { if (!wasm_runtime_memory_init(init_args->mem_alloc_type, &init_args->mem_alloc_option)) @@ -731,6 +785,30 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args) return true; } +bool +wasm_runtime_full_init(RuntimeInitArgs *init_args) +{ + bool ret = true; + +#if defined(OS_THREAD_MUTEX_INITIALIZER) + os_mutex_lock(&runtime_lock); +#endif + + bh_assert(runtime_ref_count >= 0); + if (runtime_ref_count == 0) { + ret = wasm_runtime_full_init_internal(init_args); + } + if (ret) { + runtime_ref_count++; + } + +#if defined(OS_THREAD_MUTEX_INITIALIZER) + os_mutex_unlock(&runtime_lock); +#endif + + return ret; +} + void wasm_runtime_set_log_level(log_level_t level) { @@ -971,7 +1049,7 @@ wasm_runtime_register_module_internal(const char *module_name, /* module hasn't been registered */ node = runtime_malloc(sizeof(WASMRegisteredModule), NULL, NULL, 0); if (!node) { - LOG_DEBUG("malloc WASMRegisteredModule failed. SZ=%d", + LOG_DEBUG("malloc WASMRegisteredModule failed. SZ=%zu", sizeof(WASMRegisteredModule)); return false; } @@ -1196,7 +1274,7 @@ wasm_runtime_is_built_in_module(const char *module_name) #if WASM_ENABLE_THREAD_MGR != 0 bool -wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, +wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint64 start_offset, uint32 size) { WASMModuleInstanceCommon *module_inst = @@ -1215,7 +1293,7 @@ wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, } bool -wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, +wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, uint64 *start_offset, uint32 *size) { WASMModuleInstanceCommon *module_inst = @@ -1261,11 +1339,15 @@ register_module_with_null_name(WASMModuleCommon *module_common, char *error_buf, } WASMModuleCommon * -wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, - uint32 error_buf_size) +wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args, + char *error_buf, uint32 error_buf_size) { WASMModuleCommon *module_common = NULL; + if (!args) { + return NULL; + } + if (get_package_type(buf, size) == Wasm_Module_Bytecode) { #if WASM_ENABLE_INTERP != 0 module_common = @@ -1273,13 +1355,13 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, #if WASM_ENABLE_MULTI_MODULE != 0 true, #endif - error_buf, error_buf_size); + args, error_buf, error_buf_size); #endif } else if (get_package_type(buf, size) == Wasm_Module_AoT) { #if WASM_ENABLE_AOT != 0 module_common = (WASMModuleCommon *)aot_load_from_aot_file( - buf, size, error_buf, error_buf_size); + buf, size, args, error_buf, error_buf_size); #endif } else { @@ -1295,10 +1377,21 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, LOG_DEBUG("WASM module load failed"); return NULL; } + + /*TODO: use file name as name and register with name? */ return register_module_with_null_name(module_common, error_buf, error_buf_size); } +WASMModuleCommon * +wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size) +{ + LoadArgs args = { 0 }; + args.name = ""; + return wasm_runtime_load_ex(buf, size, &args, error_buf, error_buf_size); +} + WASMModuleCommon * wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, char *error_buf, uint32 error_buf_size) @@ -1363,24 +1456,48 @@ wasm_runtime_unload(WASMModuleCommon *module) #endif } +uint32 +wasm_runtime_get_max_mem(uint32 max_memory_pages, uint32 module_init_page_count, + uint32 module_max_page_count) +{ + if (max_memory_pages == 0) { + /* Max memory not overwritten by runtime, use value from wasm module */ + return module_max_page_count; + } + + if (max_memory_pages < module_init_page_count) { + LOG_WARNING("Cannot override max memory with value lower than module " + "initial memory"); + return module_init_page_count; + } + + if (max_memory_pages > module_max_page_count) { + LOG_WARNING("Cannot override max memory with value greater than module " + "max memory"); + return module_max_page_count; + } + + return max_memory_pages; +} + WASMModuleInstanceCommon * wasm_runtime_instantiate_internal(WASMModuleCommon *module, WASMModuleInstanceCommon *parent, WASMExecEnv *exec_env_main, uint32 stack_size, - uint32 heap_size, char *error_buf, - uint32 error_buf_size) + uint32 heap_size, uint32 max_memory_pages, + char *error_buf, uint32 error_buf_size) { #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) return (WASMModuleInstanceCommon *)wasm_instantiate( (WASMModule *)module, (WASMModuleInstance *)parent, exec_env_main, - stack_size, heap_size, error_buf, error_buf_size); + stack_size, heap_size, max_memory_pages, error_buf, error_buf_size); #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) return (WASMModuleInstanceCommon *)aot_instantiate( (AOTModule *)module, (AOTModuleInstance *)parent, exec_env_main, - stack_size, heap_size, error_buf, error_buf_size); + stack_size, heap_size, max_memory_pages, error_buf, error_buf_size); #endif set_error_buf(error_buf, error_buf_size, "Instantiate module failed, invalid module type"); @@ -1391,9 +1508,21 @@ WASMModuleInstanceCommon * wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size) +{ + return wasm_runtime_instantiate_internal(module, NULL, NULL, stack_size, + heap_size, 0, error_buf, + error_buf_size); +} + +WASMModuleInstanceCommon * +wasm_runtime_instantiate_ex(WASMModuleCommon *module, + const InstantiationArgs *args, char *error_buf, + uint32 error_buf_size) { return wasm_runtime_instantiate_internal( - module, NULL, NULL, stack_size, heap_size, error_buf, error_buf_size); + module, NULL, NULL, args->default_stack_size, + args->host_managed_heap_size, args->max_memory_pages, error_buf, + error_buf_size); } void @@ -1581,11 +1710,11 @@ wasm_runtime_dump_module_inst_mem_consumption( } #endif - os_printf("WASM module inst memory consumption, total size: %u\n", + os_printf("WASM module inst memory consumption, total size: %lu\n", mem_conspn.total_size); os_printf(" module inst struct size: %u\n", mem_conspn.module_inst_struct_size); - os_printf(" memories size: %u\n", mem_conspn.memories_size); + os_printf(" memories size: %lu\n", mem_conspn.memories_size); os_printf(" app heap size: %u\n", mem_conspn.app_heap_size); os_printf(" tables size: %u\n", mem_conspn.tables_size); os_printf(" functions size: %u\n", mem_conspn.functions_size); @@ -1620,8 +1749,9 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) WASMModuleInstanceCommon *module_inst_common; WASMModuleCommon *module_common = NULL; void *heap_handle = NULL; - uint32 total_size = 0, app_heap_peak_size = 0; + uint32 app_heap_peak_size = 0; uint32 max_aux_stack_used = -1; + uint64 total_size = 0; module_inst_common = exec_env->module_inst; #if WASM_ENABLE_INTERP != 0 @@ -1671,7 +1801,7 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) wasm_runtime_dump_module_inst_mem_consumption(module_inst_common); wasm_runtime_dump_exec_env_mem_consumption(exec_env); os_printf("\nTotal memory consumption of module, module inst and " - "exec env: %u\n", + "exec env: %" PRIu64 "\n", total_size); os_printf("Total interpreter stack used: %u\n", exec_env->max_wasm_stack_used); @@ -1822,17 +1952,17 @@ wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function, WASMFunctionInstanceCommon * wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst, - const char *name, const char *signature) + const char *name) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) return (WASMFunctionInstanceCommon *)wasm_lookup_function( - (const WASMModuleInstance *)module_inst, name, signature); + (const WASMModuleInstance *)module_inst, name); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) return (WASMFunctionInstanceCommon *)aot_lookup_function( - (const AOTModuleInstance *)module_inst, name, signature); + (const AOTModuleInstance *)module_inst, name); #endif return NULL; } @@ -2742,9 +2872,9 @@ wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst) } #endif -uint32 +uint64 wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst, - WASMExecEnv *exec_env, uint32 size, + WASMExecEnv *exec_env, uint64 size, void **p_native_addr) { #if WASM_ENABLE_INTERP != 0 @@ -2760,10 +2890,10 @@ wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst, return 0; } -uint32 +uint64 wasm_runtime_module_realloc_internal(WASMModuleInstanceCommon *module_inst, - WASMExecEnv *exec_env, uint32 ptr, - uint32 size, void **p_native_addr) + WASMExecEnv *exec_env, uint64 ptr, + uint64 size, void **p_native_addr) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) @@ -2780,7 +2910,7 @@ wasm_runtime_module_realloc_internal(WASMModuleInstanceCommon *module_inst, void wasm_runtime_module_free_internal(WASMModuleInstanceCommon *module_inst, - WASMExecEnv *exec_env, uint32 ptr) + WASMExecEnv *exec_env, uint64 ptr) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { @@ -2798,8 +2928,8 @@ wasm_runtime_module_free_internal(WASMModuleInstanceCommon *module_inst, #endif } -uint32 -wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size, +uint64 +wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint64 size, void **p_native_addr) { #if WASM_ENABLE_INTERP != 0 @@ -2815,9 +2945,9 @@ wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size, return 0; } -uint32 -wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, - uint32 size, void **p_native_addr) +uint64 +wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint64 ptr, + uint64 size, void **p_native_addr) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) @@ -2833,7 +2963,7 @@ wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, } void -wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint32 ptr) +wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint64 ptr) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { @@ -2849,9 +2979,9 @@ wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint32 ptr) #endif } -uint32 +uint64 wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst, - const char *src, uint32 size) + const char *src, uint64 size) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { @@ -3638,7 +3768,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); typedef void (*NativeRawFuncPtr)(WASMExecEnv *, uint64 *); NativeRawFuncPtr invoke_native_raw = (NativeRawFuncPtr)func_ptr; - uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size; + uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size, arg_i64; uint32 *argv_src = argv, i, argc1, ptr_len; uint32 arg_i32; bool ret = false; @@ -3663,6 +3793,10 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, #endif { *(uint32 *)argv_dst = arg_i32 = *argv_src++; + /* TODO: memory64 if future there is a way for supporting + * wasm64 and wasm32 in libc at the same time, remove the + * macro control */ +#if WASM_ENABLE_MEMORY64 == 0 if (signature) { if (signature[i + 1] == '*') { /* param is a pointer */ @@ -3673,28 +3807,68 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, /* pointer without length followed */ ptr_len = 1; - if (!wasm_runtime_validate_app_addr(module, arg_i32, - ptr_len)) + if (!wasm_runtime_validate_app_addr( + module, (uint64)arg_i32, (uint64)ptr_len)) goto fail; *(uintptr_t *)argv_dst = - (uintptr_t)wasm_runtime_addr_app_to_native(module, - arg_i32); + (uintptr_t)wasm_runtime_addr_app_to_native( + module, (uint64)arg_i32); } else if (signature[i + 1] == '$') { /* param is a string */ - if (!wasm_runtime_validate_app_str_addr(module, - arg_i32)) + if (!wasm_runtime_validate_app_str_addr( + module, (uint64)arg_i32)) goto fail; *(uintptr_t *)argv_dst = - (uintptr_t)wasm_runtime_addr_app_to_native(module, - arg_i32); + (uintptr_t)wasm_runtime_addr_app_to_native( + module, (uint64)arg_i32); } } +#endif break; } case VALUE_TYPE_I64: +#if WASM_ENABLE_MEMORY64 != 0 + { + PUT_I64_TO_ADDR((uint32 *)argv_dst, + GET_I64_FROM_ADDR(argv_src)); + argv_src += 2; + arg_i64 = *argv_dst; + if (signature) { + /* TODO: memory64 pointer with length need a new symbol + * to represent type i64, with '~' still represent i32 + * length */ + if (signature[i + 1] == '*') { + /* param is a pointer */ + if (signature[i + 2] == '~') + /* pointer with length followed */ + ptr_len = *argv_src; + else + /* pointer without length followed */ + ptr_len = 1; + + if (!wasm_runtime_validate_app_addr(module, arg_i64, + (uint64)ptr_len)) + goto fail; + + *argv_dst = (uint64)wasm_runtime_addr_app_to_native( + module, arg_i64); + } + else if (signature[i + 1] == '$') { + /* param is a string */ + if (!wasm_runtime_validate_app_str_addr(module, + arg_i64)) + goto fail; + + *argv_dst = (uint64)wasm_runtime_addr_app_to_native( + module, arg_i64); + } + } + break; + } +#endif case VALUE_TYPE_F64: bh_memcpy_s(argv_dst, sizeof(uint64), argv_src, sizeof(uint32) * 2); @@ -3823,6 +3997,9 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, fail: if (argv1 != argv_buf) wasm_runtime_free(argv1); +#if WASM_ENABLE_MEMORY64 == 0 + (void)arg_i64; +#endif return ret; } @@ -4095,21 +4272,21 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* pointer without length followed */ ptr_len = 1; - if (!wasm_runtime_validate_app_addr(module, arg_i32, - ptr_len)) + if (!wasm_runtime_validate_app_addr( + module, (uint64)arg_i32, (uint64)ptr_len)) goto fail; arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native( - module, arg_i32); + module, (uint64)arg_i32); } else if (signature[i + 1] == '$') { /* param is a string */ - if (!wasm_runtime_validate_app_str_addr(module, - arg_i32)) + if (!wasm_runtime_validate_app_str_addr( + module, (uint64)arg_i32)) goto fail; arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native( - module, arg_i32); + module, (uint64)arg_i32); } } @@ -4470,21 +4647,21 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* pointer without length followed */ ptr_len = 1; - if (!wasm_runtime_validate_app_addr(module, arg_i32, - ptr_len)) + if (!wasm_runtime_validate_app_addr( + module, (uint64)arg_i32, (uint64)ptr_len)) goto fail; arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native( - module, arg_i32); + module, (uint64)arg_i32); } else if (signature[i + 1] == '$') { /* param is a string */ - if (!wasm_runtime_validate_app_str_addr(module, - arg_i32)) + if (!wasm_runtime_validate_app_str_addr( + module, (uint64)arg_i32)) goto fail; arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native( - module, arg_i32); + module, (uint64)arg_i32); } } @@ -4775,6 +4952,10 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, { arg_i32 = *argv_src++; arg_i64 = arg_i32; + /* TODO: memory64 if future there is a way for supporting + * wasm64 and wasm32 in libc at the same time, remove the + * macro control */ +#if WASM_ENABLE_MEMORY64 == 0 if (signature) { if (signature[i + 1] == '*') { /* param is a pointer */ @@ -4785,23 +4966,24 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* pointer without length followed */ ptr_len = 1; - if (!wasm_runtime_validate_app_addr(module, arg_i32, - ptr_len)) + if (!wasm_runtime_validate_app_addr( + module, (uint64)arg_i32, (uint64)ptr_len)) goto fail; arg_i64 = (uintptr_t)wasm_runtime_addr_app_to_native( - module, arg_i32); + module, (uint64)arg_i32); } else if (signature[i + 1] == '$') { /* param is a string */ - if (!wasm_runtime_validate_app_str_addr(module, - arg_i32)) + if (!wasm_runtime_validate_app_str_addr( + module, (uint64)arg_i32)) goto fail; arg_i64 = (uintptr_t)wasm_runtime_addr_app_to_native( - module, arg_i32); + module, (uint64)arg_i32); } } +#endif if (n_ints < MAX_REG_INTS) ints[n_ints++] = arg_i64; else @@ -4809,6 +4991,47 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, break; } case VALUE_TYPE_I64: +#if WASM_ENABLE_MEMORY64 != 0 + { + arg_i64 = GET_I64_FROM_ADDR(argv_src); + argv_src += 2; + if (signature) { + /* TODO: memory64 pointer with length need a new symbol + * to represent type i64, with '~' still represent i32 + * length */ + if (signature[i + 1] == '*') { + /* param is a pointer */ + if (signature[i + 2] == '~') + /* pointer with length followed */ + ptr_len = *argv_src; + else + /* pointer without length followed */ + ptr_len = 1; + + if (!wasm_runtime_validate_app_addr(module, arg_i64, + (uint64)ptr_len)) + goto fail; + + arg_i64 = (uint64)wasm_runtime_addr_app_to_native( + module, arg_i64); + } + else if (signature[i + 1] == '$') { + /* param is a string */ + if (!wasm_runtime_validate_app_str_addr(module, + arg_i64)) + goto fail; + + arg_i64 = (uint64)wasm_runtime_addr_app_to_native( + module, arg_i64); + } + } + if (n_ints < MAX_REG_INTS) + ints[n_ints++] = arg_i64; + else + stacks[n_stacks++] = arg_i64; + break; + } +#endif #if WASM_ENABLE_GC != 0 case REF_TYPE_FUNCREF: case REF_TYPE_EXTERNREF: @@ -5290,6 +5513,7 @@ wasm_externref_set_cleanup(WASMModuleInstanceCommon *module_inst, if (lookup_user_data.found) { void *key = (void *)(uintptr_t)lookup_user_data.externref_idx; ExternRefMapNode *node = bh_hash_map_find(externref_map, key); + bh_assert(node); node->cleanup = extern_obj_cleanup; ok = true; } @@ -6302,6 +6526,7 @@ wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module, bool ret = false; uint8 *buffer = NULL; uint32 buffer_size = 0; + LoadArgs args = { 0 }; /* check the registered module list of the parent */ sub_module = wasm_runtime_search_sub_module(parent_module, sub_module_name); @@ -6341,23 +6566,25 @@ wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module, if (!ret) { LOG_DEBUG("read the file of %s failed", sub_module_name); set_error_buf_v(parent_module, error_buf, error_buf_size, - "unknown import", sub_module_name); + "unknown import %s", sub_module_name); goto delete_loading_module; } if (get_package_type(buffer, buffer_size) != parent_module->module_type) { LOG_DEBUG("moudle %s type error", sub_module_name); - goto delete_loading_module; + goto destroy_file_buffer; } + + args.name = (char *)sub_module_name; if (get_package_type(buffer, buffer_size) == Wasm_Module_Bytecode) { #if WASM_ENABLE_INTERP != 0 - sub_module = (WASMModuleCommon *)wasm_load(buffer, buffer_size, false, - error_buf, error_buf_size); + sub_module = (WASMModuleCommon *)wasm_load( + buffer, buffer_size, false, &args, error_buf, error_buf_size); #endif } else if (get_package_type(buffer, buffer_size) == Wasm_Module_AoT) { #if WASM_ENABLE_AOT != 0 sub_module = (WASMModuleCommon *)aot_load_from_aot_file( - buffer, buffer_size, error_buf, error_buf_size); + buffer, buffer_size, &args, error_buf, error_buf_size); #endif } if (!sub_module) { @@ -6413,7 +6640,8 @@ bool wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, WASMModuleInstanceCommon *module_inst, uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size) + uint32 max_memory_pages, char *error_buf, + uint32 error_buf_size) { bh_list *sub_module_inst_list = NULL; WASMRegisteredModule *sub_module_list_node = NULL; @@ -6441,8 +6669,8 @@ wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, WASMModuleCommon *sub_module = sub_module_list_node->module; WASMModuleInstanceCommon *sub_module_inst = NULL; sub_module_inst = wasm_runtime_instantiate_internal( - sub_module, NULL, NULL, stack_size, heap_size, error_buf, - error_buf_size); + sub_module, NULL, NULL, stack_size, heap_size, max_memory_pages, + error_buf, error_buf_size); if (!sub_module_inst) { LOG_DEBUG("instantiate %s failed", sub_module_list_node->module_name); @@ -6451,7 +6679,7 @@ wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, sub_module_inst_list_node = loader_malloc(sizeof(WASMSubModInstNode), error_buf, error_buf_size); if (!sub_module_inst_list_node) { - LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d", + LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ: %zu", sizeof(WASMSubModInstNode)); if (sub_module_inst) wasm_runtime_deinstantiate_internal(sub_module_inst, false); @@ -6571,3 +6799,44 @@ wasm_runtime_invoke_native_shim(WASMExecEnv *exec_env, void *func_ptr, return ret; } #endif + +bool +wasm_runtime_set_module_name(wasm_module_t module, const char *name, + char *error_buf, uint32_t error_buf_size) +{ + if (!module) + return false; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) + return wasm_set_module_name((WASMModule *)module, name, error_buf, + error_buf_size); +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) + return aot_set_module_name((AOTModule *)module, name, error_buf, + error_buf_size); +#endif + + return false; +} + +const char * +wasm_runtime_get_module_name(wasm_module_t module) +{ + if (!module) + return ""; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) + return wasm_get_module_name((WASMModule *)module); +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) + return aot_get_module_name((AOTModule *)module); +#endif + + return ""; +} diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 4cf3f11fdb..e85678509b 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -373,7 +373,7 @@ typedef struct WASMModuleCommon { /* The following uint8[1] member is a dummy just to indicate some module_type dependent members follow. - Typically it should be accessed by casting to the corresponding + Typically, it should be accessed by casting to the corresponding actual module_type dependent structure, not via this member. */ uint8 module_data[1]; } WASMModuleCommon; @@ -389,7 +389,7 @@ typedef struct WASMModuleInstanceCommon { /* The following uint8[1] member is a dummy just to indicate some module_type dependent members follow. - Typically it should be accessed by casting to the corresponding + Typically, it should be accessed by casting to the corresponding actual module_type dependent structure, not via this member. */ uint8 module_inst_data[1]; } WASMModuleInstanceCommon; @@ -413,10 +413,10 @@ typedef struct WASMModuleMemConsumption { } WASMModuleMemConsumption; typedef struct WASMModuleInstMemConsumption { - uint32 total_size; + uint64 total_size; uint32 module_inst_struct_size; - uint32 memories_size; uint32 app_heap_size; + uint64 memories_size; uint32 tables_size; uint32 globals_size; uint32 functions_size; @@ -561,13 +561,18 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, WASM_RUNTIME_API_EXTERN void wasm_runtime_unload(WASMModuleCommon *module); +/* Internal API */ +uint32 +wasm_runtime_get_max_mem(uint32 max_memory_pages, uint32 module_init_page_count, + uint32 module_max_page_count); + /* Internal API */ WASMModuleInstanceCommon * wasm_runtime_instantiate_internal(WASMModuleCommon *module, WASMModuleInstanceCommon *parent, WASMExecEnv *exec_env_main, uint32 stack_size, - uint32 heap_size, char *error_buf, - uint32 error_buf_size); + uint32 heap_size, uint32 max_memory_pages, + char *error_buf, uint32 error_buf_size); /* Internal API */ void @@ -580,6 +585,12 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 default_stack_size, uint32 host_managed_heap_size, char *error_buf, uint32 error_buf_size); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon * +wasm_runtime_instantiate_ex(WASMModuleCommon *module, + const InstantiationArgs *args, char *error_buf, + uint32 error_buf_size); + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_set_running_mode(wasm_module_inst_t module_inst, @@ -600,7 +611,7 @@ wasm_runtime_get_module(WASMModuleInstanceCommon *module_inst); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon * wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst, - const char *name, const char *signature); + const char *name); /* Internal API */ WASMFuncType * @@ -759,66 +770,66 @@ WASM_RUNTIME_API_EXTERN void * wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst); /* Internal API */ -uint32 +uint64 wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst, - WASMExecEnv *exec_env, uint32 size, + WASMExecEnv *exec_env, uint64 size, void **p_native_addr); /* Internal API */ -uint32 +uint64 wasm_runtime_module_realloc_internal(WASMModuleInstanceCommon *module_inst, - WASMExecEnv *exec_env, uint32 ptr, - uint32 size, void **p_native_addr); + WASMExecEnv *exec_env, uint64 ptr, + uint64 size, void **p_native_addr); /* Internal API */ void wasm_runtime_module_free_internal(WASMModuleInstanceCommon *module_inst, - WASMExecEnv *exec_env, uint32 ptr); + WASMExecEnv *exec_env, uint64 ptr); /* See wasm_export.h for description */ -WASM_RUNTIME_API_EXTERN uint32 -wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size, +WASM_RUNTIME_API_EXTERN uint64 +wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint64 size, void **p_native_addr); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN void -wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint32 ptr); +wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint64 ptr); /* See wasm_export.h for description */ -WASM_RUNTIME_API_EXTERN uint32 +WASM_RUNTIME_API_EXTERN uint64 wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst, - const char *src, uint32 size); + const char *src, uint64 size); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst, - uint32 app_offset, uint32 size); + uint64 app_offset, uint64 size); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst, - uint32 app_str_offset); + uint64 app_str_offset); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst, - void *native_ptr, uint32 size); + void *native_ptr, uint64 size); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN void * wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst, - uint32 app_offset); + uint64 app_offset); /* See wasm_export.h for description */ -WASM_RUNTIME_API_EXTERN uint32 +WASM_RUNTIME_API_EXTERN uint64 wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst, void *native_ptr); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst, - uint32 app_offset, uint32 *p_app_start_offset, - uint32 *p_app_end_offset); + uint64 app_offset, uint64 *p_app_start_offset, + uint64 *p_app_end_offset); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool @@ -887,7 +898,8 @@ bool wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, WASMModuleInstanceCommon *module_inst, uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size); + uint32 max_memory_pages, char *error_buf, + uint32 error_buf_size); void wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst); #endif @@ -904,11 +916,11 @@ wasm_runtime_is_built_in_module(const char *module_name); #if WASM_ENABLE_THREAD_MGR != 0 bool -wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, +wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, uint64 *start_offset, uint32 *size); bool -wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, +wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint64 start_offset, uint32 size); #endif @@ -1086,9 +1098,9 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, #define wasm_runtime_invoke_native wasm_runtime_invoke_native_shim bool wasm_runtime_invoke_native_shim(WASMExecEnv *exec_env, void *func_ptr, - const WASMType *func_type, const char *signature, - void *attachment, uint32 *argv, uint32 argc, - uint32 *argv_ret); + const WASMType *func_type, + const char *signature, void *attachment, + uint32 *argv, uint32 argc, uint32 *argv_ret); #endif void wasm_runtime_read_v128(const uint8 *bytes, uint64 *ret1, uint64 *ret2); @@ -1187,11 +1199,9 @@ wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env); #if WASM_ENABLE_CHECKPOINT_RESTORE != 0 bool -wasm_runtime_checkpoint(wasm_module_inst_t module_inst, - char *file); +wasm_runtime_checkpoint(wasm_module_inst_t module_inst, char *file); bool -wasm_runtime_restore(wasm_module_inst_t module_inst, - char *file, char *file1); +wasm_runtime_restore(wasm_module_inst_t module_inst, char *file, char *file1); #endif #if WASM_ENABLE_LINUX_PERF != 0 diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index 4845314269..c0b68e05f6 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -316,11 +316,11 @@ typedef struct AOTCompData { uint32 retain_func_index; uint32 aux_data_end_global_index; - uint32 aux_data_end; + uint64 aux_data_end; uint32 aux_heap_base_global_index; - uint32 aux_heap_base; + uint64 aux_heap_base; uint32 aux_stack_top_global_index; - uint32 aux_stack_bottom; + uint64 aux_stack_bottom; uint32 aux_stack_size; #if WASM_ENABLE_STRINGREF != 0 diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 9503ac7900..9bbeba0bef 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -330,7 +330,7 @@ aot_gen_commit_values(AOTCompFrame *frame) if (!p->dirty) continue; - n = p - frame->lp; + n = (uint32)(p - frame->lp); /* Commit reference flag */ if (comp_ctx->enable_gc) { @@ -432,7 +432,7 @@ aot_gen_commit_values(AOTCompFrame *frame) continue; p->dirty = 0; - n = p - frame->lp; + n = (uint32)(p - frame->lp); /* Commit values */ switch (p->type) { @@ -538,7 +538,7 @@ aot_gen_commit_values(AOTCompFrame *frame) /* Clear reference flags for unused stack slots. */ for (p = frame->sp; p < end; p++) { bh_assert(!p->ref); - n = p - frame->lp; + n = (uint32)(p - frame->lp); /* Commit reference flag. */ if (p->ref != p->committed_ref - 1) { @@ -621,7 +621,7 @@ aot_gen_commit_sp_ip(AOTCompFrame *frame, bool commit_sp, bool commit_ip) } if (commit_sp) { - n = sp - frame->lp; + n = (uint32)(sp - frame->lp); value = I32_CONST(offset_of_local(comp_ctx, n)); if (!value) { aot_set_last_error("llvm build const failed"); @@ -980,7 +980,6 @@ load_value(AOTCompContext *comp_ctx, uint8 value_type, LLVMValueRef cur_frame, return res; } - bool aot_gen_restore_values(AOTCompFrame *frame) { @@ -1069,55 +1068,62 @@ aot_gen_restore_values(AOTCompFrame *frame) return true; } - bool aot_gen_checkpoint(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, const uint8 *frame_ip) { comp_ctx->inst_checkpointed = true; - bool disable_commit = comp_ctx->checkpoint_type != 0 && comp_ctx->exp_disable_commit_sp_ip; - bool disable_restore_jump = comp_ctx->checkpoint_type != 0 && comp_ctx->exp_disable_restore_jump; - bool disable_gen_fence_int3 = comp_ctx->checkpoint_type != 0 && comp_ctx->exp_disable_gen_fence_int3; + bool disable_commit = + comp_ctx->checkpoint_type != 0 && comp_ctx->exp_disable_commit_sp_ip; + bool disable_restore_jump = + comp_ctx->checkpoint_type != 0 && comp_ctx->exp_disable_restore_jump; + bool disable_gen_fence_int3 = + comp_ctx->checkpoint_type != 0 && comp_ctx->exp_disable_gen_fence_int3; if (disable_commit) { - } else { + } + else { if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp, - frame_ip)) + frame_ip)) return false; if (!aot_gen_commit_values(comp_ctx->aot_frame)) return false; } if (disable_gen_fence_int3) { - } else { + } + else { if (!aot_compile_emit_fence_nop(comp_ctx, func_ctx)) return false; } if (disable_restore_jump) { - } else { + } + else { char name[32]; LLVMBasicBlockRef block_restore_jump, block_restore_value; snprintf(name, sizeof(name), "restore-%zu", - (uint64)(uintptr_t)(frame_ip - func_ctx->aot_func->code)); + (uint64)(uintptr_t)(frame_ip - func_ctx->aot_func->code)); if (!(block_restore_value = LLVMAppendBasicBlockInContext( - comp_ctx->context, func_ctx->func, name))) { + comp_ctx->context, func_ctx->func, name))) { aot_set_last_error("add LLVM basic block failed."); return false; } snprintf(name, sizeof(name), "restore-jump-%zu", - (uint64)(uintptr_t)(frame_ip - func_ctx->aot_func->code)); + (uint64)(uintptr_t)(frame_ip - func_ctx->aot_func->code)); if (!(block_restore_jump = LLVMAppendBasicBlockInContext( - comp_ctx->context, func_ctx->func, name))) { + comp_ctx->context, func_ctx->func, name))) { aot_set_last_error("add LLVM basic block failed."); return false; } - LLVMMoveBasicBlockAfter(block_restore_value, - LLVMGetInsertBlock(comp_ctx->aot_frame_alloca_builder)); - LLVMMoveBasicBlockAfter(block_restore_jump, LLVMGetInsertBlock(comp_ctx->builder)); + LLVMMoveBasicBlockAfter( + block_restore_value, + LLVMGetInsertBlock(comp_ctx->aot_frame_alloca_builder)); + LLVMMoveBasicBlockAfter(block_restore_jump, + LLVMGetInsertBlock(comp_ctx->builder)); if (!LLVMBuildBr(comp_ctx->builder, block_restore_jump)) { aot_set_last_error("llvm build br failed."); @@ -1126,11 +1132,11 @@ aot_gen_checkpoint(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef ip_offset; if (comp_ctx->pointer_size == sizeof(uint64)) - ip_offset = - I64_CONST((uint64)(uintptr_t)(frame_ip - func_ctx->aot_func->code)); + ip_offset = I64_CONST( + (uint64)(uintptr_t)(frame_ip - func_ctx->aot_func->code)); else - ip_offset = - I32_CONST((uint32)(uintptr_t)(frame_ip - func_ctx->aot_func->code)); + ip_offset = I32_CONST( + (uint32)(uintptr_t)(frame_ip - func_ctx->aot_func->code)); LLVMAddCase(func_ctx->restore_switch, ip_offset, block_restore_value); LLVMPositionBuilderAtEnd(comp_ctx->builder, block_restore_value); @@ -1414,13 +1420,15 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) case WASM_OP_CALL: { uint8 *frame_ip_org = frame_ip; - if (comp_ctx->enable_checkpoint && !comp_ctx->inst_checkpointed) { + if (comp_ctx->enable_checkpoint + && !comp_ctx->inst_checkpointed) { bh_assert(comp_ctx->aot_frame); aot_gen_checkpoint(comp_ctx, func_ctx, frame_ip_org); } read_leb_uint32(frame_ip, frame_ip_end, func_idx); - if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, false, frame_ip_org)) + if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, false, + frame_ip_org)) return false; break; } @@ -1430,7 +1438,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) uint8 *frame_ip_org = frame_ip; uint32 tbl_idx; - if (comp_ctx->enable_checkpoint && !comp_ctx->inst_checkpointed) { + if (comp_ctx->enable_checkpoint + && !comp_ctx->inst_checkpointed) { bh_assert(comp_ctx->aot_frame); aot_gen_checkpoint(comp_ctx, func_ctx, frame_ip_org); } @@ -1460,7 +1469,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) } read_leb_uint32(frame_ip, frame_ip_end, func_idx); - if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, false, frame_ip)) + if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, false, + frame_ip)) return false; if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip)) return false; diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 89bb9f1bd4..1fa2af1ca7 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -25,73 +25,6 @@ } \ } while (0) -#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 -static bool -check_utf8_str(const uint8 *str, uint32 len) -{ - /* The valid ranges are taken from page 125, below link - https://www.unicode.org/versions/Unicode9.0.0/ch03.pdf */ - const uint8 *p = str, *p_end = str + len; - uint8 chr; - - while (p < p_end) { - chr = *p; - if (chr < 0x80) { - p++; - } - else if (chr >= 0xC2 && chr <= 0xDF && p + 1 < p_end) { - if (p[1] < 0x80 || p[1] > 0xBF) { - return false; - } - p += 2; - } - else if (chr >= 0xE0 && chr <= 0xEF && p + 2 < p_end) { - if (chr == 0xE0) { - if (p[1] < 0xA0 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { - return false; - } - } - else if (chr == 0xED) { - if (p[1] < 0x80 || p[1] > 0x9F || p[2] < 0x80 || p[2] > 0xBF) { - return false; - } - } - else if (chr >= 0xE1 && chr <= 0xEF) { - if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { - return false; - } - } - p += 3; - } - else if (chr >= 0xF0 && chr <= 0xF4 && p + 3 < p_end) { - if (chr == 0xF0) { - if (p[1] < 0x90 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF - || p[3] < 0x80 || p[3] > 0xBF) { - return false; - } - } - else if (chr >= 0xF1 && chr <= 0xF3) { - if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF - || p[3] < 0x80 || p[3] > 0xBF) { - return false; - } - } - else if (chr == 0xF4) { - if (p[1] < 0x80 || p[1] > 0x8F || p[2] < 0x80 || p[2] > 0xBF - || p[3] < 0x80 || p[3] > 0xBF) { - return false; - } - } - p += 4; - } - else { - return false; - } - } - return (p == p_end); -} -#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */ - /* Internal function in object file */ typedef struct AOTObjectFunc { char *func_name; @@ -850,7 +783,7 @@ get_init_data_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data, size += (uint32)sizeof(uint32) * 2; /* aux data/heap/stack data */ - size += sizeof(uint32) * 7; + size += sizeof(uint32) * 10; size += get_object_data_section_info_size(comp_ctx, obj_data); return size; @@ -1542,9 +1475,16 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, res = (uint32)res64; \ } while (0) +/* + * - transfer .name section in .wasm (comp_data->name_section_buf) to + * aot buf (comp_data->aot_name_section_buf) + * - leb128 to u32 + * - add `\0` at the end of every name, and adjust length(+1) + */ static uint32 get_name_section_size(AOTCompData *comp_data) { + /* original name section content in .wasm */ const uint8 *p = comp_data->name_section_buf, *p_end = comp_data->name_section_buf_end; uint8 *buf, *buf_end; @@ -1566,17 +1506,20 @@ get_name_section_size(AOTCompData *comp_data) aot_set_last_error("allocate memory for custom name section failed."); return 0; } + memset(buf, 0, (uint32)max_aot_buf_size); buf_end = buf + max_aot_buf_size; + /* the size of "name". it should be 4 */ read_leb_uint32(p, p_end, name_len); offset = align_uint(offset, 4); EMIT_U32(name_len); - if (!check_utf8_str(p, name_len)) { - aot_set_last_error("invalid UTF-8 encoding"); + if (name_len != 4 || p + name_len > p_end) { + aot_set_last_error("unexpected end"); return 0; } + /* "name" */ if (memcmp(p, "name", 4) != 0) { aot_set_last_error("invalid custom name section"); return 0; @@ -1626,9 +1569,18 @@ get_name_section_size(AOTCompData *comp_data) previous_func_index = func_index; read_leb_uint32(p, p_end, func_name_len); offset = align_uint(offset, 2); - EMIT_U16(func_name_len); + + /* emit a string ends with `\0` */ + if (func_name_len + 1 > UINT16_MAX) { + aot_set_last_error( + "emit string failed: string too long"); + goto fail; + } + /* extra 1 byte for \0 */ + EMIT_U16(func_name_len + 1); EMIT_BUF(p, func_name_len); p += func_name_len; + EMIT_U8(0); } } break; @@ -2409,11 +2361,11 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, EMIT_U32(comp_data->start_func_index); EMIT_U32(comp_data->aux_data_end_global_index); - EMIT_U32(comp_data->aux_data_end); + EMIT_U64(comp_data->aux_data_end); EMIT_U32(comp_data->aux_heap_base_global_index); - EMIT_U32(comp_data->aux_heap_base); + EMIT_U64(comp_data->aux_heap_base); EMIT_U32(comp_data->aux_stack_top_global_index); - EMIT_U32(comp_data->aux_stack_bottom); + EMIT_U64(comp_data->aux_stack_bottom); EMIT_U32(comp_data->aux_stack_size); if (!aot_emit_object_data_section_info(buf, buf_end, &offset, comp_ctx, @@ -3928,7 +3880,12 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data, * Note: aot_stack_sizes_section_name section only contains * stack_sizes table. */ - if (!strcmp(relocation->symbol_name, aot_stack_sizes_name)) { + if (!strcmp(relocation->symbol_name, aot_stack_sizes_name) + /* in windows 32, the symbol name may start with '_' */ + || (strlen(relocation->symbol_name) > 0 + && relocation->symbol_name[0] == '_' + && !strcmp(relocation->symbol_name + 1, + aot_stack_sizes_name))) { /* discard const */ relocation->symbol_name = (char *)aot_stack_sizes_section_name; } diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 54f2459e5d..6acfcd96dc 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -382,7 +382,9 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } #if WASM_ENABLE_DEBUG_AOT != 0 - LLVMInstructionSetDebugLoc(ret, return_location); + if (return_location != NULL) { + LLVMInstructionSetDebugLoc(ret, return_location); + } #endif } else { @@ -391,7 +393,9 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } #if WASM_ENABLE_DEBUG_AOT != 0 - LLVMInstructionSetDebugLoc(ret, return_location); + if (return_location != NULL) { + LLVMInstructionSetDebugLoc(ret, return_location); + } #endif } } @@ -1151,7 +1155,8 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (comp_ctx->enable_thread_mgr) { /* Commit sp when GC is enabled, don't commit ip */ - if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->enable_gc, false)) + if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, + comp_ctx->enable_gc, false)) return false; } @@ -1222,6 +1227,7 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, PUSH(values[j], target_block->result_types[j]); } wasm_runtime_free(values); + values = NULL; } target_block->is_reachable = true; if (i == br_count) @@ -1247,6 +1253,7 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, PUSH(values[j], target_block->param_types[j]); } wasm_runtime_free(values); + values = NULL; } if (i == br_count) default_llvm_block = target_block->llvm_entry_block; @@ -1313,7 +1320,7 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #endif // if (comp_ctx->aot_frame) - // call_aot_free_frame_func(comp_ctx, func_ctx); + // call_aot_free_frame_func(comp_ctx, func_ctx); if (block_func->result_count) { /* Store extra result values to function parameters */ for (i = 0; i < block_func->result_count - 1; i++) { diff --git a/core/iwasm/compilation/aot_emit_exception.c b/core/iwasm/compilation/aot_emit_exception.c index b4ebd2f0aa..fe81874cbe 100644 --- a/core/iwasm/compilation/aot_emit_exception.c +++ b/core/iwasm/compilation/aot_emit_exception.c @@ -88,6 +88,12 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build phi failed."); return false; } + + /* Commit ip to current frame */ + if (!commit_ip(comp_ctx, func_ctx, func_ctx->exception_ip_phi, + is_64bit)) { + return false; + } } /* Call aot_set_exception_with_id() to throw exception */ @@ -154,12 +160,6 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } - if (comp_ctx->aot_frame) { - if (!commit_ip(comp_ctx, func_ctx, func_ctx->exception_ip_phi, - is_64bit)) - return false; - } - /* Create return IR */ AOTFuncType *aot_func_type = func_ctx->aot_func->func_type; if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) { @@ -233,14 +233,14 @@ aot_compile_emit_fence_nop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) #if defined(BH_PLATFORM_WINDOWS) LLVMTypeRef param_types[] = { comp_ctx->exec_env_type, LLVMInt32Type() }; LLVMTypeRef ret_type = LLVMInt32Type(); - LLVMValueRef param_values[2], func; + LLVMValueRef param_values[2], func; - LLVMTypeRef func_type,func_ptr_type; + LLVMTypeRef func_type, func_ptr_type; GET_AOT_FUNCTION(aot_raise, 2); LLVMValueRef arg = LLVMConstInt(LLVMInt32Type(), 4, false); LLVMValueRef args[] = { func_ctx->exec_env, arg }; - if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, - func, args, 2, "call_aot_raise"))) { + if (!(value = LLVMBuildCall2(comp_ctx->builder, func_type, func, args, 2, + "call_aot_raise"))) { aot_set_last_error("llvm build call nop failed."); return false; } @@ -260,20 +260,18 @@ aot_compile_emit_fence_nop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) else { asm_string = strdup("svc 0"); } - if (!(inline_asm = - LLVMGetInlineAsm(ty, asm_string, strlen(asm_string), - "~{dirflag},~{fpsr},~{flags}", 27, true, - false, LLVMInlineAsmDialectATT, false))) { + if (!(inline_asm = LLVMGetInlineAsm( + ty, asm_string, strlen(asm_string), "~{dirflag},~{fpsr},~{flags}", + 27, true, false, LLVMInlineAsmDialectATT, false))) { aot_set_last_error("llvm build nop asm failed."); return false; } free(asm_string); - if (!(value = LLVMBuildCall2(comp_ctx->builder, ty, inline_asm, NULL, 0, - ""))) { + if (!(value = + LLVMBuildCall2(comp_ctx->builder, ty, inline_asm, NULL, 0, ""))) { aot_set_last_error("llvm build call nop failed."); return false; } #endif return true; - } \ No newline at end of file diff --git a/core/iwasm/compilation/aot_emit_exception.h b/core/iwasm/compilation/aot_emit_exception.h index f25f6b965d..cc02001771 100644 --- a/core/iwasm/compilation/aot_emit_exception.h +++ b/core/iwasm/compilation/aot_emit_exception.h @@ -16,7 +16,7 @@ bool aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, int32 exception_id, bool is_cond_br, LLVMValueRef cond_br_if, LLVMBasicBlockRef cond_br_else_block); -bool +bool aot_compile_emit_fence_nop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); #ifdef __cplusplus diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index a291d97a20..66df323194 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -331,13 +331,9 @@ call_aot_invoke_c_api_native(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_values[0] = func_ctx->aot_inst; - /* Get module_inst->e->common.c_api_func_imports */ - offset_c_api_func_imports = - get_module_inst_extra_offset(comp_ctx) - + (comp_ctx->is_jit_mode - ? offsetof(WASMModuleInstanceExtra, common.c_api_func_imports) - /* offsetof(AOTModuleInstanceExtra, common.c_api_func_imports) */ - : sizeof(uint64)); + /* Get module_inst->c_api_func_imports, jit mode WASMModuleInstance is the + * same layout with AOTModuleInstance */ + offset_c_api_func_imports = offsetof(AOTModuleInstance, c_api_func_imports); offset = I32_CONST(offset_c_api_func_imports); CHECK_LLVM_CONST(offset); c_api_func_imports = @@ -1139,8 +1135,8 @@ check_app_addr_and_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* prepare function type of aot_check_app_addr_and_convert */ func_param_types[0] = comp_ctx->aot_inst_type; /* module_inst */ func_param_types[1] = INT8_TYPE; /* is_str_arg */ - func_param_types[2] = I32_TYPE; /* app_offset */ - func_param_types[3] = I32_TYPE; /* buf_size */ + func_param_types[2] = I64_TYPE; /* app_offset */ + func_param_types[3] = I64_TYPE; /* buf_size */ func_param_types[4] = comp_ctx->basic_types.int8_pptr_type; /* p_native_addr */ if (!(func_type = @@ -1424,18 +1420,20 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Get param cell number */ param_cell_num = func_type->param_cell_num; -// #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0) -// if (comp_ctx->enable_aux_stack_frame) { -// LLVMValueRef func_idx_const; - -// if (!(func_idx_const = I32_CONST(func_idx))) { -// aot_set_last_error("llvm build const failed."); -// return false; -// } -// if (!call_aot_alloc_frame_func(comp_ctx, func_ctx, func_idx_const)) -// return false; -// } -// #endif + // #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != + // 0) + // if (comp_ctx->enable_aux_stack_frame) { + // LLVMValueRef func_idx_const; + + // if (!(func_idx_const = I32_CONST(func_idx))) { + // aot_set_last_error("llvm build const failed."); + // return false; + // } + // if (!call_aot_alloc_frame_func(comp_ctx, func_ctx, + // func_idx_const)) + // return false; + // } + // #endif /* Allocate memory for parameters. * Parameters layout: @@ -1540,7 +1538,19 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (signature[i + 2] == '~') native_addr_size = param_values[i + 2]; else - native_addr_size = I32_ONE; + native_addr_size = I64_CONST(1); + if (!(native_addr_size = LLVMBuildZExtOrBitCast( + comp_ctx->builder, native_addr_size, I64_TYPE, + "native_addr_size_i64"))) { + aot_set_last_error("llvm build zextOrBitCast failed."); + goto fail; + } + if (!(param_values[j] = LLVMBuildZExtOrBitCast( + comp_ctx->builder, param_values[j], I64_TYPE, + "native_addr_i64"))) { + aot_set_last_error("llvm build zextOrBitCast failed."); + goto fail; + } if (!check_app_addr_and_convert( comp_ctx, func_ctx, false, param_values[j], native_addr_size, &native_addr)) { @@ -1549,7 +1559,13 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_values[j] = native_addr; } else if (signature[i + 1] == '$') { - native_addr_size = I32_ZERO; + native_addr_size = I64_ZERO; + if (!(param_values[j] = LLVMBuildZExtOrBitCast( + comp_ctx->builder, param_values[j], I64_TYPE, + "native_addr_i64"))) { + aot_set_last_error("llvm build zextOrBitCast failed."); + goto fail; + } if (!check_app_addr_and_convert( comp_ctx, func_ctx, true, param_values[j], native_addr_size, &native_addr)) { @@ -2032,7 +2048,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, // return false; // if (!aot_gen_commit_sp_ip( // comp_ctx->aot_frame, - // comp_ctx->aot_frame->sp - func_type->param_cell_num, frame_ip)) + // comp_ctx->aot_frame->sp - func_type->param_cell_num, + // frame_ip)) // return false; // } diff --git a/core/iwasm/compilation/aot_emit_function.h b/core/iwasm/compilation/aot_emit_function.h index b6b45c10bb..697dc39515 100644 --- a/core/iwasm/compilation/aot_emit_function.h +++ b/core/iwasm/compilation/aot_emit_function.h @@ -18,7 +18,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 type_idx, uint32 tbl_idx, const uint8 *frame_ip); + uint32 type_idx, uint32 tbl_idx, + const uint8 *frame_ip); bool aot_compile_op_ref_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index fc9952de0e..eedc5420a6 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -919,7 +919,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, comp_ctx->comp_data->memories[0].num_bytes_per_page; uint32 init_page_count = comp_ctx->comp_data->memories[0].mem_init_page_count; - uint32 mem_data_size = num_bytes_per_page * init_page_count; + uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count; if (mem_data_size > 0 && mem_offset + mem_len <= mem_data_size) { /* inside memory space */ /* maddr = mem_base_addr + moffset */ @@ -938,7 +938,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } else { if (!(mem_size = LLVMBuildLoad2( - comp_ctx->builder, I32_TYPE, + comp_ctx->builder, I64_TYPE, func_ctx->mem_info[0].mem_data_size_addr, "mem_size"))) { aot_set_last_error("llvm build load failed."); goto fail; @@ -951,8 +951,6 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, offset = LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset"); bytes = LLVMBuildZExt(comp_ctx->builder, bytes, I64_TYPE, "extend_len"); - mem_size = - LLVMBuildZExt(comp_ctx->builder, mem_size, I64_TYPE, "extend_size"); BUILD_OP(Add, offset, bytes, max_addr, "max_addr"); BUILD_ICMP(LLVMIntUGT, max_addr, mem_size, cmp, "cmp_max_mem_addr"); diff --git a/core/iwasm/compilation/aot_emit_variable.c b/core/iwasm/compilation/aot_emit_variable.c index 73edbf085e..6cd32217e7 100644 --- a/core/iwasm/compilation/aot_emit_variable.c +++ b/core/iwasm/compilation/aot_emit_variable.c @@ -251,7 +251,7 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); LLVMBasicBlockRef check_overflow_succ, check_underflow_succ; - LLVMValueRef cmp; + LLVMValueRef cmp, global_i64; /* Add basic blocks */ if (!(check_overflow_succ = LLVMAppendBasicBlockInContext( @@ -270,8 +270,14 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ); + if (!(global_i64 = LLVMBuildZExt(comp_ctx->builder, global, + I64_TYPE, "global_i64"))) { + aot_set_last_error("llvm build zext failed."); + return false; + } + /* Check aux stack overflow */ - if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE, global, + if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE, global_i64, func_ctx->aux_stack_bound, "cmp"))) { aot_set_last_error("llvm build icmp failed."); return false; @@ -283,7 +289,7 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Check aux stack underflow */ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ); - if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, global, + if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, global_i64, func_ctx->aux_stack_bottom, "cmp"))) { aot_set_last_error("llvm build icmp failed."); return false; diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index c8417e6d6d..3af56e8b6b 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -85,7 +85,7 @@ aot_add_llvm_func1(const AOTCompContext *comp_ctx, LLVMModuleRef module, uint32 func_index, uint32 param_count, LLVMTypeRef func_type, const char *prefix) { - char func_name[48]; + char func_name[48] = { 0 }; LLVMValueRef func; LLVMValueRef local_value; uint32 i, j; @@ -124,7 +124,7 @@ create_basic_func_context(const AOTCompContext *comp_ctx, { LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr; - /* Save the pameters for fast access */ + /* Save the parameters for fast access */ func_ctx->exec_env = LLVMGetParam(func_ctx->func, 0); /* Get aot inst address, the layout of exec_env is: @@ -674,7 +674,8 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module, uint32 backend_thread_num, compile_thread_num; /* Check function parameter types and result types */ - for (i = 0; i < aot_func_type->param_count + aot_func_type->result_count; + for (i = 0; + i < (uint32)(aot_func_type->param_count + aot_func_type->result_count); i++) { if (!check_wasm_type(comp_ctx, aot_func_type->types[i])) return NULL; @@ -1004,17 +1005,23 @@ create_aux_stack_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) if (!(aux_stack_bound_addr = LLVMBuildBitCast(comp_ctx->builder, aux_stack_bound_addr, - INT32_PTR_TYPE, "aux_stack_bound_ptr"))) { + INTPTR_T_PTR_TYPE, "aux_stack_bound_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } if (!(func_ctx->aux_stack_bound = - LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, aux_stack_bound_addr, - "aux_stack_bound"))) { + LLVMBuildLoad2(comp_ctx->builder, INTPTR_T_TYPE, + aux_stack_bound_addr, "aux_stack_bound_intptr"))) { aot_set_last_error("llvm build load failed"); return false; } + if (!(func_ctx->aux_stack_bound = + LLVMBuildZExt(comp_ctx->builder, func_ctx->aux_stack_bound, + I64_TYPE, "aux_stack_bound_i64"))) { + aot_set_last_error("llvm build truncOrBitCast failed."); + return false; + } /* Get aux stack bottom address */ if (!(aux_stack_bottom_addr = LLVMBuildInBoundsGEP2( @@ -1026,16 +1033,23 @@ create_aux_stack_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) if (!(aux_stack_bottom_addr = LLVMBuildBitCast(comp_ctx->builder, aux_stack_bottom_addr, - INT32_PTR_TYPE, "aux_stack_bottom_ptr"))) { + INTPTR_T_PTR_TYPE, "aux_stack_bottom_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } + if (!(func_ctx->aux_stack_bottom = - LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, aux_stack_bottom_addr, - "aux_stack_bottom"))) { + LLVMBuildLoad2(comp_ctx->builder, INTPTR_T_TYPE, + aux_stack_bottom_addr, "aux_stack_bottom"))) { aot_set_last_error("llvm build load failed"); return false; } + if (!(func_ctx->aux_stack_bottom = + LLVMBuildZExt(comp_ctx->builder, func_ctx->aux_stack_bottom, + I64_TYPE, "aux_stack_bottom_i64"))) { + aot_set_last_error("llvm build truncOrBitCast failed."); + return false; + } return true; } @@ -1365,7 +1379,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildBitCast( comp_ctx->builder, func_ctx->mem_info[0].mem_data_size_addr, - INT32_PTR_TYPE, "mem_data_size_ptr"))) { + INT64_PTR_TYPE, "mem_data_size_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } @@ -1384,7 +1398,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildLoad2( - comp_ctx->builder, I32_TYPE, + comp_ctx->builder, I64_TYPE, func_ctx->mem_info[0].mem_data_size_addr, "mem_data_size"))) { aot_set_last_error("llvm build load failed"); return false; @@ -1965,8 +1979,8 @@ aot_set_llvm_basic_types(AOTLLVMTypes *basic_types, LLVMContextRef context, basic_types->intptr_t_ptr_type = basic_types->int64_ptr_type; } - basic_types->gc_ref_type = LLVMPointerType(basic_types->void_type, 0); - basic_types->gc_ref_ptr_type = LLVMPointerType(basic_types->gc_ref_type, 0); + basic_types->gc_ref_type = basic_types->int8_ptr_type; + basic_types->gc_ref_ptr_type = basic_types->int8_pptr_type; return (basic_types->int8_ptr_type && basic_types->int8_pptr_type && basic_types->int16_ptr_type && basic_types->int32_ptr_type @@ -2534,6 +2548,9 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) aot_set_last_error("create LLVM module failed."); goto fail; } +#if LLVM_VERSION_MAJOR >= 19 + LLVMSetIsNewDbgInfoFormat(comp_ctx->module, true); +#endif #if WASM_ENABLE_LINUX_PERF != 0 if (wasm_runtime_get_linux_perf()) { diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index e7c5d24693..8306e7df37 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -352,7 +352,6 @@ typedef struct AOTLLVMConsts { LLVMValueRef i8_ptr_null; } AOTLLVMConsts; - /** * Compiler context */ @@ -399,7 +398,8 @@ typedef struct AOTCompContext { /* Native stack usage estimation */ bool enable_stack_estimation; bool enable_perf_profiling; - bool enable_memory_profiling;bool quick_invoke_c_api_import; + bool enable_memory_profiling; + bool quick_invoke_c_api_import; /* 128-bit SIMD */ bool enable_simd; /* 128-bit GC */ @@ -462,7 +462,7 @@ typedef struct AOTCompContext { /* Whether optimize the JITed code */ bool optimize; - bool emit_frame_pointer; + bool emit_frame_pointer; uint32 opt_level; uint32 size_level; @@ -621,7 +621,8 @@ void aot_block_destroy(AOTCompContext *comp_ctx, AOTBlock *block); LLVMTypeRef -wasm_type_to_llvm_type(const AOTCompContext *comp_ctx,const AOTLLVMTypes *llvm_types, uint8 wasm_type); +wasm_type_to_llvm_type(const AOTCompContext *comp_ctx, + const AOTLLVMTypes *llvm_types, uint8 wasm_type); bool aot_checked_addr_list_add(AOTFuncContext *func_ctx, uint32 local_idx, @@ -682,11 +683,9 @@ aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err); char * aot_compress_aot_func_names(AOTCompContext *comp_ctx, uint32 *p_size); - void aot_block_add_unroll_pass(AOTCompContext *comp_ctx, LLVMValueRef branch); - bool aot_set_cond_br_weights(AOTCompContext *comp_ctx, LLVMValueRef cond_br, int32 weights_true, int32 weights_false); diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index ec1140411b..7a1da62431 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -254,7 +254,8 @@ struct AddNopPass : public PassInfoMixin { dummy_inst->setDebugLoc( DILocation::get(context, getLineNo(), 2, sp)); - auto fence_inst = builder.CreateFence(AtomicOrdering::SequentiallyConsistent); + auto fence_inst = builder.CreateFence( + AtomicOrdering::SequentiallyConsistent); fence_inst->setDebugLoc( DILocation::get(context, getLineNo(), 514, sp)); diff --git a/core/iwasm/compilation/debug/dwarf_extractor.cpp b/core/iwasm/compilation/debug/dwarf_extractor.cpp index 2804735cbc..e2e515ba0a 100644 --- a/core/iwasm/compilation/debug/dwarf_extractor.cpp +++ b/core/iwasm/compilation/debug/dwarf_extractor.cpp @@ -295,6 +295,28 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx, const size_t num_function_args = function_args.GetSize(); dwarf_extractor *extractor; + /* + * Process only known languages. + * We have a few assumptions which might not be true for non-C functions. + * + * At least it's known broken for C++ and Rust: + * https://github.com/bytecodealliance/wasm-micro-runtime/issues/3187 + * https://github.com/bytecodealliance/wasm-micro-runtime/issues/3163 + */ + LanguageType language_type = function.GetLanguage(); + switch (language_type) { + case eLanguageTypeC89: + case eLanguageTypeC: + case eLanguageTypeC99: + case eLanguageTypeC11: + case eLanguageTypeC17: + break; + default: + LOG_WARNING("func %s has unsuppoted language_type 0x%x", + function_name, (int)language_type); + return NULL; + } + if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) return NULL; @@ -313,6 +335,17 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx, if (function_arg_type.IsValid()) { ParamTypes[function_arg_idx + 1] = lldb_type_to_type_dbi(comp_ctx, function_arg_type); + if (ParamTypes[function_arg_idx + 1] == NULL) { + LOG_WARNING( + "func %s arg %" PRIu32 + " has a type not implemented by lldb_type_to_type_dbi", + function_name, function_arg_idx); + } + } + else { + LOG_WARNING("func %s arg %" PRIu32 ": GetTypeAtIndex failed", + function_name, function_arg_idx); + ParamTypes[function_arg_idx + 1] = NULL; } } @@ -381,7 +414,7 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx, for (uint32_t function_arg_idx = 0; function_arg_idx < variable_list.GetSize(); ++function_arg_idx) { SBValue variable(variable_list.GetValueAtIndex(function_arg_idx)); - if (variable.IsValid()) { + if (variable.IsValid() && ParamTypes[function_arg_idx + 1] != NULL) { SBDeclaration dec(variable.GetDeclaration()); auto valtype = variable.GetType(); LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation( @@ -474,6 +507,8 @@ dwarf_gen_location(const AOTCompContext *comp_ctx, dwarf_extractor *extractor; AOTFunc *func = func_ctx->aot_func; + if (func_ctx->debug_func == NULL) + return NULL; if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) return NULL; diff --git a/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp b/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp index f5605b6f2c..79c72503e7 100644 --- a/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp +++ b/core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp @@ -7511,7 +7511,7 @@ at_rmw_xor_r_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst, CHECK_KIND(r3, JIT_REG_KIND_I64); \ } \ /* r0: read/return value r2: memory base addr can't be const */ \ - /* already check it's not const in LOAD_4ARGS(); */ \ + /* already check it's not const in LOAD_4ARGS() */ \ reg_no_dst = jit_reg_no(r0); \ CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \ /* mem_data base address has to be non-const */ \ @@ -9293,8 +9293,8 @@ jit_codegen_init() imm.setValue(INT32_MAX); a.jne(imm); - char *stream = (char *)a.code()->sectionById(0)->buffer().data() - + a.code()->sectionById(0)->buffer().size(); + char *stream_old = (char *)a.code()->sectionById(0)->buffer().data() + + a.code()->sectionById(0)->buffer().size(); /* If yes, call jit_set_exception_with_id to throw exception, and then set eax to JIT_INTERP_ACTION_THROWN, and jump to @@ -9319,7 +9319,7 @@ jit_codegen_init() /* Patch the offset of jne instruction */ char *stream_new = (char *)a.code()->sectionById(0)->buffer().data() + a.code()->sectionById(0)->buffer().size(); - *(int32 *)(stream - 4) = (int32)(stream_new - stream); + *(int32 *)(stream_old - 4) = (int32)(stream_new - stream_old); } /* Load compiled func ptr and call it */ @@ -9419,7 +9419,7 @@ static uint8 hreg_info_F64[3][16] = { 1, 1, 1, 1, 1, 1, 1, 0 }, /* caller_saved_jitted */ }; -static const JitHardRegInfo hreg_info = { +static const JitHardRegInfo g_hreg_info = { { { 0, NULL, NULL, NULL }, /* VOID */ @@ -9459,7 +9459,7 @@ static const JitHardRegInfo hreg_info = { const JitHardRegInfo * jit_codegen_get_hreg_info() { - return &hreg_info; + return &g_hreg_info; } static const char *reg_names_i32[] = { diff --git a/core/iwasm/fast-jit/fe/jit_emit_function.c b/core/iwasm/fast-jit/fe/jit_emit_function.c index d1c71c3093..1e41994407 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_function.c +++ b/core/iwasm/fast-jit/fe/jit_emit_function.c @@ -331,12 +331,14 @@ jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call) func_params[1] = NEW_CONST(I32, false); /* is_str = false */ func_params[2] = argvs[i]; if (signature[i + 2] == '~') { + /* TODO: Memory64 no need to convert if mem idx type i64 */ + func_params[3] = jit_cc_new_reg_I64(cc); /* pointer with length followed */ - func_params[3] = argvs[i + 1]; + GEN_INSN(I32TOI64, func_params[3], argvs[i + 1]); } else { /* pointer with length followed */ - func_params[3] = NEW_CONST(I32, 1); + func_params[3] = NEW_CONST(I64, 1); } } else if (signature[i + 1] == '$') { @@ -344,10 +346,15 @@ jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call) is_pointer_arg = true; func_params[1] = NEW_CONST(I32, true); /* is_str = true */ func_params[2] = argvs[i]; - func_params[3] = NEW_CONST(I32, 1); + func_params[3] = NEW_CONST(I64, 1); } if (is_pointer_arg) { + JitReg native_addr_64 = jit_cc_new_reg_I64(cc); + /* TODO: Memory64 no need to convert if mem idx type i64 */ + GEN_INSN(I32TOI64, native_addr_64, func_params[2]); + func_params[2] = native_addr_64; + if (!jit_emit_callnative(cc, jit_check_app_addr_and_convert, ret, func_params, 5)) { goto fail; diff --git a/core/iwasm/fast-jit/fe/jit_emit_memory.c b/core/iwasm/fast-jit/fe/jit_emit_memory.c index 420b4dd8e5..ea245ba345 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_memory.c +++ b/core/iwasm/fast-jit/fe/jit_emit_memory.c @@ -630,13 +630,13 @@ wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx, { WASMMemoryInstance *mem_inst; WASMDataSeg *data_segment; - uint32 mem_size; + uint64 mem_size; uint8 *mem_addr, *data_addr; uint32 seg_len; /* if d + n > the length of mem.data */ mem_inst = inst->memories[mem_idx]; - mem_size = mem_inst->cur_page_count * mem_inst->num_bytes_per_page; + mem_size = mem_inst->cur_page_count * (uint64)mem_inst->num_bytes_per_page; if (mem_size < mem_offset || mem_size - mem_offset < len) goto out_of_bounds; @@ -655,7 +655,7 @@ wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx, goto out_of_bounds; mem_addr = mem_inst->memory_data + mem_offset; - bh_memcpy_s(mem_addr, mem_size - mem_offset, data_addr, len); + bh_memcpy_s(mem_addr, (uint32)(mem_size - mem_offset), data_addr, len); return 0; out_of_bounds: @@ -719,13 +719,15 @@ wasm_copy_memory(WASMModuleInstance *inst, uint32 src_mem_idx, uint32 dst_offset) { WASMMemoryInstance *src_mem, *dst_mem; - uint32 src_mem_size, dst_mem_size; + uint64 src_mem_size, dst_mem_size; uint8 *src_addr, *dst_addr; src_mem = inst->memories[src_mem_idx]; dst_mem = inst->memories[dst_mem_idx]; - src_mem_size = src_mem->cur_page_count * src_mem->num_bytes_per_page; - dst_mem_size = dst_mem->cur_page_count * dst_mem->num_bytes_per_page; + src_mem_size = + src_mem->cur_page_count * (uint64)src_mem->num_bytes_per_page; + dst_mem_size = + dst_mem->cur_page_count * (uint64)dst_mem->num_bytes_per_page; /* if s + n > the length of mem.data */ if (src_mem_size < src_offset || src_mem_size - src_offset < len) @@ -738,7 +740,7 @@ wasm_copy_memory(WASMModuleInstance *inst, uint32 src_mem_idx, src_addr = src_mem->memory_data + src_offset; dst_addr = dst_mem->memory_data + dst_offset; /* allowing the destination and source to overlap */ - bh_memmove_s(dst_addr, dst_mem_size - dst_offset, src_addr, len); + bh_memmove_s(dst_addr, (uint32)(dst_mem_size - dst_offset), src_addr, len); return 0; out_of_bounds: @@ -784,11 +786,11 @@ wasm_fill_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 len, uint32 val, uint32 dst) { WASMMemoryInstance *mem_inst; - uint32 mem_size; + uint64 mem_size; uint8 *dst_addr; mem_inst = inst->memories[mem_idx]; - mem_size = mem_inst->cur_page_count * mem_inst->num_bytes_per_page; + mem_size = mem_inst->cur_page_count * (uint64)mem_inst->num_bytes_per_page; if (mem_size < dst || mem_size - dst < len) goto out_of_bounds; diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index f770b274c1..b8d40f97fd 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -194,12 +194,15 @@ JitReg get_aux_stack_bound_reg(JitFrame *frame) { JitCompContext *cc = frame->cc; + JitReg tmp = jit_cc_new_reg_I32(cc); if (!frame->aux_stack_bound_reg) { frame->aux_stack_bound_reg = cc->aux_stack_bound_reg; - GEN_INSN( - LDI32, frame->aux_stack_bound_reg, cc->exec_env_reg, - NEW_CONST(I32, offsetof(WASMExecEnv, aux_stack_boundary.boundary))); + GEN_INSN(LDPTR, frame->aux_stack_bound_reg, cc->exec_env_reg, + NEW_CONST(I32, offsetof(WASMExecEnv, aux_stack_boundary))); + /* TODO: Memory64 whether to convert depends on memory idx type */ + GEN_INSN(I64TOI32, tmp, frame->aux_stack_bound_reg); + frame->aux_stack_bound_reg = tmp; } return frame->aux_stack_bound_reg; } @@ -208,12 +211,15 @@ JitReg get_aux_stack_bottom_reg(JitFrame *frame) { JitCompContext *cc = frame->cc; + JitReg tmp = jit_cc_new_reg_I32(cc); if (!frame->aux_stack_bottom_reg) { frame->aux_stack_bottom_reg = cc->aux_stack_bottom_reg; - GEN_INSN( - LDI32, frame->aux_stack_bottom_reg, cc->exec_env_reg, - NEW_CONST(I32, offsetof(WASMExecEnv, aux_stack_bottom.bottom))); + GEN_INSN(LDPTR, frame->aux_stack_bottom_reg, cc->exec_env_reg, + NEW_CONST(I32, offsetof(WASMExecEnv, aux_stack_bottom))); + /* TODO: Memory64 whether to convert depends on memory idx type */ + GEN_INSN(I64TOI32, tmp, frame->aux_stack_bottom_reg); + frame->aux_stack_bottom_reg = tmp; } return frame->aux_stack_bottom_reg; } @@ -915,8 +921,8 @@ create_fixed_virtual_regs(JitCompContext *cc) cc->import_func_ptrs_reg = jit_cc_new_reg_ptr(cc); cc->fast_jit_func_ptrs_reg = jit_cc_new_reg_ptr(cc); cc->func_type_indexes_reg = jit_cc_new_reg_ptr(cc); - cc->aux_stack_bound_reg = jit_cc_new_reg_I32(cc); - cc->aux_stack_bottom_reg = jit_cc_new_reg_I32(cc); + cc->aux_stack_bound_reg = jit_cc_new_reg_ptr(cc); + cc->aux_stack_bottom_reg = jit_cc_new_reg_ptr(cc); count = module->import_memory_count + module->memory_count; if (count > 0) { diff --git a/core/iwasm/include/gc_export.h b/core/iwasm/include/gc_export.h index 8a1003194a..3eb88dbabb 100644 --- a/core/iwasm/include/gc_export.h +++ b/core/iwasm/include/gc_export.h @@ -437,6 +437,16 @@ WASM_RUNTIME_API_EXTERN void wasm_struct_obj_get_field(const wasm_struct_obj_t obj, uint32_t field_idx, bool sign_extend, wasm_value_t *value); +/** + * Get the field count of the a struct object. + * + * @param obj the WASM struct object + * + * @return the field count of the a struct object + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_struct_obj_get_field_count(const wasm_struct_obj_t obj); + /** * Create an array object with the index of defined type, the obj's length is * length, init value is init_value diff --git a/core/iwasm/include/wasm_c_api.h b/core/iwasm/include/wasm_c_api.h index 304b3a4ee8..0d62c27518 100644 --- a/core/iwasm/include/wasm_c_api.h +++ b/core/iwasm/include/wasm_c_api.h @@ -186,6 +186,16 @@ struct wasm_config_t { /*TODO: wasi args*/ }; +#ifndef INSTANTIATION_ARGS_OPTION_DEFINED +#define INSTANTIATION_ARGS_OPTION_DEFINED +/* WASM module instantiation arguments */ +typedef struct InstantiationArgs { + uint32_t default_stack_size; + uint32_t host_managed_heap_size; + uint32_t max_memory_pages; +} InstantiationArgs; +#endif /* INSTANTIATION_ARGS_OPTION_DEFINED */ + /* * by default: * - mem_alloc_type is Alloc_With_System_Allocator @@ -507,10 +517,21 @@ struct WASMModuleCommon; typedef struct WASMModuleCommon *wasm_module_t; #endif +#ifndef LOAD_ARGS_OPTION_DEFINED +#define LOAD_ARGS_OPTION_DEFINED +typedef struct LoadArgs { + char *name; + /* TODO: more fields? */ +} LoadArgs; +#endif /* LOAD_ARGS_OPTION_DEFINED */ WASM_API_EXTERN own wasm_module_t* wasm_module_new( wasm_store_t*, const wasm_byte_vec_t* binary); +// please refer to wasm_runtime_load_ex(...) in core/iwasm/include/wasm_export.h +WASM_API_EXTERN own wasm_module_t* wasm_module_new_ex( + wasm_store_t*, const wasm_byte_vec_t* binary, const LoadArgs *args); + WASM_API_EXTERN void wasm_module_delete(own wasm_module_t*); WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary); @@ -526,6 +547,9 @@ WASM_API_EXTERN own wasm_shared_module_t* wasm_module_share(wasm_module_t*); WASM_API_EXTERN own wasm_module_t* wasm_module_obtain(wasm_store_t*, wasm_shared_module_t*); WASM_API_EXTERN void wasm_shared_module_delete(own wasm_shared_module_t*); +WASM_API_EXTERN bool wasm_module_set_name(wasm_module_t*, const char* name); +WASM_API_EXTERN const char *wasm_module_get_name(wasm_module_t*); + // Function Instances @@ -644,6 +668,12 @@ WASM_API_EXTERN own wasm_instance_t* wasm_instance_new_with_args( own wasm_trap_t** trap, const uint32_t stack_size, const uint32_t heap_size ); +// please refer to wasm_runtime_instantiate_ex(...) in core/iwasm/include/wasm_export.h +WASM_API_EXTERN own wasm_instance_t* wasm_instance_new_with_args_ex( + wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t *imports, + own wasm_trap_t** trap, const InstantiationArgs *inst_args +); + WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out); diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 2bf4a8c4d1..de33b5da95 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -183,6 +183,24 @@ typedef struct RuntimeInitArgs { bool enable_linux_perf; } RuntimeInitArgs; +#ifndef LOAD_ARGS_OPTION_DEFINED +#define LOAD_ARGS_OPTION_DEFINED +typedef struct LoadArgs { + char *name; + /* TODO: more fields? */ +} LoadArgs; +#endif /* LOAD_ARGS_OPTION_DEFINED */ + +#ifndef INSTANTIATION_ARGS_OPTION_DEFINED +#define INSTANTIATION_ARGS_OPTION_DEFINED +/* WASM module instantiation arguments */ +typedef struct InstantiationArgs { + uint32_t default_stack_size; + uint32_t host_managed_heap_size; + uint32_t max_memory_pages; +} InstantiationArgs; +#endif /* INSTANTIATION_ARGS_OPTION_DEFINED */ + #ifndef WASM_VALKIND_T_DEFINED #define WASM_VALKIND_T_DEFINED typedef uint8_t wasm_valkind_t; @@ -409,6 +427,13 @@ WASM_RUNTIME_API_EXTERN wasm_module_t wasm_runtime_load(uint8_t *buf, uint32_t size, char *error_buf, uint32_t error_buf_size); +/** + * Load a WASM module with specified load argument. + */ +WASM_RUNTIME_API_EXTERN wasm_module_t +wasm_runtime_load_ex(uint8_t *buf, uint32_t size, const LoadArgs *args, + char *error_buf, uint32_t error_buf_size); + /** * Load a WASM module from a specified WASM or AOT section list. * @@ -527,6 +552,16 @@ wasm_runtime_instantiate(const wasm_module_t module, uint32_t default_stack_size, uint32_t host_managed_heap_size, char *error_buf, uint32_t error_buf_size); +/** + * Instantiate a WASM module, with specified instantiation arguments + * + * Same as wasm_runtime_instantiate, but it also allows overwriting maximum memory + */ +WASM_RUNTIME_API_EXTERN wasm_module_inst_t +wasm_runtime_instantiate_ex(const wasm_module_t module, + const InstantiationArgs *args, + char *error_buf, uint32_t error_buf_size); + /** * Set the running mode of a WASM module instance, override the * default running mode of the runtime. Note that it only makes sense when @@ -596,13 +631,12 @@ wasm_runtime_get_wasi_exit_code(wasm_module_inst_t module_inst); * * @param module_inst the module instance * @param name the name of the function - * @param signature the signature of the function, ignored currently * * @return the function instance found, NULL if not found */ WASM_RUNTIME_API_EXTERN wasm_function_inst_t wasm_runtime_lookup_function(wasm_module_inst_t const module_inst, - const char *name, const char *signature); + const char *name); /** * Get parameter count of the function instance @@ -1011,8 +1045,8 @@ wasm_runtime_is_bounds_checks_enabled( * it is not an absolute address. * Return non-zero if success, zero if failed. */ -WASM_RUNTIME_API_EXTERN uint32_t -wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint32_t size, +WASM_RUNTIME_API_EXTERN uint64_t +wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint64_t size, void **p_native_addr); /** @@ -1022,7 +1056,7 @@ wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint32_t size, * @param ptr the pointer to free */ WASM_RUNTIME_API_EXTERN void -wasm_runtime_module_free(wasm_module_inst_t module_inst, uint32_t ptr); +wasm_runtime_module_free(wasm_module_inst_t module_inst, uint64_t ptr); /** * Allocate memory from the heap of WASM module instance and initialize @@ -1037,9 +1071,9 @@ wasm_runtime_module_free(wasm_module_inst_t module_inst, uint32_t ptr); * it is not an absolute address. * Return non-zero if success, zero if failed. */ -WASM_RUNTIME_API_EXTERN uint32_t +WASM_RUNTIME_API_EXTERN uint64_t wasm_runtime_module_dup_data(wasm_module_inst_t module_inst, - const char *src, uint32_t size); + const char *src, uint64_t size); /** * Validate the app address, check whether it belongs to WASM module @@ -1054,7 +1088,7 @@ wasm_runtime_module_dup_data(wasm_module_inst_t module_inst, */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_validate_app_addr(wasm_module_inst_t module_inst, - uint32_t app_offset, uint32_t size); + uint64_t app_offset, uint64_t size); /** * Similar to wasm_runtime_validate_app_addr(), except that the size parameter @@ -1076,7 +1110,7 @@ wasm_runtime_validate_app_addr(wasm_module_inst_t module_inst, */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_validate_app_str_addr(wasm_module_inst_t module_inst, - uint32_t app_str_offset); + uint64_t app_str_offset); /** * Validate the native address, check whether it belongs to WASM module @@ -1092,7 +1126,7 @@ wasm_runtime_validate_app_str_addr(wasm_module_inst_t module_inst, */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_validate_native_addr(wasm_module_inst_t module_inst, - void *native_ptr, uint32_t size); + void *native_ptr, uint64_t size); /** * Convert app address(relative address) to native address(absolute address) @@ -1108,7 +1142,7 @@ wasm_runtime_validate_native_addr(wasm_module_inst_t module_inst, */ WASM_RUNTIME_API_EXTERN void * wasm_runtime_addr_app_to_native(wasm_module_inst_t module_inst, - uint32_t app_offset); + uint64_t app_offset); /** * Convert native address(absolute address) to app address(relative address) @@ -1118,7 +1152,7 @@ wasm_runtime_addr_app_to_native(wasm_module_inst_t module_inst, * * @return the app address converted */ -WASM_RUNTIME_API_EXTERN uint32_t +WASM_RUNTIME_API_EXTERN uint64_t wasm_runtime_addr_native_to_app(wasm_module_inst_t module_inst, void *native_ptr); @@ -1134,9 +1168,9 @@ wasm_runtime_addr_native_to_app(wasm_module_inst_t module_inst, */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_get_app_addr_range(wasm_module_inst_t module_inst, - uint32_t app_offset, - uint32_t *p_app_start_offset, - uint32_t *p_app_end_offset); + uint64_t app_offset, + uint64_t *p_app_start_offset, + uint64_t *p_app_end_offset); /** * Get the native address range (absolute address) that a native address @@ -1673,6 +1707,15 @@ WASM_RUNTIME_API_EXTERN bool wasm_runtime_restore(wasm_module_inst_t module_inst, char *file, char *file1); #endif + +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_set_module_name(wasm_module_t module, const char *name, + char *error_buf, uint32_t error_buf_size); + +/* return the most recently set module name or "" if never set before */ +WASM_RUNTIME_API_EXTERN const char* +wasm_runtime_get_module_name(wasm_module_t module); + /* clang-format on */ #ifdef __cplusplus diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index d62351a276..80ce67b8e8 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -90,8 +90,22 @@ extern "C" { */ #define VALUE_TYPE_GC_REF 0x43 +#define MAX_PAGE_COUNT_FLAG 0x01 +#define SHARED_MEMORY_FLAG 0x02 +#define MEMORY64_FLAG 0x04 + #define DEFAULT_NUM_BYTES_PER_PAGE 65536 #define DEFAULT_MAX_PAGES 65536 +#define DEFAULT_MEM64_MAX_PAGES UINT32_MAX + +/* Max size of linear memory */ +#define MAX_LINEAR_MEMORY_SIZE (4 * (uint64)BH_GB) +/* Roughly 274 TB */ +#define MAX_LINEAR_MEM64_MEMORY_SIZE \ + (DEFAULT_MEM64_MAX_PAGES * (uint64)64 * (uint64)BH_KB) +/* Macro to check memory flag and return appropriate memory size */ +#define GET_MAX_LINEAR_MEMORY_SIZE(is_memory64) \ + (is_memory64 ? MAX_LINEAR_MEM64_MEMORY_SIZE : MAX_LINEAR_MEMORY_SIZE) #if WASM_ENABLE_GC == 0 typedef uintptr_t table_elem_type_t; @@ -481,6 +495,12 @@ typedef struct WASMTable { #endif } WASMTable; +#if WASM_ENABLE_MEMORY64 != 0 +typedef uint64 mem_offset_t; +#else +typedef uint32 mem_offset_t; +#endif + typedef struct WASMMemory { uint32 flags; uint32 num_bytes_per_page; @@ -870,19 +890,19 @@ struct WASMModule { -1 means unexported */ uint32 aux_data_end_global_index; /* auxiliary __data_end exported by wasm app */ - uint32 aux_data_end; + uint64 aux_data_end; /* the index of auxiliary __heap_base global, -1 means unexported */ uint32 aux_heap_base_global_index; /* auxiliary __heap_base exported by wasm app */ - uint32 aux_heap_base; + uint64 aux_heap_base; /* the index of auxiliary stack top global, -1 means unexported */ uint32 aux_stack_top_global_index; /* auxiliary stack bottom resolved */ - uint32 aux_stack_bottom; + uint64 aux_stack_bottom; /* auxiliary stack size resolved */ uint32 aux_stack_size; @@ -1045,6 +1065,9 @@ struct WASMModule { bool is_ref_types_used; bool is_bulk_memory_used; #endif + + /* user defined name */ + char *name; }; typedef struct BlockType { @@ -1091,6 +1114,21 @@ align_uint(unsigned v, unsigned b) return (v + m) & ~m; } +/** + * Align an 64 bit unsigned value on a alignment boundary. + * + * @param v the value to be aligned + * @param b the alignment boundary (2, 4, 8, ...) + * + * @return the aligned value + */ +inline static uint64 +align_uint64(uint64 v, uint64 b) +{ + uint64 m = b - 1; + return (v + m) & ~m; +} + /** * Check whether a piece of data is out of range * @@ -1291,8 +1329,8 @@ block_type_get_param_types(BlockType *block_type, uint8 **p_param_types, param_count = func_type->param_count; #if WASM_ENABLE_GC != 0 *p_param_reftype_maps = func_type->ref_type_maps; - *p_param_reftype_map_count = - func_type->result_ref_type_maps - func_type->ref_type_maps; + *p_param_reftype_map_count = (uint32)(func_type->result_ref_type_maps + - func_type->ref_type_maps); #endif } else { diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 6c181d0949..8a914333ca 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -50,32 +50,33 @@ typedef float64 CellType_F64; #define get_linear_mem_size() GET_LINEAR_MEMORY_SIZE(memory) #endif -#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ - || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 -#define CHECK_MEMORY_OVERFLOW(bytes) \ - do { \ - uint64 offset1 = (uint64)offset + (uint64)addr; \ - if (disable_bounds_checks \ - || offset1 + bytes <= (uint64)get_linear_mem_size()) \ - /* If offset1 is in valid range, maddr must also \ - be in valid range, no need to check it again. */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#if WASM_ENABLE_MEMORY64 == 0 + +#if (!defined(OS_ENABLE_HW_BOUND_CHECK) \ + || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0) +#define CHECK_MEMORY_OVERFLOW(bytes) \ + do { \ + uint64 offset1 = (uint64)offset + (uint64)addr; \ + if (disable_bounds_checks || offset1 + bytes <= get_linear_mem_size()) \ + /* If offset1 is in valid range, maddr must also \ + be in valid range, no need to check it again. */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) -#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ - do { \ - uint64 offset1 = (uint32)(start); \ - if (disable_bounds_checks \ - || offset1 + bytes <= (uint64)get_linear_mem_size()) \ - /* App heap space is not valid space for \ - bulk memory operation */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ + do { \ + uint64 offset1 = (uint32)(start); \ + if (disable_bounds_checks || offset1 + bytes <= get_linear_mem_size()) \ + /* App heap space is not valid space for \ + bulk memory operation */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) -#else +#else /* else of !defined(OS_ENABLE_HW_BOUND_CHECK) || \ + WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */ #define CHECK_MEMORY_OVERFLOW(bytes) \ do { \ uint64 offset1 = (uint64)offset + (uint64)addr; \ @@ -86,8 +87,37 @@ typedef float64 CellType_F64; do { \ maddr = memory->memory_data + (uint32)(start); \ } while (0) -#endif /* !defined(OS_ENABLE_HW_BOUND_CHECK) \ - || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */ +#endif /* end of !defined(OS_ENABLE_HW_BOUND_CHECK) || \ + WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */ + +#else /* else of WASM_ENABLE_MEMORY64 == 0 */ + +#define CHECK_MEMORY_OVERFLOW(bytes) \ + do { \ + uint64 offset1 = (uint64)offset + (uint64)addr; \ + /* If memory64 is enabled, offset1, offset1 + bytes can overflow */ \ + if (disable_bounds_checks \ + || (offset1 >= offset && offset1 + bytes >= offset1 \ + && offset1 + bytes <= get_linear_mem_size())) \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ + } while (0) +#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ + do { \ + uint64 offset1 = (uint64)(start); \ + /* If memory64 is enabled, offset1 + bytes can overflow */ \ + if (disable_bounds_checks \ + || (offset1 + bytes >= offset1 \ + && offset1 + bytes <= get_linear_mem_size())) \ + /* App heap space is not valid space for \ + bulk memory operation */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ + } while (0) + +#endif /* end of WASM_ENABLE_MEMORY64 == 0 */ #define CHECK_ATOMIC_MEMORY_ACCESS() \ do { \ @@ -478,6 +508,23 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame) #define SET_LABEL_TYPE(_label_type) (void)0 #endif +#if WASM_ENABLE_MEMORY64 != 0 +#define PUSH_MEM_OFFSET(value) \ + do { \ + if (is_memory64) { \ + PUT_I64_TO_ADDR(frame_sp, value); \ + frame_sp += 2; \ + } \ + else { \ + *(int32 *)frame_sp++ = (int32)(value); \ + } \ + } while (0) +#else +#define PUSH_MEM_OFFSET(value) PUSH_I32(value) +#endif + +#define PUSH_PAGE_COUNT(value) PUSH_MEM_OFFSET(value) + #define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \ do { \ bh_assert(frame_csp < frame->csp_boundary); \ @@ -507,6 +554,14 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame) GET_REF_FROM_ADDR(frame_sp)) #endif +#if WASM_ENABLE_MEMORY64 != 0 +#define POP_MEM_OFFSET() (is_memory64 ? POP_I64() : POP_I32()) +#else +#define POP_MEM_OFFSET() POP_I32() +#endif + +#define POP_PAGE_COUNT() POP_MEM_OFFSET() + #define POP_CSP_CHECK_OVERFLOW(n) \ do { \ bh_assert(frame_csp - n >= frame->csp_bottom); \ @@ -573,51 +628,73 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame) frame_csp = frame->csp; \ } while (0) -#define read_leb_int64(p, p_end, res) \ - do { \ - uint8 _val = *p; \ - if (!(_val & 0x80)) { \ - res = (int64)_val; \ - if (_val & 0x40) \ - /* sign extend */ \ - res |= 0xFFFFFFFFFFFFFF80LL; \ - p++; \ - break; \ - } \ - uint32 _off = 0; \ - res = (int64)read_leb(p, &_off, 64, true); \ - p += _off; \ +#define read_leb_int64(p, p_end, res) \ + do { \ + uint8 _val = *p; \ + if (!(_val & 0x80)) { \ + res = (int64)_val; \ + if (_val & 0x40) \ + /* sign extend */ \ + res |= 0xFFFFFFFFFFFFFF80LL; \ + p++; \ + } \ + else { \ + uint32 _off = 0; \ + res = (int64)read_leb(p, &_off, 64, true); \ + p += _off; \ + } \ } while (0) -#define read_leb_uint32(p, p_end, res) \ - do { \ - uint8 _val = *p; \ - if (!(_val & 0x80)) { \ - res = _val; \ - p++; \ - break; \ - } \ - uint32 _off = 0; \ - res = (uint32)read_leb(p, &_off, 32, false); \ - p += _off; \ +#define read_leb_uint32(p, p_end, res) \ + do { \ + uint8 _val = *p; \ + if (!(_val & 0x80)) { \ + res = _val; \ + p++; \ + } \ + else { \ + uint32 _off = 0; \ + res = (uint32)read_leb(p, &_off, 32, false); \ + p += _off; \ + } \ } while (0) -#define read_leb_int32(p, p_end, res) \ - do { \ - uint8 _val = *p; \ - if (!(_val & 0x80)) { \ - res = (int32)_val; \ - if (_val & 0x40) \ - /* sign extend */ \ - res |= 0xFFFFFF80; \ - p++; \ - break; \ - } \ - uint32 _off = 0; \ - res = (int32)read_leb(p, &_off, 32, true); \ - p += _off; \ +#define read_leb_int32(p, p_end, res) \ + do { \ + uint8 _val = *p; \ + if (!(_val & 0x80)) { \ + res = (int32)_val; \ + if (_val & 0x40) \ + /* sign extend */ \ + res |= 0xFFFFFF80; \ + p++; \ + } \ + else { \ + uint32 _off = 0; \ + res = (int32)read_leb(p, &_off, 32, true); \ + p += _off; \ + } \ } while (0) +#if WASM_ENABLE_MEMORY64 != 0 +#define read_leb_mem_offset(p, p_end, res) \ + do { \ + uint8 _val = *p; \ + if (!(_val & 0x80)) { \ + res = (mem_offset_t)_val; \ + p++; \ + } \ + else { \ + uint32 _off = 0; \ + res = (mem_offset_t)read_leb(p, &_off, is_memory64 ? 64 : 32, \ + false); \ + p += _off; \ + } \ + } while (0) +#else +#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res) +#endif + #if WASM_ENABLE_LABELS_AS_VALUES == 0 #define RECOVER_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func) #else @@ -880,7 +957,7 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, uint32 readv, sval; \ \ sval = POP_I32(); \ - addr = POP_I32(); \ + addr = POP_MEM_OFFSET(); \ \ if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \ CHECK_MEMORY_OVERFLOW(1); \ @@ -920,7 +997,7 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, uint64 readv, sval; \ \ sval = (uint64)POP_I64(); \ - addr = POP_I32(); \ + addr = POP_MEM_OFFSET(); \ \ if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \ CHECK_MEMORY_OVERFLOW(1); \ @@ -1114,9 +1191,8 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (!func_import->call_conv_wasm_c_api) { native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } - else if (module_inst->e->common.c_api_func_imports) { - c_api_func_import = - module_inst->e->common.c_api_func_imports + cur_func_index; + else if (module_inst->c_api_func_imports) { + c_api_func_import = module_inst->c_api_func_imports + cur_func_index; native_func_pointer = c_api_func_import->func_ptr_linked; } @@ -1217,8 +1293,8 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, uint8 *ip = prev_frame->ip; char buf[128]; WASMExecEnv *sub_module_exec_env = NULL; - uint32 aux_stack_origin_boundary = 0; - uint32 aux_stack_origin_bottom = 0; + uintptr_t aux_stack_origin_boundary = 0; + uintptr_t aux_stack_origin_bottom = 0; if (!sub_func_inst) { snprintf(buf, sizeof(buf), @@ -1241,13 +1317,11 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, wasm_exec_env_set_module_inst(exec_env, (WASMModuleInstanceCommon *)sub_module_inst); /* - aux_stack_boundary */ - aux_stack_origin_boundary = exec_env->aux_stack_boundary.boundary; - exec_env->aux_stack_boundary.boundary = - sub_module_exec_env->aux_stack_boundary.boundary; + aux_stack_origin_boundary = exec_env->aux_stack_boundary; + exec_env->aux_stack_boundary = sub_module_exec_env->aux_stack_boundary; /* - aux_stack_bottom */ - aux_stack_origin_bottom = exec_env->aux_stack_bottom.bottom; - exec_env->aux_stack_bottom.bottom = - sub_module_exec_env->aux_stack_bottom.bottom; + aux_stack_origin_bottom = exec_env->aux_stack_bottom; + exec_env->aux_stack_bottom = sub_module_exec_env->aux_stack_bottom; /* set ip NULL to make call_func_bytecode return after executing this function */ @@ -1259,8 +1333,8 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, /* restore ip and other replaced */ prev_frame->ip = ip; - exec_env->aux_stack_boundary.boundary = aux_stack_origin_boundary; - exec_env->aux_stack_bottom.bottom = aux_stack_origin_bottom; + exec_env->aux_stack_boundary = aux_stack_origin_boundary; + exec_env->aux_stack_bottom = aux_stack_origin_bottom; wasm_exec_env_restore_module_inst(exec_env, (WASMModuleInstanceCommon *)module_inst); } @@ -1380,7 +1454,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ || WASM_ENABLE_BULK_MEMORY != 0 - uint32 linear_mem_size = 0; + uint64 linear_mem_size = 0; if (memory) #if WASM_ENABLE_THREAD_MGR == 0 linear_mem_size = memory->memory_data_size; @@ -1450,6 +1524,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMStringviewIterObjectRef stringview_iter_obj; #endif #endif +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + bool is_return_call = false; +#endif +#if WASM_ENABLE_MEMORY64 != 0 + /* TODO: multi-memories for now assuming the memory idx type is consistent + * across multi-memories */ + bool is_memory64 = false; + if (memory) + is_memory64 = memory->is_memory64; +#endif #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; @@ -4114,28 +4198,46 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_SET_GLOBAL_AUX_STACK) { - uint32 aux_stack_top; + uint64 aux_stack_top; read_leb_uint32(frame_ip, frame_ip_end, global_idx); bh_assert(global_idx < module->e->global_count); global = globals + global_idx; global_addr = get_global_addr(global_data, global); - aux_stack_top = *(uint32 *)(frame_sp - 1); - if (aux_stack_top <= exec_env->aux_stack_boundary.boundary) { +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) { + aux_stack_top = *(uint64 *)(frame_sp - 2); + } + else +#endif + { + aux_stack_top = (uint64)(*(uint32 *)(frame_sp - 1)); + } + if (aux_stack_top <= (uint64)exec_env->aux_stack_boundary) { wasm_set_exception(module, "wasm auxiliary stack overflow"); goto got_exception; } - if (aux_stack_top > exec_env->aux_stack_bottom.bottom) { + if (aux_stack_top > (uint64)exec_env->aux_stack_bottom) { wasm_set_exception(module, "wasm auxiliary stack underflow"); goto got_exception; } - *(int32 *)global_addr = aux_stack_top; - frame_sp--; +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) { + *(uint64 *)global_addr = aux_stack_top; + frame_sp -= 2; + } + else +#endif + { + *(uint32 *)global_addr = aux_stack_top; + frame_sp--; + } #if WASM_ENABLE_MEMORY_PROFILING != 0 if (module->module->aux_stack_top_global_index != (uint32)-1) { - uint32 aux_stack_used = module->module->aux_stack_bottom - - *(uint32 *)global_addr; + uint32 aux_stack_used = + (uint32)(module->module->aux_stack_bottom + - *(uint32 *)global_addr); if (aux_stack_used > module->e->max_aux_stack_used) module->e->max_aux_stack_used = aux_stack_used; } @@ -4159,13 +4261,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I32_LOAD) HANDLE_OP(WASM_OP_F32_LOAD) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - LOG_DEBUG("load.i32 %d %d %d %ld", offset, flags, *frame_sp, - ((uint8 *)frame_sp) - exec_env->wasm_stack.s.bottom); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); PUSH_I32(LOAD_I32(maddr)); CHECK_READ_WATCHPOINT(addr, offset); @@ -4176,11 +4277,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_LOAD) HANDLE_OP(WASM_OP_F64_LOAD) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(8); PUSH_I64(LOAD_I64(maddr)); CHECK_READ_WATCHPOINT(addr, offset); @@ -4190,11 +4292,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I32_LOAD8_S) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(1); PUSH_I32(sign_ext_8_32(*(int8 *)maddr)); CHECK_READ_WATCHPOINT(addr, offset); @@ -4204,11 +4307,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I32_LOAD8_U) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(1); PUSH_I32((uint32)(*(uint8 *)maddr)); CHECK_READ_WATCHPOINT(addr, offset); @@ -4218,11 +4322,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I32_LOAD16_S) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(2); PUSH_I32(sign_ext_16_32(LOAD_I16(maddr))); CHECK_READ_WATCHPOINT(addr, offset); @@ -4232,11 +4337,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I32_LOAD16_U) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(2); PUSH_I32((uint32)(LOAD_U16(maddr))); CHECK_READ_WATCHPOINT(addr, offset); @@ -4246,11 +4352,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_LOAD8_S) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(1); PUSH_I64(sign_ext_8_64(*(int8 *)maddr)); CHECK_READ_WATCHPOINT(addr, offset); @@ -4260,11 +4367,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_LOAD8_U) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(1); PUSH_I64((uint64)(*(uint8 *)maddr)); CHECK_READ_WATCHPOINT(addr, offset); @@ -4274,11 +4382,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_LOAD16_S) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(2); PUSH_I64(sign_ext_16_64(LOAD_I16(maddr))); CHECK_READ_WATCHPOINT(addr, offset); @@ -4288,11 +4397,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_LOAD16_U) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(2); PUSH_I64((uint64)(LOAD_U16(maddr))); CHECK_READ_WATCHPOINT(addr, offset); @@ -4302,12 +4412,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_LOAD32_S) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; opcode = *(frame_ip - 1); read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); PUSH_I64(sign_ext_32_64(LOAD_I32(maddr))); CHECK_READ_WATCHPOINT(addr, offset); @@ -4317,11 +4428,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_LOAD32_U) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); PUSH_I64((uint64)(LOAD_U32(maddr))); CHECK_READ_WATCHPOINT(addr, offset); @@ -4333,14 +4445,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I32_STORE) HANDLE_OP(WASM_OP_F32_STORE) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); frame_sp--; - addr = POP_I32(); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); - STORE_U32(maddr, frame_sp[1]); +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) { + STORE_U32(maddr, frame_sp[2]); + } + else +#endif + { + STORE_U32(maddr, frame_sp[1]); + } CHECK_WRITE_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); @@ -4349,15 +4470,26 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_STORE) HANDLE_OP(WASM_OP_F64_STORE) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); frame_sp -= 2; - addr = POP_I32(); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(8); - PUT_I64_TO_ADDR((uint32 *)maddr, - GET_I64_FROM_ADDR(frame_sp + 1)); + +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) { + PUT_I64_TO_ADDR((mem_offset_t *)maddr, + GET_I64_FROM_ADDR(frame_sp + 2)); + } + else +#endif + { + PUT_I64_TO_ADDR((uint32 *)maddr, + GET_I64_FROM_ADDR(frame_sp + 1)); + } CHECK_WRITE_WATCHPOINT(addr, offset); (void)flags; HANDLE_OP_END(); @@ -4366,14 +4498,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I32_STORE8) HANDLE_OP(WASM_OP_I32_STORE16) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; uint32 sval; opcode = *(frame_ip - 1); read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); sval = (uint32)POP_I32(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); if (opcode == WASM_OP_I32_STORE8) { CHECK_MEMORY_OVERFLOW(1); @@ -4392,14 +4525,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_I64_STORE16) HANDLE_OP(WASM_OP_I64_STORE32) { - uint32 offset, flags, addr; + uint32 flags; + mem_offset_t offset, addr; uint64 sval; opcode = *(frame_ip - 1); read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); sval = (uint64)POP_I64(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); if (opcode == WASM_OP_I64_STORE8) { CHECK_MEMORY_OVERFLOW(1); @@ -4423,7 +4557,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { uint32 reserved; read_leb_uint32(frame_ip, frame_ip_end, reserved); - PUSH_I32(memory->cur_page_count); + PUSH_PAGE_COUNT(memory->cur_page_count); (void)reserved; HANDLE_OP_END(); } @@ -4434,15 +4568,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, prev_page_count = memory->cur_page_count; read_leb_uint32(frame_ip, frame_ip_end, reserved); - delta = (uint32)POP_I32(); + delta = (uint32)POP_PAGE_COUNT(); if (!wasm_enlarge_memory(module, delta)) { /* failed to memory.grow, return -1 */ - PUSH_I32(-1); + PUSH_PAGE_COUNT(-1); } else { /* success, return previous page count */ - PUSH_I32(prev_page_count); + PUSH_PAGE_COUNT(prev_page_count); /* update memory size, no need to update memory ptr as it isn't changed in wasm_enlarge_memory */ #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ @@ -5447,7 +5581,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_BULK_MEMORY != 0 case WASM_OP_MEMORY_INIT: { - uint32 addr, segment; + uint32 segment; + mem_offset_t addr; uint64 bytes, offset, seg_len; uint8 *data; @@ -5457,7 +5592,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, bytes = (uint64)(uint32)POP_I32(); offset = (uint64)(uint32)POP_I32(); - addr = (uint32)POP_I32(); + addr = (mem_offset_t)POP_MEM_OFFSET(); #if WASM_ENABLE_THREAD_MGR != 0 linear_mem_size = get_linear_mem_size(); @@ -5466,8 +5601,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #ifndef OS_ENABLE_HW_BOUND_CHECK CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr); #else - if ((uint64)(uint32)addr + bytes - > (uint64)linear_mem_size) + if ((uint64)(uint32)addr + bytes > linear_mem_size) goto out_of_bounds; maddr = memory->memory_data + (uint32)addr; #endif @@ -5486,7 +5620,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (offset + bytes > seg_len) goto out_of_bounds; - bh_memcpy_s(maddr, linear_mem_size - addr, + bh_memcpy_s(maddr, (uint32)(linear_mem_size - addr), data + offset, (uint32)bytes); break; } @@ -5501,14 +5635,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } case WASM_OP_MEMORY_COPY: { - uint32 dst, src, len; + mem_offset_t dst, src, len; uint8 *mdst, *msrc; frame_ip += 2; - - len = POP_I32(); - src = POP_I32(); - dst = POP_I32(); + len = POP_MEM_OFFSET(); + src = POP_MEM_OFFSET(); + dst = POP_MEM_OFFSET(); #if WASM_ENABLE_THREAD_MGR != 0 linear_mem_size = get_linear_mem_size(); @@ -5518,28 +5651,29 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc); CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); #else - if ((uint64)(uint32)src + len > (uint64)linear_mem_size) + if ((uint64)(uint32)src + len > linear_mem_size) goto out_of_bounds; msrc = memory->memory_data + (uint32)src; - if ((uint64)(uint32)dst + len > (uint64)linear_mem_size) + if ((uint64)(uint32)dst + len > linear_mem_size) goto out_of_bounds; mdst = memory->memory_data + (uint32)dst; #endif /* allowing the destination and source to overlap */ - bh_memmove_s(mdst, linear_mem_size - dst, msrc, len); + bh_memmove_s(mdst, (uint32)(linear_mem_size - dst), + msrc, len); break; } case WASM_OP_MEMORY_FILL: { - uint32 dst, len; + mem_offset_t dst, len; uint8 fill_val, *mdst; frame_ip++; - len = POP_I32(); + len = POP_MEM_OFFSET(); fill_val = POP_I32(); - dst = POP_I32(); + dst = POP_MEM_OFFSET(); #if WASM_ENABLE_THREAD_MGR != 0 linear_mem_size = get_linear_mem_size(); @@ -5548,7 +5682,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #ifndef OS_ENABLE_HW_BOUND_CHECK CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); #else - if ((uint64)(uint32)dst + len > (uint64)linear_mem_size) + if ((uint64)(uint32)dst + len > linear_mem_size) goto out_of_bounds; mdst = memory->memory_data + (uint32)dst; #endif @@ -5769,7 +5903,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_SHARED_MEMORY != 0 HANDLE_OP(WASM_OP_ATOMIC_PREFIX) { - uint32 offset = 0, align = 0, addr; + mem_offset_t offset = 0, addr; + uint32 align = 0; uint32 opcode1; read_leb_uint32(frame_ip, frame_ip_end, opcode1); @@ -5779,7 +5914,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode != WASM_OP_ATOMIC_FENCE) { read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); + read_leb_mem_offset(frame_ip, frame_ip_end, offset); } switch (opcode) { @@ -5788,7 +5923,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 notify_count, ret; notify_count = POP_I32(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); CHECK_ATOMIC_MEMORY_ACCESS(); @@ -5808,7 +5943,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, timeout = POP_I64(); expect = POP_I32(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); CHECK_ATOMIC_MEMORY_ACCESS(); @@ -5832,7 +5967,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, timeout = POP_I64(); expect = POP_I64(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(8); CHECK_ATOMIC_MEMORY_ACCESS(); @@ -5863,7 +5998,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { uint32 readv; - addr = POP_I32(); + addr = POP_MEM_OFFSET(); if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { CHECK_MEMORY_OVERFLOW(1); @@ -5898,7 +6033,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { uint64 readv; - addr = POP_I32(); + addr = POP_MEM_OFFSET(); if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { CHECK_MEMORY_OVERFLOW(1); @@ -5940,7 +6075,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 sval; sval = (uint32)POP_I32(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); if (opcode == WASM_OP_ATOMIC_I32_STORE8) { CHECK_MEMORY_OVERFLOW(1); @@ -5974,7 +6109,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint64 sval; sval = (uint64)POP_I64(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); if (opcode == WASM_OP_ATOMIC_I64_STORE8) { CHECK_MEMORY_OVERFLOW(1); @@ -6001,7 +6136,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_MEMORY_OVERFLOW(8); CHECK_ATOMIC_MEMORY_ACCESS(); shared_memory_lock(memory); - PUT_I64_TO_ADDR((uint32 *)maddr, sval); + STORE_I64(maddr, sval); shared_memory_unlock(memory); } break; @@ -6015,7 +6150,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, sval = POP_I32(); expect = POP_I32(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) { CHECK_MEMORY_OVERFLOW(1); @@ -6061,7 +6196,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, sval = (uint64)POP_I64(); expect = (uint64)POP_I64(); - addr = POP_I32(); + addr = POP_MEM_OFFSET(); if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) { CHECK_MEMORY_OVERFLOW(1); @@ -6130,6 +6265,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, frame_ip = frame->ip; frame_sp = frame->sp; frame_csp = frame->csp; +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + is_return_call = false; +#endif goto call_func_from_entry; } @@ -6223,6 +6361,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } FREE_FRAME(exec_env, frame); wasm_exec_env_set_cur_frame(exec_env, prev_frame); + is_return_call = true; goto call_func_from_entry; } #endif @@ -6236,6 +6375,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } SYNC_ALL_TO_FRAME(); prev_frame = frame; +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + is_return_call = false; +#endif } call_func_from_entry: @@ -6245,15 +6387,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (cur_func->import_func_inst) { wasm_interp_call_func_import(module, exec_env, cur_func, prev_frame); +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + if (is_return_call) { + /* the frame was freed before tail calling and + the prev_frame was set as exec_env's cur_frame, + so here we recover context from prev_frame */ + RECOVER_CONTEXT(prev_frame); + } + else +#endif + { + prev_frame = frame->prev_frame; + cur_func = frame->function; + UPDATE_ALL_FROM_FRAME(); + } + #if WASM_ENABLE_EXCE_HANDLING != 0 char uncaught_exception[128] = { 0 }; bool has_exception = wasm_copy_exception(module, uncaught_exception); if (has_exception && strstr(uncaught_exception, "uncaught wasm exception")) { - /* fix framesp */ - UPDATE_ALL_FROM_FRAME(); - uint32 import_exception; /* initialize imported exception index to be invalid */ SET_INVALID_TAGINDEX(import_exception); @@ -6295,12 +6449,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { wasm_interp_call_func_native(module, exec_env, cur_func, prev_frame); +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + if (is_return_call) { + /* the frame was freed before tail calling and + the prev_frame was set as exec_env's cur_frame, + so here we recover context from prev_frame */ + RECOVER_CONTEXT(prev_frame); + } + else +#endif + { + prev_frame = frame->prev_frame; + cur_func = frame->function; + UPDATE_ALL_FROM_FRAME(); + } } - prev_frame = frame->prev_frame; - cur_func = frame->function; - UPDATE_ALL_FROM_FRAME(); - /* update memory size, no need to update memory ptr as it isn't changed in wasm_enlarge_memory */ #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 21de183823..2de04fc7d1 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -39,16 +39,15 @@ typedef float64 CellType_F64; #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 -#define CHECK_MEMORY_OVERFLOW(bytes) \ - do { \ - uint64 offset1 = (uint64)offset + (uint64)addr; \ - if (disable_bounds_checks \ - || offset1 + bytes <= (uint64)get_linear_mem_size()) \ - /* If offset1 is in valid range, maddr must also \ - be in valid range, no need to check it again. */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#define CHECK_MEMORY_OVERFLOW(bytes) \ + do { \ + uint64 offset1 = (uint64)offset + (uint64)addr; \ + if (disable_bounds_checks || offset1 + bytes <= get_linear_mem_size()) \ + /* If offset1 is in valid range, maddr must also \ + be in valid range, no need to check it again. */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) #define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ @@ -1188,9 +1187,8 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (!func_import->call_conv_wasm_c_api) { native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } - else if (module_inst->e->common.c_api_func_imports) { - c_api_func_import = - module_inst->e->common.c_api_func_imports + cur_func_index; + else if (module_inst->c_api_func_imports) { + c_api_func_import = module_inst->c_api_func_imports + cur_func_index; native_func_pointer = c_api_func_import->func_ptr_linked; } @@ -1274,8 +1272,8 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, uint8 *ip = prev_frame->ip; char buf[128]; WASMExecEnv *sub_module_exec_env = NULL; - uint32 aux_stack_origin_boundary = 0; - uint32 aux_stack_origin_bottom = 0; + uintptr_t aux_stack_origin_boundary = 0; + uintptr_t aux_stack_origin_bottom = 0; if (!sub_func_inst) { snprintf(buf, sizeof(buf), @@ -1298,13 +1296,11 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, wasm_exec_env_set_module_inst(exec_env, (WASMModuleInstanceCommon *)sub_module_inst); /* - aux_stack_boundary */ - aux_stack_origin_boundary = exec_env->aux_stack_boundary.boundary; - exec_env->aux_stack_boundary.boundary = - sub_module_exec_env->aux_stack_boundary.boundary; + aux_stack_origin_boundary = exec_env->aux_stack_boundary; + exec_env->aux_stack_boundary = sub_module_exec_env->aux_stack_boundary; /* - aux_stack_bottom */ - aux_stack_origin_bottom = exec_env->aux_stack_bottom.bottom; - exec_env->aux_stack_bottom.bottom = - sub_module_exec_env->aux_stack_bottom.bottom; + aux_stack_origin_bottom = exec_env->aux_stack_bottom; + exec_env->aux_stack_bottom = sub_module_exec_env->aux_stack_bottom; /* set ip NULL to make call_func_bytecode return after executing this function */ @@ -1316,8 +1312,8 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, /* restore ip and other replaced */ prev_frame->ip = ip; - exec_env->aux_stack_boundary.boundary = aux_stack_origin_boundary; - exec_env->aux_stack_bottom.bottom = aux_stack_origin_bottom; + exec_env->aux_stack_boundary = aux_stack_origin_boundary; + exec_env->aux_stack_bottom = aux_stack_origin_bottom; wasm_exec_env_restore_module_inst(exec_env, (WASMModuleInstanceCommon *)module_inst); } @@ -1444,7 +1440,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ || WASM_ENABLE_BULK_MEMORY != 0 - uint32 linear_mem_size = 0; + uint64 linear_mem_size = 0; if (memory) #if WASM_ENABLE_THREAD_MGR == 0 linear_mem_size = memory->memory_data_size; @@ -1505,6 +1501,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMStringviewIterObjectRef stringview_iter_obj; #endif #endif +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + bool is_return_call = false; +#endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op @@ -1697,7 +1696,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, /* clang-format off */ #if WASM_ENABLE_GC == 0 - fidx = tbl_inst->elems[val]; + fidx = (uint32)tbl_inst->elems[val]; if (fidx == (uint32)-1) { wasm_set_exception(module, "uninitialized element"); goto got_exception; @@ -3527,27 +3526,29 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_SET_GLOBAL_AUX_STACK) { - uint32 aux_stack_top; + uint64 aux_stack_top; global_idx = read_uint32(frame_ip); bh_assert(global_idx < module->e->global_count); global = globals + global_idx; global_addr = get_global_addr(global_data, global); - aux_stack_top = frame_lp[GET_OFFSET()]; - if (aux_stack_top <= exec_env->aux_stack_boundary.boundary) { + /* TODO: Memory64 the data type depends on mem idx type */ + aux_stack_top = (uint64)frame_lp[GET_OFFSET()]; + if (aux_stack_top <= (uint64)exec_env->aux_stack_boundary) { wasm_set_exception(module, "wasm auxiliary stack overflow"); goto got_exception; } - if (aux_stack_top > exec_env->aux_stack_bottom.bottom) { + if (aux_stack_top > (uint64)exec_env->aux_stack_bottom) { wasm_set_exception(module, "wasm auxiliary stack underflow"); goto got_exception; } - *(int32 *)global_addr = aux_stack_top; + *(int32 *)global_addr = (uint32)aux_stack_top; #if WASM_ENABLE_MEMORY_PROFILING != 0 if (module->module->aux_stack_top_global_index != (uint32)-1) { - uint32 aux_stack_used = module->module->aux_stack_bottom - - *(uint32 *)global_addr; + uint32 aux_stack_used = + (uint32)(module->module->aux_stack_bottom + - *(uint32 *)global_addr); if (aux_stack_used > module->e->max_aux_stack_used) module->e->max_aux_stack_used = aux_stack_used; } @@ -4968,8 +4969,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #ifndef OS_ENABLE_HW_BOUND_CHECK CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr); #else - if ((uint64)(uint32)addr + bytes - > (uint64)linear_mem_size) + if ((uint64)(uint32)addr + bytes > linear_mem_size) goto out_of_bounds; maddr = memory->memory_data + (uint32)addr; #endif @@ -4987,7 +4987,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (offset + bytes > seg_len) goto out_of_bounds; - bh_memcpy_s(maddr, linear_mem_size - addr, + bh_memcpy_s(maddr, (uint32)(linear_mem_size - addr), data + offset, (uint32)bytes); break; } @@ -5017,17 +5017,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc); CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); #else - if ((uint64)(uint32)src + len > (uint64)linear_mem_size) + if ((uint64)(uint32)src + len > linear_mem_size) goto out_of_bounds; msrc = memory->memory_data + (uint32)src; - if ((uint64)(uint32)dst + len > (uint64)linear_mem_size) + if ((uint64)(uint32)dst + len > linear_mem_size) goto out_of_bounds; mdst = memory->memory_data + (uint32)dst; #endif /* allowing the destination and source to overlap */ - bh_memmove_s(mdst, linear_mem_size - dst, msrc, len); + bh_memmove_s(mdst, (uint32)(linear_mem_size - dst), + msrc, len); break; } case WASM_OP_MEMORY_FILL: @@ -5046,7 +5047,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #ifndef OS_ENABLE_HW_BOUND_CHECK CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); #else - if ((uint64)(uint32)dst + len > (uint64)linear_mem_size) + if ((uint64)(uint32)dst + len > linear_mem_size) goto out_of_bounds; mdst = memory->memory_data + (uint32)dst; #endif @@ -5620,6 +5621,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { frame = prev_frame; frame_ip = frame->ip; +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + is_return_call = false; +#endif goto call_func_from_entry; } @@ -5768,6 +5772,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, FREE_FRAME(exec_env, frame); frame_ip += cur_func->param_count * sizeof(int16); wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame); + is_return_call = true; goto call_func_from_entry; } #endif /* WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 */ @@ -5840,6 +5845,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } SYNC_ALL_TO_FRAME(); prev_frame = frame; +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + is_return_call = false; +#endif } call_func_from_entry: @@ -5857,9 +5865,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, prev_frame); } - prev_frame = frame->prev_frame; - cur_func = frame->function; - UPDATE_ALL_FROM_FRAME(); +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + if (is_return_call) { + /* the frame was freed before tail calling and + the prev_frame was set as exec_env's cur_frame, + so here we recover context from prev_frame */ + RECOVER_CONTEXT(prev_frame); + } + else +#endif + { + prev_frame = frame->prev_frame; + cur_func = frame->function; + UPDATE_ALL_FROM_FRAME(); + } /* update memory size, no need to update memory ptr as it isn't changed in wasm_enlarge_memory */ diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 8bf2ed9206..a07ce5866c 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -45,6 +45,16 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) } } +#if WASM_ENABLE_MEMORY64 != 0 +static void +set_error_buf_mem_offset_out_of_range(char *error_buf, uint32 error_buf_size) +{ + if (error_buf != NULL) { + snprintf(error_buf, error_buf_size, "offset out of range"); + } +} +#endif + static void set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...) { @@ -102,6 +112,7 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length, #define skip_leb_int64(p, p_end) skip_leb(p) #define skip_leb_uint32(p, p_end) skip_leb(p) #define skip_leb_int32(p, p_end) skip_leb(p) +#define skip_leb_mem_offset(p, p_end) skip_leb(p) static bool read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, @@ -139,7 +150,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, } else if (sign && maxbits == 32) { if (shift < maxbits) { - /* Sign extend, second highest bit is the sign bit */ + /* Sign extend, second-highest bit is the sign bit */ if ((uint8)byte & 0x40) result |= (~((uint64)0)) << shift; } @@ -154,7 +165,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, } else if (sign && maxbits == 64) { if (shift < maxbits) { - /* Sign extend, second highest bit is the sign bit */ + /* Sign extend, second-highest bit is the sign bit */ if ((uint8)byte & 0x40) result |= (~((uint64)0)) << shift; } @@ -191,6 +202,21 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, res = (int64)res64; \ } while (0) +#if WASM_ENABLE_MEMORY64 != 0 +#define read_leb_mem_offset(p, p_end, res) \ + do { \ + uint64 res64; \ + if (!read_leb((uint8 **)&p, p_end, is_memory64 ? 64 : 32, false, \ + &res64, error_buf, error_buf_size)) { \ + set_error_buf_mem_offset_out_of_range(error_buf, error_buf_size); \ + goto fail; \ + } \ + res = (mem_offset_t)res64; \ + } while (0) +#else +#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res) +#endif + #define read_leb_uint32(p, p_end, res) \ do { \ uint64 res64; \ @@ -366,138 +392,6 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf, mem = mem_new; \ } while (0) -static bool -check_utf8_str(const uint8 *str, uint32 len) -{ - /* The valid ranges are taken from page 125, below link - https://www.unicode.org/versions/Unicode9.0.0/ch03.pdf */ - const uint8 *p = str, *p_end = str + len; - uint8 chr; - - while (p < p_end) { - chr = *p; - - if (chr == 0) { - LOG_WARNING( - "LIMITATION: a string which contains '\\00' is unsupported"); - return false; - } - else if (chr < 0x80) { - p++; - } - else if (chr >= 0xC2 && chr <= 0xDF && p + 1 < p_end) { - if (p[1] < 0x80 || p[1] > 0xBF) { - return false; - } - p += 2; - } - else if (chr >= 0xE0 && chr <= 0xEF && p + 2 < p_end) { - if (chr == 0xE0) { - if (p[1] < 0xA0 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { - return false; - } - } - else if (chr == 0xED) { - if (p[1] < 0x80 || p[1] > 0x9F || p[2] < 0x80 || p[2] > 0xBF) { - return false; - } - } - else { /* chr >= 0xE1 && chr <= 0xEF */ - if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { - return false; - } - } - p += 3; - } - else if (chr >= 0xF0 && chr <= 0xF4 && p + 3 < p_end) { - if (chr == 0xF0) { - if (p[1] < 0x90 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF - || p[3] < 0x80 || p[3] > 0xBF) { - return false; - } - } - else if (chr <= 0xF3) { /* and also chr >= 0xF1 */ - if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF - || p[3] < 0x80 || p[3] > 0xBF) { - return false; - } - } - else { /* chr == 0xF4 */ - if (p[1] < 0x80 || p[1] > 0x8F || p[2] < 0x80 || p[2] > 0xBF - || p[3] < 0x80 || p[3] > 0xBF) { - return false; - } - } - p += 4; - } - else { - return false; - } - } - return (p == p_end); -} - -static char * -const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, - bool is_load_from_file_buf, char *error_buf, - uint32 error_buf_size) -{ - StringNode *node, *node_next; - - if (!check_utf8_str(str, len)) { - set_error_buf(error_buf, error_buf_size, "invalid UTF-8 encoding"); - return NULL; - } - - if (len == 0) { - return ""; - } - else if (is_load_from_file_buf) { - /* As the file buffer can be referred to after loading, we use - the previous byte of leb encoded size to adjust the string: - move string 1 byte backward and then append '\0' */ - char *c_str = (char *)str - 1; - bh_memmove_s(c_str, len + 1, c_str + 1, len); - c_str[len] = '\0'; - return c_str; - } - - /* Search const str list */ - node = module->const_str_list; - while (node) { - node_next = node->next; - if (strlen(node->str) == len && !memcmp(node->str, str, len)) - break; - node = node_next; - } - - if (node) { - return node->str; - } - - if (!(node = loader_malloc(sizeof(StringNode) + len + 1, error_buf, - error_buf_size))) { - return NULL; - } - - node->str = ((char *)node) + sizeof(StringNode); - bh_memcpy_s(node->str, len + 1, str, len); - node->str[len] = '\0'; - - if (!module->const_str_list) { - /* set as head */ - module->const_str_list = node; - node->next = NULL; - } - else { - /* insert it */ - node->next = module->const_str_list; - module->const_str_list = node; - } - - return node->str; -} - #if WASM_ENABLE_GC != 0 static bool check_type_index(const WASMModule *module, uint32 type_index, char *error_buf, @@ -1627,7 +1521,7 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module, #endif #if WASM_ENABLE_WAMR_COMPILER != 0 - for (i = 0; i < type->param_count + type->result_count; i++) { + for (i = 0; i < (uint32)(type->param_count + type->result_count); i++) { if (type->types[i] == VALUE_TYPE_V128) module->is_simd_used = true; } @@ -2035,8 +1929,8 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } #else /* else of WASM_ENABLE_GC == 0 */ for (i = 0; i < type_count; i++) { - uint32 super_type_count = 0, parent_type_idx = (uint32)-1, - rec_count = 1, j; + uint32 super_type_count = 0, parent_type_idx = (uint32)-1; + uint32 rec_count = 1, j; bool is_sub_final = true; CHECK_BUF(p, p_end, 1); @@ -2048,10 +1942,22 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (rec_count > 1) { uint64 new_total_size; + /* integer overflow */ + if (rec_count - 1 > UINT32_MAX - module->type_count) { + set_error_buf(error_buf, error_buf_size, + "recursive type count too large"); + return false; + } module->type_count += rec_count - 1; new_total_size = sizeof(WASMFuncType *) * (uint64)module->type_count; - MEM_REALLOC(module->types, total_size, new_total_size); + if (new_total_size > UINT32_MAX) { + set_error_buf(error_buf, error_buf_size, + "allocate memory failed"); + return false; + } + MEM_REALLOC(module->types, (uint32)total_size, + (uint32)new_total_size); total_size = new_total_size; } @@ -2714,31 +2620,92 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, } static bool -check_memory_init_size(uint32 init_size, char *error_buf, uint32 error_buf_size) +check_memory_init_size(bool is_memory64, uint32 init_size, char *error_buf, + uint32 error_buf_size) { - if (init_size > DEFAULT_MAX_PAGES) { + uint32 default_max_size = + is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES; + + if (!is_memory64 && init_size > default_max_size) { set_error_buf(error_buf, error_buf_size, "memory size must be at most 65536 pages (4GiB)"); return false; } +#if WASM_ENABLE_MEMORY64 != 0 + else if (is_memory64 && init_size > default_max_size) { + set_error_buf( + error_buf, error_buf_size, + "memory size must be at most 4,294,967,295 pages (274 Terabyte)"); + return false; + } +#endif return true; } static bool -check_memory_max_size(uint32 init_size, uint32 max_size, char *error_buf, - uint32 error_buf_size) +check_memory_max_size(bool is_memory64, uint32 init_size, uint32 max_size, + char *error_buf, uint32 error_buf_size) { + uint32 default_max_size = + is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES; + if (max_size < init_size) { set_error_buf(error_buf, error_buf_size, "size minimum must not be greater than maximum"); return false; } - if (max_size > DEFAULT_MAX_PAGES) { + if (!is_memory64 && max_size > default_max_size) { set_error_buf(error_buf, error_buf_size, "memory size must be at most 65536 pages (4GiB)"); return false; } +#if WASM_ENABLE_MEMORY64 != 0 + else if (is_memory64 && max_size > default_max_size) { + set_error_buf( + error_buf, error_buf_size, + "memory size must be at most 4,294,967,295 pages (274 Terabyte)"); + return false; + } +#endif + + return true; +} + +static bool +check_memory_flag(const uint8 mem_flag, char *error_buf, uint32 error_buf_size) +{ + /* Check whether certain features indicated by mem_flag are enabled in + * runtime */ + if (mem_flag > MAX_PAGE_COUNT_FLAG) { +#if WASM_ENABLE_SHARED_MEMORY == 0 + if (mem_flag & SHARED_MEMORY_FLAG) { + LOG_VERBOSE("shared memory flag was found, please enable shared " + "memory, lib-pthread or lib-wasi-threads"); + set_error_buf(error_buf, error_buf_size, "invalid limits flags"); + return false; + } +#endif +#if WASM_ENABLE_MEMORY64 == 0 + if (mem_flag & MEMORY64_FLAG) { + LOG_VERBOSE("memory64 flag was found, please enable memory64"); + set_error_buf(error_buf, error_buf_size, "invalid limits flags"); + return false; + } +#endif + } + + if (mem_flag > MAX_PAGE_COUNT_FLAG + SHARED_MEMORY_FLAG + MEMORY64_FLAG) { + set_error_buf(error_buf, error_buf_size, "invalid limits flags"); + return false; + } + else if ((mem_flag & SHARED_MEMORY_FLAG) + && !(mem_flag & MAX_PAGE_COUNT_FLAG)) { + set_error_buf(error_buf, error_buf_size, + "shared memory must have maximum"); + return false; + } + return true; } @@ -2748,15 +2715,16 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, const char *memory_name, WASMMemoryImport *memory, char *error_buf, uint32 error_buf_size) { - const uint8 *p = *p_buf, *p_end = buf_end; + const uint8 *p = *p_buf, *p_end = buf_end, *p_org; #if WASM_ENABLE_APP_FRAMEWORK != 0 uint32 pool_size = wasm_runtime_memory_pool_size(); uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT / DEFAULT_NUM_BYTES_PER_PAGE; #else - uint32 max_page_count = DEFAULT_MAX_PAGES; + uint32 max_page_count; #endif /* WASM_ENABLE_APP_FRAMEWORK */ - uint32 declare_max_page_count_flag = 0; + uint32 mem_flag = 0; + bool is_memory64 = false; uint32 declare_init_page_count = 0; uint32 declare_max_page_count = 0; #if WASM_ENABLE_MULTI_MODULE != 0 @@ -2764,16 +2732,31 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *linked_memory = NULL; #endif - read_leb_uint32(p, p_end, declare_max_page_count_flag); + p_org = p; + read_leb_uint32(p, p_end, mem_flag); + is_memory64 = mem_flag & MEMORY64_FLAG; + if (p - p_org > 1) { + LOG_VERBOSE("integer representation too long"); + set_error_buf(error_buf, error_buf_size, "invalid limits flags"); + return false; + } + + if (!check_memory_flag(mem_flag, error_buf, error_buf_size)) { + return false; + } + read_leb_uint32(p, p_end, declare_init_page_count); - if (!check_memory_init_size(declare_init_page_count, error_buf, + if (!check_memory_init_size(is_memory64, declare_init_page_count, error_buf, error_buf_size)) { return false; } - if (declare_max_page_count_flag & 1) { +#if WASM_ENABLE_APP_FRAMEWORK == 0 + max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES; +#endif + if (mem_flag & MAX_PAGE_COUNT_FLAG) { read_leb_uint32(p, p_end, declare_max_page_count); - if (!check_memory_max_size(declare_init_page_count, + if (!check_memory_max_size(is_memory64, declare_init_page_count, declare_max_page_count, error_buf, error_buf_size)) { return false; @@ -2796,7 +2779,7 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_LIB_WASI_THREADS != 0 /* Avoid memory import failure when wasi-threads is enabled and the memory is shared */ - if (!(declare_max_page_count_flag & 2)) + if (!(mem_flag & SHARED_MEMORY_FLAG)) return false; #else return false; @@ -2844,7 +2827,7 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, } /* now we believe all declaration are ok */ - memory->flags = declare_max_page_count_flag; + memory->flags = mem_flag; memory->init_page_count = declare_init_page_count; memory->max_page_count = declare_max_page_count; memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; @@ -3145,53 +3128,34 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT / DEFAULT_NUM_BYTES_PER_PAGE; #else - uint32 max_page_count = DEFAULT_MAX_PAGES; + uint32 max_page_count; #endif + bool is_memory64 = false; p_org = p; read_leb_uint32(p, p_end, memory->flags); -#if WASM_ENABLE_SHARED_MEMORY == 0 - if (p - p_org > 1) { - set_error_buf(error_buf, error_buf_size, - "integer representation too long"); - return false; - } - if (memory->flags > 1) { - if (memory->flags & 2) { - set_error_buf(error_buf, error_buf_size, - "shared memory flag was found, " - "please enable shared memory, lib-pthread " - "or lib-wasi-threads"); - } - else { - set_error_buf(error_buf, error_buf_size, "invalid memory flags"); - } - return false; - } -#else + is_memory64 = memory->flags & MEMORY64_FLAG; if (p - p_org > 1) { + LOG_VERBOSE("integer representation too long"); set_error_buf(error_buf, error_buf_size, "invalid limits flags"); return false; } - if (memory->flags > 3) { - set_error_buf(error_buf, error_buf_size, "invalid limits flags"); - return false; - } - else if (memory->flags == 2) { - set_error_buf(error_buf, error_buf_size, - "shared memory must have maximum"); + + if (!check_memory_flag(memory->flags, error_buf, error_buf_size)) { return false; } -#endif read_leb_uint32(p, p_end, memory->init_page_count); - if (!check_memory_init_size(memory->init_page_count, error_buf, + if (!check_memory_init_size(is_memory64, memory->init_page_count, error_buf, error_buf_size)) return false; +#if WASM_ENABLE_APP_FRAMEWORK == 0 + max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES; +#endif if (memory->flags & 1) { read_leb_uint32(p, p_end, memory->max_page_count); - if (!check_memory_max_size(memory->init_page_count, + if (!check_memory_max_size(is_memory64, memory->init_page_count, memory->max_page_count, error_buf, error_buf_size)) return false; @@ -3370,7 +3334,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, /* load module name */ read_leb_uint32(p, p_end, name_len); CHECK_BUF(p, p_end, name_len); - if (!(sub_module_name = const_str_list_insert( + if (!(sub_module_name = wasm_const_str_list_insert( p, name_len, module, is_load_from_file_buf, error_buf, error_buf_size))) { return false; @@ -3380,7 +3344,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, /* load field name */ read_leb_uint32(p, p_end, name_len); CHECK_BUF(p, p_end, name_len); - if (!(field_name = const_str_list_insert( + if (!(field_name = wasm_const_str_list_insert( p, name_len, module, is_load_from_file_buf, error_buf, error_buf_size))) { return false; @@ -4103,7 +4067,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } } - if (!(export->name = const_str_list_insert( + if (!(export->name = wasm_const_str_list_insert( p, str_len, module, is_load_from_file_buf, error_buf, error_buf_size))) { return false; @@ -4582,6 +4546,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, bool is_passive = false; uint32 mem_flag; #endif + uint8 mem_offset_type; read_leb_uint32(p, p_end, data_seg_count); @@ -4647,11 +4612,35 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, } #endif /* WASM_ENABLE_BULK_MEMORY */ +#if WASM_ENABLE_BULK_MEMORY != 0 + if (!is_passive) +#endif + { +#if WASM_ENABLE_MEMORY64 != 0 + /* This memory_flag is from memory instead of data segment */ + uint8 memory_flag; + if (module->import_memory_count > 0) { + memory_flag = + module->import_memories[mem_index].u.memory.flags; + } + else { + memory_flag = + module + ->memories[mem_index - module->import_memory_count] + .flags; + } + mem_offset_type = memory_flag & MEMORY64_FLAG ? VALUE_TYPE_I64 + : VALUE_TYPE_I32; +#else + mem_offset_type = VALUE_TYPE_I32; +#endif + } + #if WASM_ENABLE_BULK_MEMORY != 0 if (!is_passive) #endif if (!load_init_expr(module, &p, p_end, &init_expr, - VALUE_TYPE_I32, NULL, error_buf, + mem_offset_type, NULL, error_buf, error_buf_size)) return false; @@ -4987,7 +4976,7 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } if (!(module->functions[func_index]->field_name = - const_str_list_insert( + wasm_const_str_list_insert( p, func_name_len, module, #if WASM_ENABLE_WAMR_COMPILER != 0 false, @@ -5039,7 +5028,7 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } - if (!check_utf8_str(p, name_len)) { + if (!wasm_check_utf8_str(p, name_len)) { set_error_buf(error_buf, error_buf_size, "invalid UTF-8 encoding"); return false; } @@ -5055,7 +5044,7 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 - if (memcmp(p, "name", 4) == 0) { + if (name_len == 4 && memcmp(p, "name", 4) == 0) { module->name_section_buf = buf; module->name_section_buf_end = buf_end; p += name_len; @@ -5597,8 +5586,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, *buf_func = NULL, *buf_func_end = NULL; WASMGlobal *aux_data_end_global = NULL, *aux_heap_base_global = NULL; WASMGlobal *aux_stack_top_global = NULL, *global; - uint32 aux_data_end = (uint32)-1, aux_heap_base = (uint32)-1; - uint32 aux_stack_top = (uint32)-1, global_index, func_index, i; + uint64 aux_data_end = (uint64)-1LL, aux_heap_base = (uint64)-1LL, + aux_stack_top = (uint64)-1LL; + uint32 global_index, func_index, i; uint32 aux_data_end_global_index = (uint32)-1; uint32 aux_heap_base_global_index = (uint32)-1; WASMFuncType *func_type; @@ -5735,9 +5725,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, && global->init_expr.init_expr_type == INIT_EXPR_TYPE_I32_CONST) { aux_heap_base_global = global; - aux_heap_base = global->init_expr.u.i32; + aux_heap_base = (uint64)(uint32)global->init_expr.u.i32; aux_heap_base_global_index = export->index; - LOG_VERBOSE("Found aux __heap_base global, value: %d", + LOG_VERBOSE("Found aux __heap_base global, value: %" PRIu64, aux_heap_base); } } @@ -5748,12 +5738,12 @@ load_from_sections(WASMModule *module, WASMSection *sections, && global->init_expr.init_expr_type == INIT_EXPR_TYPE_I32_CONST) { aux_data_end_global = global; - aux_data_end = global->init_expr.u.i32; + aux_data_end = (uint64)(uint32)global->init_expr.u.i32; aux_data_end_global_index = export->index; - LOG_VERBOSE("Found aux __data_end global, value: %d", + LOG_VERBOSE("Found aux __data_end global, value: %" PRIu64, aux_data_end); - aux_data_end = align_uint(aux_data_end, 16); + aux_data_end = align_uint64(aux_data_end, 16); } } @@ -5789,20 +5779,22 @@ load_from_sections(WASMModule *module, WASMSection *sections, && global->type == VALUE_TYPE_I32 && global->init_expr.init_expr_type == INIT_EXPR_TYPE_I32_CONST - && (uint32)global->init_expr.u.i32 <= aux_heap_base) { + && (uint64)(uint32)global->init_expr.u.i32 + <= aux_heap_base) { aux_stack_top_global = global; - aux_stack_top = (uint32)global->init_expr.u.i32; + aux_stack_top = (uint64)(uint32)global->init_expr.u.i32; module->aux_stack_top_global_index = module->import_global_count + global_index; module->aux_stack_bottom = aux_stack_top; module->aux_stack_size = aux_stack_top > aux_data_end - ? aux_stack_top - aux_data_end - : aux_stack_top; - LOG_VERBOSE("Found aux stack top global, value: %d, " - "global index: %d, stack size: %d", - aux_stack_top, global_index, - module->aux_stack_size); + ? (uint32)(aux_stack_top - aux_data_end) + : (uint32)aux_stack_top; + LOG_VERBOSE( + "Found aux stack top global, value: %" PRIu64 ", " + "global index: %d, stack size: %d", + aux_stack_top, global_index, + module->aux_stack_size); break; } } @@ -5939,29 +5931,36 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (aux_data_end_global && aux_heap_base_global && aux_stack_top_global) { uint64 init_memory_size; - uint32 shrunk_memory_size = align_uint(aux_heap_base, 8); + uint64 shrunk_memory_size = align_uint64(aux_heap_base, 8); - if (module->import_memory_count) { - memory_import = &module->import_memories[0].u.memory; - init_memory_size = (uint64)memory_import->num_bytes_per_page - * memory_import->init_page_count; - if (shrunk_memory_size <= init_memory_size) { - /* Reset memory info to decrease memory usage */ - memory_import->num_bytes_per_page = shrunk_memory_size; - memory_import->init_page_count = 1; - LOG_VERBOSE("Shrink import memory size to %d", - shrunk_memory_size); + /* Only resize(shrunk) the memory size if num_bytes_per_page is in + * valid range of uint32 */ + if (shrunk_memory_size <= UINT32_MAX) { + if (module->import_memory_count) { + memory_import = &module->import_memories[0].u.memory; + init_memory_size = (uint64)memory_import->num_bytes_per_page + * memory_import->init_page_count; + if (shrunk_memory_size <= init_memory_size) { + /* Reset memory info to decrease memory usage */ + memory_import->num_bytes_per_page = + (uint32)shrunk_memory_size; + memory_import->init_page_count = 1; + LOG_VERBOSE("Shrink import memory size to %" PRIu64, + shrunk_memory_size); + } } - } - if (module->memory_count) { - memory = &module->memories[0]; - init_memory_size = (uint64)memory->num_bytes_per_page - * memory->init_page_count; - if (shrunk_memory_size <= init_memory_size) { - /* Reset memory info to decrease memory usage */ - memory->num_bytes_per_page = shrunk_memory_size; - memory->init_page_count = 1; - LOG_VERBOSE("Shrink memory size to %d", shrunk_memory_size); + + if (module->memory_count) { + memory = &module->memories[0]; + init_memory_size = (uint64)memory->num_bytes_per_page + * memory->init_page_count; + if (shrunk_memory_size <= init_memory_size) { + /* Reset memory info to decrease memory usage */ + memory->num_bytes_per_page = (uint32)shrunk_memory_size; + memory->init_page_count = 1; + LOG_VERBOSE("Shrink memory size to %" PRIu64, + shrunk_memory_size); + } } } } @@ -5969,30 +5968,31 @@ load_from_sections(WASMModule *module, WASMSection *sections, #if WASM_ENABLE_MULTI_MODULE == 0 if (module->import_memory_count) { memory_import = &module->import_memories[0].u.memory; - if (memory_import->init_page_count < DEFAULT_MAX_PAGES) + /* Only resize the memory to one big page if num_bytes_per_page is + * in valid range of uint32 */ + if (memory_import->init_page_count < DEFAULT_MAX_PAGES) { memory_import->num_bytes_per_page *= memory_import->init_page_count; - else - memory_import->num_bytes_per_page = UINT32_MAX; - if (memory_import->init_page_count > 0) - memory_import->init_page_count = memory_import->max_page_count = - 1; - else - memory_import->init_page_count = memory_import->max_page_count = - 0; + if (memory_import->init_page_count > 0) + memory_import->init_page_count = + memory_import->max_page_count = 1; + else + memory_import->init_page_count = + memory_import->max_page_count = 0; + } } if (module->memory_count) { memory = &module->memories[0]; - if (memory->init_page_count < DEFAULT_MAX_PAGES) + /* Only resize(shrunk) the memory size if num_bytes_per_page is in + * valid range of uint32 */ + if (memory->init_page_count < DEFAULT_MAX_PAGES) { memory->num_bytes_per_page *= memory->init_page_count; - else - memory->num_bytes_per_page = UINT32_MAX; - - if (memory->init_page_count > 0) - memory->init_page_count = memory->max_page_count = 1; - else - memory->init_page_count = memory->max_page_count = 0; + if (memory->init_page_count > 0) + memory->init_page_count = memory->max_page_count = 1; + else + memory->init_page_count = memory->max_page_count = 0; + } } #endif } @@ -6043,7 +6043,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, } static WASMModule * -create_module(char *error_buf, uint32 error_buf_size) +create_module(char *name, char *error_buf, uint32 error_buf_size) { WASMModule *module = loader_malloc(sizeof(WASMModule), error_buf, error_buf_size); @@ -6058,6 +6058,8 @@ create_module(char *error_buf, uint32 error_buf_size) /* Set start_function to -1, means no start function */ module->start_function = (uint32)-1; + module->name = name; + #if WASM_ENABLE_FAST_INTERP == 0 module->br_table_cache_list = &module->br_table_cache_list_head; ret = bh_list_init(module->br_table_cache_list); @@ -6136,7 +6138,7 @@ WASMModule * wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf, uint32 error_buf_size) { - WASMModule *module = create_module(error_buf, error_buf_size); + WASMModule *module = create_module("", error_buf, error_buf_size); if (!module) return NULL; @@ -6477,9 +6479,9 @@ wasm_loader_load(uint8 *buf, uint32 size, #if WASM_ENABLE_MULTI_MODULE != 0 bool main_module, #endif - char *error_buf, uint32 error_buf_size) + const LoadArgs *args, char *error_buf, uint32 error_buf_size) { - WASMModule *module = create_module(error_buf, error_buf_size); + WASMModule *module = create_module(args->name, error_buf, error_buf_size); if (!module) { return NULL; } @@ -6666,7 +6668,7 @@ wasm_loader_unload(WASMModule *module) #if WASM_ENABLE_STRINGREF != 0 if (module->string_literal_ptrs) { - wasm_runtime_free(module->string_literal_ptrs); + wasm_runtime_free((void *)module->string_literal_ptrs); } if (module->string_literal_lengths) { wasm_runtime_free(module->string_literal_lengths); @@ -7100,8 +7102,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE32: - skip_leb_uint32(p, p_end); /* align */ - skip_leb_uint32(p, p_end); /* offset */ + skip_leb_uint32(p, p_end); /* align */ + skip_leb_mem_offset(p, p_end); /* offset */ break; case WASM_OP_MEMORY_SIZE: @@ -7447,6 +7449,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) case WASM_OP_SIMD_PREFIX: { + /* TODO: memory64 offset type changes */ uint32 opcode1; read_leb_uint32(p, p_end, opcode1); @@ -7543,6 +7546,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { + /* TODO: memory64 offset type changes */ uint32 opcode1; /* atomic_op (u32_leb) + memarg (2 u32_leb) */ @@ -7552,8 +7556,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, opcode = (uint8)opcode1; if (opcode != WASM_OP_ATOMIC_FENCE) { - skip_leb_uint32(p, p_end); /* align */ - skip_leb_uint32(p, p_end); /* offset */ + skip_leb_uint32(p, p_end); /* align */ + skip_leb_mem_offset(p, p_end); /* offset */ } else { /* atomic.fence doesn't have memarg */ @@ -8366,12 +8370,12 @@ wasm_loader_pop_nullable_ht(WASMLoaderContext *ctx, uint8 *p_type, } /* Convert to related (ref ht) and return */ - if ((type >= REF_TYPE_EQREF && type <= REF_TYPE_FUNCREF) - || (type >= REF_TYPE_NULLREF && type <= REF_TYPE_I31REF)) { - /* Return (ref func/extern/any/eq/i31/nofunc/noextern/struct/array/none) + if (type >= REF_TYPE_ARRAYREF && type <= REF_TYPE_NULLFUNCREF) { + /* Return (ref array/struct/i31/eq/any/extern/func/none/noextern/nofunc) */ wasm_set_refheaptype_common(&ref_ht_ret->ref_ht_common, false, - HEAP_TYPE_FUNC + (type - REF_TYPE_FUNCREF)); + HEAP_TYPE_ARRAY + + (type - REF_TYPE_ARRAYREF)); type = ref_ht_ret->ref_type; } else if (wasm_is_reftype_htref_nullable(type) @@ -8569,11 +8573,11 @@ wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, char *error_buf, wasm_loader_emit_ptr(loader_ctx, NULL); \ } while (0) -#define emit_br_info(frame_csp) \ - do { \ - if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, error_buf, \ - error_buf_size)) \ - goto fail; \ +#define emit_br_info(frame_csp, is_br) \ + do { \ + if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, is_br, error_buf, \ + error_buf_size)) \ + goto fail; \ } while (0) #define LAST_OP_OUTPUT_I32() \ @@ -8967,7 +8971,7 @@ apply_label_patch(WASMLoaderContext *ctx, uint8 depth, uint8 patch_type) static bool wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, - char *error_buf, uint32 error_buf_size) + bool is_br, char *error_buf, uint32 error_buf_size) { /* br info layout: * a) arity of target block @@ -9028,7 +9032,8 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, /* Part e */ dynamic_offset = frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); - ctx->dynamic_offset = dynamic_offset; + if (is_br) + ctx->dynamic_offset = dynamic_offset; for (i = (int32)arity - 1; i >= 0; i--) { cell = (uint8)wasm_value_type_cell_num(types[i]); dynamic_offset -= cell; @@ -9454,6 +9459,8 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, #define PUSH_EXTERNREF() TEMPLATE_PUSH(EXTERNREF) #define PUSH_REF(Type) TEMPLATE_PUSH_REF(Type) #define POP_REF(Type) TEMPLATE_POP_REF(Type) +#define PUSH_MEM_OFFSET() TEMPLATE_PUSH_REF(mem_offset_type) +#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET() #define POP_I32() TEMPLATE_POP(I32) #define POP_F32() TEMPLATE_POP(F32) @@ -9463,6 +9470,7 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, #define POP_FUNCREF() TEMPLATE_POP(FUNCREF) #define POP_EXTERNREF() TEMPLATE_POP(EXTERNREF) #define POP_STRINGREF() TEMPLATE_POP(STRINGREF) +#define POP_MEM_OFFSET() TEMPLATE_POP_REF(mem_offset_type) #if WASM_ENABLE_FAST_INTERP != 0 @@ -9896,8 +9904,8 @@ check_memory_align_equal(uint8 opcode, uint32 align, char *error_buf, #endif /* end of WASM_ENABLE_SHARED_MEMORY */ static bool -wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, - bool is_br_table, char *error_buf, uint32 error_buf_size) +wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, uint8 opcode, + char *error_buf, uint32 error_buf_size) { BranchBlock *target_block, *cur_block; BlockType *target_block_type; @@ -9994,7 +10002,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, /* Backup stack data since it may be changed in the below push operations, and the stack data may be used when checking other target blocks of opcode br_table */ - if (is_br_table) { + if (opcode == WASM_OP_BR_TABLE) { uint64 total_size; frame_ref_after_popped = loader_ctx->frame_ref; @@ -10058,13 +10066,13 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, } #if WASM_ENABLE_FAST_INTERP != 0 - emit_br_info(target_block); + emit_br_info(target_block, opcode == WASM_OP_BR); #endif /* Restore the stack data, note that frame_ref_bottom, frame_reftype_map_bottom, frame_offset_bottom may be re-allocated in the above push operations */ - if (is_br_table) { + if (opcode == WASM_OP_BR_TABLE) { uint32 total_size; /* The stack operand num should not be smaller than before @@ -10073,8 +10081,8 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, loader_ctx->stack_cell_num = stack_cell_num_old; loader_ctx->frame_ref = loader_ctx->frame_ref_bottom + stack_cell_num_old; - total_size = (uint32)sizeof(uint8) - * (frame_ref_old - frame_ref_after_popped); + total_size = (uint32)(sizeof(uint8) + * (frame_ref_old - frame_ref_after_popped)); bh_memcpy_s((uint8 *)loader_ctx->frame_ref - total_size, total_size, frame_ref_buf, total_size); @@ -10085,9 +10093,9 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, loader_ctx->reftype_map_num = reftype_map_num_old; loader_ctx->frame_reftype_map = loader_ctx->frame_reftype_map_bottom + reftype_map_num_old; - total_size = - (uint32)sizeof(WASMRefTypeMap) - * (frame_reftype_map_old - frame_reftype_map_after_popped); + total_size = (uint32)(sizeof(WASMRefTypeMap) + * (frame_reftype_map_old + - frame_reftype_map_after_popped)); bh_memcpy_s((uint8 *)loader_ctx->frame_reftype_map - total_size, total_size, frame_reftype_map_buf, total_size); #endif @@ -10095,8 +10103,9 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, #if WASM_ENABLE_FAST_INTERP != 0 loader_ctx->frame_offset = loader_ctx->frame_offset_bottom + stack_cell_num_old; - total_size = (uint32)sizeof(int16) - * (frame_offset_old - frame_offset_after_popped); + total_size = + (uint32)(sizeof(int16) + * (frame_offset_old - frame_offset_after_popped)); bh_memcpy_s((uint8 *)loader_ctx->frame_offset - total_size, total_size, frame_offset_buf, total_size); (loader_ctx->frame_csp - 1)->dynamic_offset = dynamic_offset_old; @@ -10155,7 +10164,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, } #if WASM_ENABLE_FAST_INTERP != 0 - emit_br_info(target_block); + emit_br_info(target_block, opcode == WASM_OP_BR); #endif ret = true; @@ -10170,7 +10179,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, #endif #if WASM_ENABLE_FAST_INTERP != 0 if (frame_offset_buf && frame_offset_buf != frame_offset_tmp) - wasm_runtime_free(frame_offset_tmp); + wasm_runtime_free(frame_offset_buf); #endif return ret; @@ -10178,14 +10187,14 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, static BranchBlock * check_branch_block(WASMLoaderContext *loader_ctx, uint8 **p_buf, uint8 *buf_end, - bool is_br_table, char *error_buf, uint32 error_buf_size) + uint8 opcode, char *error_buf, uint32 error_buf_size) { uint8 *p = *p_buf, *p_end = buf_end; BranchBlock *frame_csp_tmp; uint32 depth; read_leb_uint32(p, p_end, depth); - if (!wasm_loader_check_br(loader_ctx, depth, is_br_table, error_buf, + if (!wasm_loader_check_br(loader_ctx, depth, opcode, error_buf, error_buf_size)) { goto fail; } @@ -10226,7 +10235,7 @@ check_branch_block_for_delegate(WASMLoaderContext *loader_ctx, uint8 **p_buf, } frame_csp_tmp = loader_ctx->frame_csp - depth - 2; #if WASM_ENABLE_FAST_INTERP != 0 - emit_br_info(frame_csp_tmp); + emit_br_info(frame_csp_tmp, false); #endif *p_buf = p; @@ -10630,11 +10639,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org; uint32 param_count, local_count, global_count; - uint8 *param_types, *local_types, local_type, global_type; + uint8 *param_types, *local_types, local_type, global_type, mem_offset_type; BlockType func_block_type; uint16 *local_offsets, local_offset; uint32 type_idx, func_idx, local_idx, global_idx, table_idx; - uint32 table_seg_idx, data_seg_idx, count, align, mem_offset, i; + uint32 table_seg_idx, data_seg_idx, count, align, i; + mem_offset_t mem_offset; int32 i32_const = 0; int64 i64_const; uint8 opcode; @@ -10659,6 +10669,19 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n", func->param_cell_num, func->local_cell_num, func->ret_cell_num); #endif +#if WASM_ENABLE_MEMORY64 != 0 + bool is_memory64 = false; + /* TODO: multi-memories for now assuming the memory idx type is consistent + * across multi-memories */ + if (module->import_memory_count > 0) + is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG; + else if (module->memory_count > 0) + is_memory64 = module->memories[0].flags & MEMORY64_FLAG; + + mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32; +#else + mem_offset_type = VALUE_TYPE_I32; +#endif global_count = module->import_global_count + module->global_count; @@ -11102,7 +11125,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, /* check the target catching block: LABEL_TYPE_CATCH */ if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, false, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) goto fail; @@ -11389,7 +11412,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_BR: { if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, false, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) goto fail; @@ -11403,7 +11426,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, POP_I32(); if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, false, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) goto fail; @@ -11412,7 +11435,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_BR_TABLE: { - uint32 depth, default_arity, arity = 0; + uint32 depth = 0, default_arity, arity = 0; BranchBlock *target_block; BlockType *target_block_type; #if WASM_ENABLE_FAST_INTERP == 0 @@ -11473,7 +11496,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, true, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) { goto fail; } @@ -12378,7 +12401,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, if (opcode == WASM_OP_BR_ON_NULL) { if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, false, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) { goto fail; } @@ -12425,7 +12448,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, PUSH_REF(type); } if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, false, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) { goto fail; } @@ -12850,8 +12873,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } #endif CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ - read_leb_uint32(p, p_end, mem_offset); /* offset */ + read_leb_uint32(p, p_end, align); /* align */ + read_leb_mem_offset(p, p_end, mem_offset); /* offset */ if (!check_memory_access_align(opcode, align, error_buf, error_buf_size)) { goto fail; @@ -12869,7 +12892,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_I32_LOAD8_U: case WASM_OP_I32_LOAD16_S: case WASM_OP_I32_LOAD16_U: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32); break; case WASM_OP_I64_LOAD: case WASM_OP_I64_LOAD8_S: @@ -12878,35 +12901,35 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_I64_LOAD16_U: case WASM_OP_I64_LOAD32_S: case WASM_OP_I64_LOAD32_U: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64); break; case WASM_OP_F32_LOAD: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F32); break; case WASM_OP_F64_LOAD: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F64); break; /* store */ case WASM_OP_I32_STORE: case WASM_OP_I32_STORE8: case WASM_OP_I32_STORE16: POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_I64_STORE: case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE32: POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_F32_STORE: POP_F32(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_F64_STORE: POP_F64(); - POP_I32(); + POP_MEM_OFFSET(); break; default: break; @@ -12922,7 +12945,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, "zero byte expected"); goto fail; } - PUSH_I32(); + PUSH_PAGE_COUNT(); module->possible_memory_grow = true; #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 @@ -12938,7 +12961,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, "zero byte expected"); goto fail; } - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_AND_PUSH(mem_offset_type, mem_offset_type); module->possible_memory_grow = true; #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ @@ -13907,7 +13930,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } PUSH_REF(type_tmp); if (!(frame_csp_tmp = check_branch_block( - loader_ctx, &p, p_end, false, error_buf, + loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) { goto fail; } @@ -14299,7 +14322,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, POP_I32(); POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 func->has_memory_operations = true; #endif @@ -14342,9 +14365,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, && module->memory_count == 0) goto fail_unknown_memory; - POP_I32(); - POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); + POP_MEM_OFFSET(); + POP_MEM_OFFSET(); #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 func->has_memory_operations = true; #endif @@ -14362,10 +14385,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, && module->memory_count == 0) { goto fail_unknown_memory; } - - POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); POP_I32(); + POP_MEM_OFFSET(); #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 func->has_memory_operations = true; #endif @@ -14611,6 +14633,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) case WASM_OP_SIMD_PREFIX: { + /* TODO: memory64 offset type changes */ uint32 opcode1; #if WASM_ENABLE_WAMR_COMPILER != 0 @@ -15287,8 +15310,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif if (opcode1 != WASM_OP_ATOMIC_FENCE) { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ - read_leb_uint32(p, p_end, mem_offset); /* offset */ + read_leb_uint32(p, p_end, align); /* align */ + read_leb_mem_offset(p, p_end, mem_offset); /* offset */ if (!check_memory_align_equal(opcode1, align, error_buf, error_buf_size)) { goto fail; @@ -15302,18 +15325,20 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif switch (opcode1) { case WASM_OP_ATOMIC_NOTIFY: - POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_I32(); + POP_MEM_OFFSET(); + PUSH_I32(); break; case WASM_OP_ATOMIC_WAIT32: POP_I64(); POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I32(); break; case WASM_OP_ATOMIC_WAIT64: POP_I64(); POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I32(); break; case WASM_OP_ATOMIC_FENCE: @@ -15327,26 +15352,26 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_I32_LOAD: case WASM_OP_ATOMIC_I32_LOAD8_U: case WASM_OP_ATOMIC_I32_LOAD16_U: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32); break; case WASM_OP_ATOMIC_I32_STORE: case WASM_OP_ATOMIC_I32_STORE8: case WASM_OP_ATOMIC_I32_STORE16: POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_ATOMIC_I64_LOAD: case WASM_OP_ATOMIC_I64_LOAD8_U: case WASM_OP_ATOMIC_I64_LOAD16_U: case WASM_OP_ATOMIC_I64_LOAD32_U: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64); break; case WASM_OP_ATOMIC_I64_STORE: case WASM_OP_ATOMIC_I64_STORE8: case WASM_OP_ATOMIC_I64_STORE16: case WASM_OP_ATOMIC_I64_STORE32: POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_ATOMIC_RMW_I32_ADD: case WASM_OP_ATOMIC_RMW_I32_ADD8_U: @@ -15366,7 +15391,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_RMW_I32_XCHG: case WASM_OP_ATOMIC_RMW_I32_XCHG8_U: case WASM_OP_ATOMIC_RMW_I32_XCHG16_U: - POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_I32(); + POP_MEM_OFFSET(); + PUSH_I32(); break; case WASM_OP_ATOMIC_RMW_I64_ADD: case WASM_OP_ATOMIC_RMW_I64_ADD8_U: @@ -15393,7 +15420,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_RMW_I64_XCHG16_U: case WASM_OP_ATOMIC_RMW_I64_XCHG32_U: POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I64(); break; case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: @@ -15401,7 +15428,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: POP_I32(); POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I32(); break; case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: @@ -15410,7 +15437,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: POP_I64(); POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I64(); break; default: diff --git a/core/iwasm/interpreter/wasm_loader.h b/core/iwasm/interpreter/wasm_loader.h index 8b0dc77d61..676770ee22 100644 --- a/core/iwasm/interpreter/wasm_loader.h +++ b/core/iwasm/interpreter/wasm_loader.h @@ -28,7 +28,7 @@ wasm_loader_load(uint8 *buf, uint32 size, #if WASM_ENABLE_MULTI_MODULE != 0 bool main_module, #endif - char *error_buf, uint32 error_buf_size); + const LoadArgs *args, char *error_buf, uint32 error_buf_size); /** * Load a WASM module from a specified WASM section list. diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 2b28d676cc..dc96a194d6 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -47,6 +47,7 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) #define skip_leb_int64(p, p_end) skip_leb(p) #define skip_leb_uint32(p, p_end) skip_leb(p) #define skip_leb_int32(p, p_end) skip_leb(p) +#define skip_leb_mem_offset(p, p_end) skip_leb(p) static bool is_32bit_type(uint8 type) @@ -116,7 +117,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, } else if (sign && maxbits == 32) { if (shift < maxbits) { - /* Sign extend, second highest bit is the sign bit */ + /* Sign extend, second-highest bit is the sign bit */ if ((uint8)byte & 0x40) result |= (~((uint64)0)) << shift; } @@ -132,7 +133,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, } else if (sign && maxbits == 64) { if (shift < maxbits) { - /* Sign extend, second highest bit is the sign bit */ + /* Sign extend, second-highest bit is the sign bit */ if ((uint8)byte & 0x40) result |= (~((uint64)0)) << shift; } @@ -180,6 +181,18 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, res = (int32)res64; \ } while (0) +#if WASM_ENABLE_MEMORY64 != 0 +#define read_leb_mem_offset(p, p_end, res) \ + do { \ + uint64 res64; \ + read_leb((uint8 **)&p, p_end, is_memory64 ? 64 : 32, false, &res64, \ + error_buf, error_buf_size); \ + res = (mem_offset_t)res64; \ + } while (0) +#else +#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res) +#endif + static void * loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) { @@ -217,63 +230,6 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf, mem = mem_new; \ } while (0) -static char * -const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, - bool is_load_from_file_buf, char *error_buf, - uint32 error_buf_size) -{ - StringNode *node, *node_next; - - if (len == 0) { - return ""; - } - else if (is_load_from_file_buf) { - /* As the file buffer can be referred to after loading, we use - the previous byte of leb encoded size to adjust the string: - move string 1 byte backward and then append '\0' */ - char *c_str = (char *)str - 1; - bh_memmove_s(c_str, len + 1, c_str + 1, len); - c_str[len] = '\0'; - return c_str; - } - - /* Search const str list */ - node = module->const_str_list; - while (node) { - node_next = node->next; - if (strlen(node->str) == len && !memcmp(node->str, str, len)) - break; - node = node_next; - } - - if (node) { - LOG_DEBUG("reuse %s", node->str); - return node->str; - } - - if (!(node = loader_malloc(sizeof(StringNode) + len + 1, error_buf, - error_buf_size))) { - return NULL; - } - - node->str = ((char *)node) + sizeof(StringNode); - bh_memcpy_s(node->str, len + 1, str, len); - node->str[len] = '\0'; - - if (!module->const_str_list) { - /* set as head */ - module->const_str_list = node; - node->next = NULL; - } - else { - /* insert it */ - node->next = module->const_str_list; - module->const_str_list = node; - } - - return node->str; -} - static void destroy_wasm_type(WASMFuncType *type) { @@ -740,6 +696,38 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, return true; } +static bool +check_memory_flag(const uint8 mem_flag) +{ + /* Check whether certain features indicated by mem_flag are enabled in + * runtime */ + if (mem_flag > MAX_PAGE_COUNT_FLAG) { +#if WASM_ENABLE_SHARED_MEMORY == 0 + if (mem_flag & SHARED_MEMORY_FLAG) { + LOG_VERBOSE("shared memory flag was found, please enable shared " + "memory, lib-pthread or lib-wasi-threads"); + return false; + } +#endif +#if WASM_ENABLE_MEMORY64 == 0 + if (mem_flag & MEMORY64_FLAG) { + LOG_VERBOSE("memory64 flag was found, please enable memory64"); + return false; + } +#endif + } + + if (mem_flag > MAX_PAGE_COUNT_FLAG + SHARED_MEMORY_FLAG + MEMORY64_FLAG) { + return false; + } + else if ((mem_flag & SHARED_MEMORY_FLAG) + && !(mem_flag & MAX_PAGE_COUNT_FLAG)) { + return false; + } + + return true; +} + static bool load_memory_import(const uint8 **p_buf, const uint8 *buf_end, WASMModule *parent_module, const char *sub_module_name, @@ -752,20 +740,28 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT / DEFAULT_NUM_BYTES_PER_PAGE; #else - uint32 max_page_count = DEFAULT_MAX_PAGES; + uint32 max_page_count; #endif /* WASM_ENABLE_APP_FRAMEWORK */ - uint32 declare_max_page_count_flag = 0; + uint32 mem_flag = 0; + bool is_memory64 = false; uint32 declare_init_page_count = 0; uint32 declare_max_page_count = 0; - read_leb_uint32(p, p_end, declare_max_page_count_flag); + read_leb_uint32(p, p_end, mem_flag); + bh_assert(check_memory_flag(mem_flag)); + +#if WASM_ENABLE_APP_FRAMEWORK == 0 + is_memory64 = mem_flag & MEMORY64_FLAG; + max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES; +#endif + read_leb_uint32(p, p_end, declare_init_page_count); - bh_assert(declare_init_page_count <= 65536); + bh_assert(declare_init_page_count <= max_page_count); - if (declare_max_page_count_flag & 1) { + if (mem_flag & MAX_PAGE_COUNT_FLAG) { read_leb_uint32(p, p_end, declare_max_page_count); bh_assert(declare_init_page_count <= declare_max_page_count); - bh_assert(declare_max_page_count <= 65536); + bh_assert(declare_max_page_count <= max_page_count); if (declare_max_page_count > max_page_count) { declare_max_page_count = max_page_count; } @@ -776,12 +772,13 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, } /* now we believe all declaration are ok */ - memory->flags = declare_max_page_count_flag; + memory->flags = mem_flag; memory->init_page_count = declare_init_page_count; memory->max_page_count = declare_max_page_count; memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; *p_buf = p; + (void)check_memory_flag; return true; } @@ -868,26 +865,28 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT / DEFAULT_NUM_BYTES_PER_PAGE; #else - uint32 max_page_count = DEFAULT_MAX_PAGES; + uint32 max_page_count; + bool is_memory64 = false; #endif p_org = p; read_leb_uint32(p, p_end, memory->flags); bh_assert(p - p_org <= 1); (void)p_org; -#if WASM_ENABLE_SHARED_MEMORY == 0 - bh_assert(memory->flags <= 1); -#else - bh_assert(memory->flags <= 3 && memory->flags != 2); + bh_assert(check_memory_flag(memory->flags)); + +#if WASM_ENABLE_APP_FRAMEWORK == 0 + is_memory64 = memory->flags & MEMORY64_FLAG; + max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES; #endif read_leb_uint32(p, p_end, memory->init_page_count); - bh_assert(memory->init_page_count <= 65536); + bh_assert(memory->init_page_count <= max_page_count); if (memory->flags & 1) { read_leb_uint32(p, p_end, memory->max_page_count); bh_assert(memory->init_page_count <= memory->max_page_count); - bh_assert(memory->max_page_count <= 65536); + bh_assert(memory->max_page_count <= max_page_count); if (memory->max_page_count > max_page_count) memory->max_page_count = max_page_count; } @@ -899,6 +898,7 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; *p_buf = p; + (void)check_memory_flag; return true; } @@ -1008,7 +1008,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, /* load module name */ read_leb_uint32(p, p_end, name_len); CHECK_BUF(p, p_end, name_len); - if (!(sub_module_name = const_str_list_insert( + if (!(sub_module_name = wasm_const_str_list_insert( p, name_len, module, is_load_from_file_buf, error_buf, error_buf_size))) { return false; @@ -1018,7 +1018,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, /* load field name */ read_leb_uint32(p, p_end, name_len); CHECK_BUF(p, p_end, name_len); - if (!(field_name = const_str_list_insert( + if (!(field_name = wasm_const_str_list_insert( p, name_len, module, is_load_from_file_buf, error_buf, error_buf_size))) { return false; @@ -1426,7 +1426,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, && memcmp(name, p, str_len) == 0)); } - if (!(export->name = const_str_list_insert( + if (!(export->name = wasm_const_str_list_insert( p, str_len, module, is_load_from_file_buf, error_buf, error_buf_size))) { return false; @@ -1761,6 +1761,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, bool is_passive = false; uint32 mem_flag; #endif + uint8 mem_offset_type; read_leb_uint32(p, p_end, data_seg_count); @@ -1807,11 +1808,35 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, < module->import_memory_count + module->memory_count); #endif /* WASM_ENABLE_BULK_MEMORY */ +#if WASM_ENABLE_BULK_MEMORY != 0 + if (!is_passive) +#endif /* WASM_ENABLE_BULK_MEMORY */ + { +#if WASM_ENABLE_MEMORY64 != 0 + /* This memory_flag is from memory instead of data segment */ + uint8 memory_flag; + if (module->import_memory_count > 0) { + memory_flag = + module->import_memories[mem_index].u.memory.flags; + } + else { + memory_flag = + module + ->memories[mem_index - module->import_memory_count] + .flags; + } + mem_offset_type = memory_flag & MEMORY64_FLAG ? VALUE_TYPE_I64 + : VALUE_TYPE_I32; +#else + mem_offset_type = VALUE_TYPE_I32; +#endif /* WASM_ENABLE_MEMORY64 */ + } + #if WASM_ENABLE_BULK_MEMORY != 0 if (!is_passive) #endif if (!load_init_expr(module, &p, p_end, &init_expr, - VALUE_TYPE_I32, error_buf, error_buf_size)) + mem_offset_type, error_buf, error_buf_size)) return false; read_leb_uint32(p, p_end, data_seg_len); @@ -1957,7 +1982,7 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, func_index -= module->import_function_count; bh_assert(func_index < module->function_count); if (!(module->functions[func_index]->field_name = - const_str_list_insert( + wasm_const_str_list_insert( p, func_name_len, module, is_load_from_file_buf, error_buf, error_buf_size))) { @@ -1999,7 +2024,7 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, bh_assert(name_len > 0 && p + name_len <= p_end); #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 - if (memcmp(p, "name", 4) == 0) { + if (name_len == 4 && memcmp(p, "name", 4) == 0) { p += name_len; handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf, error_buf_size); @@ -2542,8 +2567,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, *buf_func = NULL, *buf_func_end = NULL; WASMGlobal *aux_data_end_global = NULL, *aux_heap_base_global = NULL; WASMGlobal *aux_stack_top_global = NULL, *global; - uint32 aux_data_end = (uint32)-1, aux_heap_base = (uint32)-1; - uint32 aux_stack_top = (uint32)-1, global_index, func_index, i; + uint64 aux_data_end = (uint64)-1LL, aux_heap_base = (uint64)-1LL, + aux_stack_top = (uint64)-1LL; + uint32 global_index, func_index, i; uint32 aux_data_end_global_index = (uint32)-1; uint32 aux_heap_base_global_index = (uint32)-1; WASMFuncType *func_type; @@ -2661,9 +2687,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, && global->init_expr.init_expr_type == INIT_EXPR_TYPE_I32_CONST) { aux_heap_base_global = global; - aux_heap_base = global->init_expr.u.i32; + aux_heap_base = (uint64)(uint32)global->init_expr.u.i32; aux_heap_base_global_index = export->index; - LOG_VERBOSE("Found aux __heap_base global, value: %d", + LOG_VERBOSE("Found aux __heap_base global, value: %" PRIu64, aux_heap_base); } } @@ -2674,12 +2700,11 @@ load_from_sections(WASMModule *module, WASMSection *sections, && global->init_expr.init_expr_type == INIT_EXPR_TYPE_I32_CONST) { aux_data_end_global = global; - aux_data_end = global->init_expr.u.i32; + aux_data_end = (uint64)(uint32)global->init_expr.u.i32; aux_data_end_global_index = export->index; - LOG_VERBOSE("Found aux __data_end global, value: %d", + LOG_VERBOSE("Found aux __data_end global, value: %" PRIu64, aux_data_end); - - aux_data_end = align_uint(aux_data_end, 16); + aux_data_end = align_uint64(aux_data_end, 16); } } @@ -2715,20 +2740,22 @@ load_from_sections(WASMModule *module, WASMSection *sections, && global->type == VALUE_TYPE_I32 && global->init_expr.init_expr_type == INIT_EXPR_TYPE_I32_CONST - && (uint32)global->init_expr.u.i32 <= aux_heap_base) { + && (uint64)(uint32)global->init_expr.u.i32 + <= aux_heap_base) { aux_stack_top_global = global; - aux_stack_top = (uint32)global->init_expr.u.i32; + aux_stack_top = (uint64)(uint32)global->init_expr.u.i32; module->aux_stack_top_global_index = module->import_global_count + global_index; module->aux_stack_bottom = aux_stack_top; module->aux_stack_size = aux_stack_top > aux_data_end - ? aux_stack_top - aux_data_end - : aux_stack_top; - LOG_VERBOSE("Found aux stack top global, value: %d, " - "global index: %d, stack size: %d", - aux_stack_top, global_index, - module->aux_stack_size); + ? (uint32)(aux_stack_top - aux_data_end) + : (uint32)aux_stack_top; + LOG_VERBOSE( + "Found aux stack top global, value: %" PRIu64 ", " + "global index: %d, stack size: %d", + aux_stack_top, global_index, + module->aux_stack_size); break; } } @@ -2862,60 +2889,62 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (aux_data_end_global && aux_heap_base_global && aux_stack_top_global) { uint64 init_memory_size; - uint32 shrunk_memory_size = align_uint(aux_heap_base, 8); - - if (module->import_memory_count) { - memory_import = &module->import_memories[0].u.memory; - init_memory_size = (uint64)memory_import->num_bytes_per_page - * memory_import->init_page_count; - if (shrunk_memory_size <= init_memory_size) { - /* Reset memory info to decrease memory usage */ - memory_import->num_bytes_per_page = shrunk_memory_size; - memory_import->init_page_count = 1; - LOG_VERBOSE("Shrink import memory size to %d", - shrunk_memory_size); + uint64 shrunk_memory_size = align_uint64(aux_heap_base, 8); + + /* Only resize(shrunk) the memory size if num_bytes_per_page is in + * valid range of uint32 */ + if (shrunk_memory_size <= UINT32_MAX) { + if (module->import_memory_count) { + memory_import = &module->import_memories[0].u.memory; + init_memory_size = (uint64)memory_import->num_bytes_per_page + * memory_import->init_page_count; + if (shrunk_memory_size <= init_memory_size) { + /* Reset memory info to decrease memory usage */ + memory_import->num_bytes_per_page = shrunk_memory_size; + memory_import->init_page_count = 1; + LOG_VERBOSE("Shrink import memory size to %" PRIu64, + shrunk_memory_size); + } } - } - if (module->memory_count) { - memory = &module->memories[0]; - init_memory_size = (uint64)memory->num_bytes_per_page - * memory->init_page_count; - if (shrunk_memory_size <= init_memory_size) { - /* Reset memory info to decrease memory usage */ - memory->num_bytes_per_page = shrunk_memory_size; - memory->init_page_count = 1; - LOG_VERBOSE("Shrink memory size to %d", shrunk_memory_size); + + if (module->memory_count) { + memory = &module->memories[0]; + init_memory_size = (uint64)memory->num_bytes_per_page + * memory->init_page_count; + if (shrunk_memory_size <= init_memory_size) { + /* Reset memory info to decrease memory usage */ + memory->num_bytes_per_page = shrunk_memory_size; + memory->init_page_count = 1; + LOG_VERBOSE("Shrink memory size to %" PRIu64, + shrunk_memory_size); + } } } } if (module->import_memory_count) { memory_import = &module->import_memories[0].u.memory; - if (memory_import->init_page_count < DEFAULT_MAX_PAGES) + if (memory_import->init_page_count < DEFAULT_MAX_PAGES) { memory_import->num_bytes_per_page *= memory_import->init_page_count; - else - memory_import->num_bytes_per_page = UINT32_MAX; - - if (memory_import->init_page_count > 0) - memory_import->init_page_count = memory_import->max_page_count = - 1; - else - memory_import->init_page_count = memory_import->max_page_count = - 0; + if (memory_import->init_page_count > 0) + memory_import->init_page_count = + memory_import->max_page_count = 1; + else + memory_import->init_page_count = + memory_import->max_page_count = 0; + } } if (module->memory_count) { memory = &module->memories[0]; - if (memory->init_page_count < DEFAULT_MAX_PAGES) + if (memory->init_page_count < DEFAULT_MAX_PAGES) { memory->num_bytes_per_page *= memory->init_page_count; - else - memory->num_bytes_per_page = UINT32_MAX; - - if (memory->init_page_count > 0) - memory->init_page_count = memory->max_page_count = 1; - else - memory->init_page_count = memory->max_page_count = 0; + if (memory->init_page_count > 0) + memory->init_page_count = memory->max_page_count = 1; + else + memory->init_page_count = memory->max_page_count = 0; + } } } @@ -2965,7 +2994,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, } static WASMModule * -create_module(char *error_buf, uint32 error_buf_size) +create_module(char *name, char *error_buf, uint32 error_buf_size) { WASMModule *module = loader_malloc(sizeof(WASMModule), error_buf, error_buf_size); @@ -2980,6 +3009,8 @@ create_module(char *error_buf, uint32 error_buf_size) /* Set start_function to -1, means no start function */ module->start_function = (uint32)-1; + module->name = name; + #if WASM_ENABLE_FAST_INTERP == 0 module->br_table_cache_list = &module->br_table_cache_list_head; ret = bh_list_init(module->br_table_cache_list); @@ -3004,7 +3035,7 @@ WASMModule * wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf, uint32 error_buf_size) { - WASMModule *module = create_module(error_buf, error_buf_size); + WASMModule *module = create_module("", error_buf, error_buf_size); if (!module) return NULL; @@ -3175,10 +3206,10 @@ load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf, } WASMModule * -wasm_loader_load(uint8 *buf, uint32 size, char *error_buf, +wasm_loader_load(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf, uint32 error_buf_size) { - WASMModule *module = create_module(error_buf, error_buf_size); + WASMModule *module = create_module(args->name, error_buf, error_buf_size); if (!module) { return NULL; } @@ -3584,8 +3615,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE32: - skip_leb_uint32(p, p_end); /* align */ - skip_leb_uint32(p, p_end); /* offset */ + skip_leb_uint32(p, p_end); /* align */ + skip_leb_mem_offset(p, p_end); /* offset */ break; case WASM_OP_MEMORY_SIZE: @@ -3800,6 +3831,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { + /* TODO: memory64 offset type changes */ uint32 opcode1; /* atomic_op (u32_leb) + memarg (2 u32_leb) */ @@ -3809,8 +3841,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, opcode = (uint8)opcode1; if (opcode != WASM_OP_ATOMIC_FENCE) { - skip_leb_uint32(p, p_end); /* align */ - skip_leb_uint32(p, p_end); /* offset */ + skip_leb_uint32(p, p_end); /* align */ + skip_leb_mem_offset(p, p_end); /* offset */ } else { /* atomic.fence doesn't have memarg */ @@ -4312,11 +4344,11 @@ wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, char *error_buf, wasm_loader_emit_ptr(loader_ctx, NULL); \ } while (0) -#define emit_br_info(frame_csp) \ - do { \ - if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, error_buf, \ - error_buf_size)) \ - goto fail; \ +#define emit_br_info(frame_csp, is_br) \ + do { \ + if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, is_br, error_buf, \ + error_buf_size)) \ + goto fail; \ } while (0) #define LAST_OP_OUTPUT_I32() \ @@ -4701,7 +4733,7 @@ apply_label_patch(WASMLoaderContext *ctx, uint8 depth, uint8 patch_type) static bool wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, - char *error_buf, uint32 error_buf_size) + bool is_br, char *error_buf, uint32 error_buf_size) { /* br info layout: * a) arity of target block @@ -4750,7 +4782,8 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, /* Part e */ dynamic_offset = frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); - ctx->dynamic_offset = dynamic_offset; + if (is_br) + ctx->dynamic_offset = dynamic_offset; for (i = (int32)arity - 1; i >= 0; i--) { cell = (uint8)wasm_value_type_cell_num(types[i]); dynamic_offset -= cell; @@ -5126,6 +5159,11 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, goto fail; \ } while (0) +#define PUSH_MEM_OFFSET() PUSH_OFFSET_TYPE(mem_offset_type) +#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET() + +#define POP_MEM_OFFSET() POP_OFFSET_TYPE(mem_offset_type) + #define POP_AND_PUSH(type_pop, type_push) \ do { \ if (!(wasm_loader_push_pop_frame_ref_offset( \ @@ -5180,6 +5218,15 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, goto fail; \ } while (0) +#define PUSH_MEM_OFFSET() \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, mem_offset_type, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET() + #define POP_I32() \ do { \ if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I32, error_buf, \ @@ -5215,6 +5262,13 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, goto fail; \ } while (0) +#define POP_MEM_OFFSET() \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, mem_offset_type, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + #define POP_AND_PUSH(type_pop, type_push) \ do { \ if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, type_push, \ @@ -5435,8 +5489,8 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode, } while (0) static bool -wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, - bool is_br_table, char *error_buf, uint32 error_buf_size) +wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, uint8 opcode, + char *error_buf, uint32 error_buf_size) { BranchBlock *target_block, *cur_block; BlockType *target_block_type; @@ -5494,7 +5548,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, /* Backup stack data since it may be changed in the below push operations, and the stack data may be used when checking other target blocks of opcode br_table */ - if (is_br_table) { + if (opcode == WASM_OP_BR_TABLE) { uint64 total_size; frame_ref_after_popped = loader_ctx->frame_ref; @@ -5532,13 +5586,13 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, } #if WASM_ENABLE_FAST_INTERP != 0 - emit_br_info(target_block); + emit_br_info(target_block, opcode == WASM_OP_BR); #endif /* Restore the stack data, note that frame_ref_bottom, frame_reftype_map_bottom, frame_offset_bottom may be re-allocated in the above push operations */ - if (is_br_table) { + if (opcode == WASM_OP_BR_TABLE) { uint32 total_size; /* The stack operand num should not be smaller than before @@ -5582,7 +5636,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, } #if WASM_ENABLE_FAST_INTERP != 0 - emit_br_info(target_block); + emit_br_info(target_block, opcode == WASM_OP_BR); #endif ret = true; @@ -5593,7 +5647,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, wasm_runtime_free(frame_ref_buf); #if WASM_ENABLE_FAST_INTERP != 0 if (frame_offset_buf && frame_offset_buf != frame_offset_tmp) - wasm_runtime_free(frame_offset_tmp); + wasm_runtime_free(frame_offset_buf); #endif return ret; @@ -5601,14 +5655,14 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, static BranchBlock * check_branch_block(WASMLoaderContext *loader_ctx, uint8 **p_buf, uint8 *buf_end, - bool is_br_table, char *error_buf, uint32 error_buf_size) + uint8 opcode, char *error_buf, uint32 error_buf_size) { uint8 *p = *p_buf, *p_end = buf_end; BranchBlock *frame_csp_tmp; uint32 depth; read_leb_uint32(p, p_end, depth); - if (!wasm_loader_check_br(loader_ctx, depth, is_br_table, error_buf, + if (!wasm_loader_check_br(loader_ctx, depth, opcode, error_buf, error_buf_size)) { goto fail; } @@ -5825,10 +5879,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org; uint32 param_count, local_count, global_count; - uint8 *param_types, *local_types, local_type, global_type; + uint8 *param_types, *local_types, local_type, global_type, mem_offset_type; BlockType func_block_type; uint16 *local_offsets, local_offset; - uint32 count, local_idx, global_idx, u32, align, mem_offset, i; + uint32 count, local_idx, global_idx, u32, align, i; + mem_offset_t mem_offset; int32 i32, i32_const = 0; int64 i64_const; uint8 opcode, u8; @@ -5850,6 +5905,19 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n", func->param_cell_num, func->local_cell_num, func->ret_cell_num); #endif +#if WASM_ENABLE_MEMORY64 != 0 + bool is_memory64 = false; + /* TODO: multi-memories for now assuming the memory idx type is consistent + * across multi-memories */ + if (module->import_memory_count > 0) + is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG; + else if (module->memory_count > 0) + is_memory64 = module->memories[0].flags & MEMORY64_FLAG; + + mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32; +#else + mem_offset_type = VALUE_TYPE_I32; +#endif global_count = module->import_global_count + module->global_count; @@ -6232,7 +6300,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_BR: { if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, false, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) goto fail; @@ -6246,7 +6314,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, POP_I32(); if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, false, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) goto fail; @@ -6276,7 +6344,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif for (i = 0; i <= count; i++) { if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, true, + check_branch_block(loader_ctx, &p, p_end, opcode, error_buf, error_buf_size))) goto fail; @@ -7158,8 +7226,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } #endif CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ - read_leb_uint32(p, p_end, mem_offset); /* offset */ + read_leb_uint32(p, p_end, align); /* align */ + read_leb_mem_offset(p, p_end, mem_offset); /* offset */ #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, mem_offset); #endif @@ -7173,7 +7241,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_I32_LOAD8_U: case WASM_OP_I32_LOAD16_S: case WASM_OP_I32_LOAD16_U: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32); break; case WASM_OP_I64_LOAD: case WASM_OP_I64_LOAD8_S: @@ -7182,35 +7250,35 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_I64_LOAD16_U: case WASM_OP_I64_LOAD32_S: case WASM_OP_I64_LOAD32_U: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64); break; case WASM_OP_F32_LOAD: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F32); break; case WASM_OP_F64_LOAD: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F64); break; /* store */ case WASM_OP_I32_STORE: case WASM_OP_I32_STORE8: case WASM_OP_I32_STORE16: POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_I64_STORE: case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE32: POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_F32_STORE: POP_F32(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_F64_STORE: POP_F64(); - POP_I32(); + POP_MEM_OFFSET(); break; default: break; @@ -7223,7 +7291,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, /* reserved byte 0x00 */ bh_assert(*p == 0x00); p++; - PUSH_I32(); + PUSH_PAGE_COUNT(); module->possible_memory_grow = true; #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 @@ -7236,7 +7304,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, /* reserved byte 0x00 */ bh_assert(*p == 0x00); p++; - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_AND_PUSH(mem_offset_type, mem_offset_type); module->possible_memory_grow = true; #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ @@ -7587,7 +7655,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, POP_I32(); POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 func->has_memory_operations = true; #endif @@ -7616,9 +7684,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, + module->memory_count > 0); - POP_I32(); - POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); + POP_MEM_OFFSET(); + POP_MEM_OFFSET(); #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 func->has_memory_operations = true; #endif @@ -7633,9 +7701,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, + module->memory_count > 0); + POP_MEM_OFFSET(); POP_I32(); - POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 func->has_memory_operations = true; #endif @@ -7799,8 +7867,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif if (opcode1 != WASM_OP_ATOMIC_FENCE) { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ - read_leb_uint32(p, p_end, mem_offset); /* offset */ + read_leb_uint32(p, p_end, align); /* align */ + read_leb_mem_offset(p, p_end, mem_offset); /* offset */ #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, mem_offset); #endif @@ -7810,18 +7878,20 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif switch (opcode1) { case WASM_OP_ATOMIC_NOTIFY: - POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_I32(); + POP_MEM_OFFSET(); + PUSH_I32(); break; case WASM_OP_ATOMIC_WAIT32: POP_I64(); POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I32(); break; case WASM_OP_ATOMIC_WAIT64: POP_I64(); POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I32(); break; case WASM_OP_ATOMIC_FENCE: @@ -7832,26 +7902,26 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_I32_LOAD: case WASM_OP_ATOMIC_I32_LOAD8_U: case WASM_OP_ATOMIC_I32_LOAD16_U: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32); break; case WASM_OP_ATOMIC_I32_STORE: case WASM_OP_ATOMIC_I32_STORE8: case WASM_OP_ATOMIC_I32_STORE16: POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_ATOMIC_I64_LOAD: case WASM_OP_ATOMIC_I64_LOAD8_U: case WASM_OP_ATOMIC_I64_LOAD16_U: case WASM_OP_ATOMIC_I64_LOAD32_U: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64); + POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64); break; case WASM_OP_ATOMIC_I64_STORE: case WASM_OP_ATOMIC_I64_STORE8: case WASM_OP_ATOMIC_I64_STORE16: case WASM_OP_ATOMIC_I64_STORE32: POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); break; case WASM_OP_ATOMIC_RMW_I32_ADD: case WASM_OP_ATOMIC_RMW_I32_ADD8_U: @@ -7871,7 +7941,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_RMW_I32_XCHG: case WASM_OP_ATOMIC_RMW_I32_XCHG8_U: case WASM_OP_ATOMIC_RMW_I32_XCHG16_U: - POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); + POP_I32(); + POP_MEM_OFFSET(); + PUSH_I32(); break; case WASM_OP_ATOMIC_RMW_I64_ADD: case WASM_OP_ATOMIC_RMW_I64_ADD8_U: @@ -7898,7 +7970,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_RMW_I64_XCHG16_U: case WASM_OP_ATOMIC_RMW_I64_XCHG32_U: POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I64(); break; case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: @@ -7906,7 +7978,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: POP_I32(); POP_I32(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I32(); break; case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: @@ -7915,7 +7987,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: POP_I64(); POP_I64(); - POP_I32(); + POP_MEM_OFFSET(); PUSH_I64(); break; default: diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index a75a204bbe..688f1c2c14 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -60,13 +60,13 @@ wasm_load(uint8 *buf, uint32 size, #if WASM_ENABLE_MULTI_MODULE != 0 bool main_module, #endif - char *error_buf, uint32 error_buf_size) + const LoadArgs *name, char *error_buf, uint32 error_buf_size) { return wasm_loader_load(buf, size, #if WASM_ENABLE_MULTI_MODULE != 0 main_module, #endif - error_buf, error_buf_size); + name, error_buf, error_buf_size); } WASMModule * @@ -162,15 +162,16 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, char *error_buf, uint32 error_buf_size) { WASMModule *module = module_inst->module; - uint64 memory_data_size, max_memory_data_size; - uint32 heap_offset = num_bytes_per_page * init_page_count; - uint32 inc_page_count, aux_heap_base, global_idx; + uint32 inc_page_count, global_idx, default_max_page; uint32 bytes_of_last_page, bytes_to_page_end; + uint64 aux_heap_base, + heap_offset = (uint64)num_bytes_per_page * init_page_count; + uint64 memory_data_size, max_memory_data_size; uint8 *global_addr; bool is_shared_memory = false; #if WASM_ENABLE_SHARED_MEMORY != 0 - is_shared_memory = flags & 0x02 ? true : false; + is_shared_memory = flags & SHARED_MEMORY_FLAG ? true : false; /* shared memory */ if (is_shared_memory && parent != NULL) { @@ -185,6 +186,14 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, (void)flags; #endif /* end of WASM_ENABLE_SHARED_MEMORY */ +#if WASM_ENABLE_MEMORY64 != 0 + if (flags & MEMORY64_FLAG) { + memory->is_memory64 = 1; + } +#endif + default_max_page = + memory->is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES; + if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1 && module_inst->module->free_function != (uint32)-1) { /* Disable app heap, use malloc/free function exported @@ -192,6 +201,16 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, heap_size = 0; } + /* If initial memory is the largest size allowed, disallowing insert host + * managed heap */ + if (heap_size > 0 + && heap_offset == GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)) { + set_error_buf(error_buf, error_buf_size, + "failed to insert app heap into linear memory, " + "try using `--heap-size=0` option"); + return NULL; + } + if (init_page_count == max_page_count && init_page_count == 1) { /* If only one page and at most one page, we just append the app heap to the end of linear memory, enlarge the @@ -215,7 +234,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, } else if (module->aux_heap_base_global_index != (uint32)-1 && module->aux_heap_base - < num_bytes_per_page * init_page_count) { + < (uint64)num_bytes_per_page * init_page_count) { /* Insert app heap before __heap_base */ aux_heap_base = module->aux_heap_base; bytes_of_last_page = aux_heap_base % num_bytes_per_page; @@ -243,54 +262,58 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, && global_idx < module_inst->e->global_count); global_addr = module_inst->global_data + module_inst->e->globals[global_idx].data_offset; - *(uint32 *)global_addr = aux_heap_base; - LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base); +#if WASM_ENABLE_MEMORY64 != 0 + if (memory->is_memory64) { + /* For memory64, the global value should be i64 */ + *(uint64 *)global_addr = aux_heap_base; + } + else +#endif + { + /* For memory32, the global value should be i32 */ + *(uint32 *)global_addr = (uint32)aux_heap_base; + } + LOG_VERBOSE("Reset __heap_base global to %" PRIu64, aux_heap_base); } else { /* Insert app heap before new page */ inc_page_count = (heap_size + num_bytes_per_page - 1) / num_bytes_per_page; - heap_offset = num_bytes_per_page * init_page_count; - heap_size = num_bytes_per_page * inc_page_count; + heap_offset = (uint64)num_bytes_per_page * init_page_count; + heap_size = (uint64)num_bytes_per_page * inc_page_count; if (heap_size > 0) heap_size -= 1 * BH_KB; } init_page_count += inc_page_count; max_page_count += inc_page_count; - if (init_page_count > DEFAULT_MAX_PAGES) { + if (init_page_count > default_max_page) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " "try using `--heap-size=0` option"); return NULL; } - else if (init_page_count == DEFAULT_MAX_PAGES) { - num_bytes_per_page = UINT32_MAX; - init_page_count = max_page_count = 1; - } - if (max_page_count > DEFAULT_MAX_PAGES) - max_page_count = DEFAULT_MAX_PAGES; - } - else { /* heap_size == 0 */ - if (init_page_count == DEFAULT_MAX_PAGES) { - num_bytes_per_page = UINT32_MAX; - init_page_count = max_page_count = 1; - } + + if (max_page_count > default_max_page) + max_page_count = default_max_page; } LOG_VERBOSE("Memory instantiate:"); LOG_VERBOSE(" page bytes: %u, init pages: %u, max pages: %u", num_bytes_per_page, init_page_count, max_page_count); - LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size); + LOG_VERBOSE(" heap offset: %" PRIu64 ", heap size: %u\n", heap_offset, + heap_size); max_memory_data_size = (uint64)num_bytes_per_page * max_page_count; - bh_assert(max_memory_data_size <= 4 * (uint64)BH_GB); + bh_assert(max_memory_data_size + <= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)); (void)max_memory_data_size; bh_assert(memory != NULL); if (wasm_allocate_linear_memory(&memory->memory_data, is_shared_memory, - num_bytes_per_page, init_page_count, - max_page_count, &memory_data_size) + memory->is_memory64, num_bytes_per_page, + init_page_count, max_page_count, + &memory_data_size) != BHT_OK) { set_error_buf(error_buf, error_buf_size, "allocate linear memory failed"); @@ -301,11 +324,11 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = init_page_count; memory->max_page_count = max_page_count; - memory->memory_data_size = (uint32)memory_data_size; + memory->memory_data_size = memory_data_size; memory->heap_data = memory->memory_data + heap_offset; memory->heap_data_end = memory->heap_data + heap_size; - memory->memory_data_end = memory->memory_data + (uint32)memory_data_size; + memory->memory_data_end = memory->memory_data + memory_data_size; /* Initialize heap */ if (heap_size > 0) { @@ -353,7 +376,8 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, static WASMMemoryInstance ** memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, WASMModuleInstance *parent, uint32 heap_size, - char *error_buf, uint32 error_buf_size) + uint32 max_memory_pages, char *error_buf, + uint32 error_buf_size) { WASMImport *import; uint32 mem_index = 0, i, @@ -374,7 +398,9 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, for (i = 0; i < module->import_memory_count; i++, import++, memory++) { uint32 num_bytes_per_page = import->u.memory.num_bytes_per_page; uint32 init_page_count = import->u.memory.init_page_count; - uint32 max_page_count = import->u.memory.max_page_count; + uint32 max_page_count = wasm_runtime_get_max_mem( + max_memory_pages, import->u.memory.init_page_count, + import->u.memory.max_page_count); uint32 flags = import->u.memory.flags; uint32 actual_heap_size = heap_size; @@ -412,12 +438,15 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, /* instantiate memories from memory section */ for (i = 0; i < module->memory_count; i++, memory++) { + uint32 max_page_count = wasm_runtime_get_max_mem( + max_memory_pages, module->memories[i].init_page_count, + module->memories[i].max_page_count); if (!(memories[mem_index] = memory_instantiate( module_inst, parent, memory, mem_index, module->memories[i].num_bytes_per_page, - module->memories[i].init_page_count, - module->memories[i].max_page_count, heap_size, - module->memories[i].flags, error_buf, error_buf_size))) { + module->memories[i].init_page_count, max_page_count, + heap_size, module->memories[i].flags, error_buf, + error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } @@ -650,7 +679,7 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, if (function->import_module_inst) { function->import_func_inst = wasm_lookup_function(function->import_module_inst, - import->u.function.field_name, NULL); + import->u.function.field_name); } } #endif /* WASM_ENABLE_MULTI_MODULE */ @@ -1214,7 +1243,7 @@ lookup_post_instantiate_func(WASMModuleInstance *module_inst, WASMFunctionInstance *func; WASMFuncType *func_type; - if (!(func = wasm_lookup_function(module_inst, func_name, NULL))) + if (!(func = wasm_lookup_function(module_inst, func_name))) /* Not found */ return NULL; @@ -1934,13 +1963,15 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode) WASMModuleInstance * wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, - uint32 heap_size, char *error_buf, uint32 error_buf_size) + uint32 heap_size, uint32 max_memory_pages, char *error_buf, + uint32 error_buf_size) { WASMModuleInstance *module_inst; WASMGlobalInstance *globals = NULL, *global; WASMTableInstance *first_table; uint32 global_count, i; - uint32 base_offset, length, extra_info_offset; + uint32 length, extra_info_offset; + mem_offset_t base_offset; uint32 module_inst_struct_size = offsetof(WASMModuleInstance, global_table_data.bytes); uint64 module_inst_mem_inst_size; @@ -2022,7 +2053,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, &module_inst->e->sub_module_inst_list_head; ret = wasm_runtime_sub_module_instantiate( (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst, - stack_size, heap_size, error_buf, error_buf_size); + stack_size, heap_size, max_memory_pages, error_buf, error_buf_size); if (!ret) { LOG_DEBUG("build a sub module list failed"); goto fail; @@ -2131,9 +2162,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, /* Instantiate memories/tables/functions/tags */ if ((module_inst->memory_count > 0 - && !(module_inst->memories = - memories_instantiate(module, module_inst, parent, heap_size, - error_buf, error_buf_size))) + && !(module_inst->memories = memories_instantiate( + module, module_inst, parent, heap_size, max_memory_pages, + error_buf, error_buf_size))) || (module_inst->table_count > 0 && !(module_inst->tables = tables_instantiate(module, module_inst, first_table, @@ -2298,10 +2329,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, (uint64)memory->num_bytes_per_page * memory->cur_page_count; bh_assert(memory_data || memory_size == 0); - bh_assert(data_seg->base_offset.init_expr_type - == INIT_EXPR_TYPE_I32_CONST - || data_seg->base_offset.init_expr_type - == INIT_EXPR_TYPE_GET_GLOBAL); + bh_assert( + data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL + || (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST + && !memory->is_memory64) + || (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I64_CONST + && memory->is_memory64)); if (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { if (!check_global_init_expr(module, @@ -2312,23 +2345,48 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, if (!globals || globals[data_seg->base_offset.u.global_index].type - != VALUE_TYPE_I32) { + != (memory->is_memory64 ? VALUE_TYPE_I64 + : VALUE_TYPE_I32)) { set_error_buf(error_buf, error_buf_size, "data segment does not fit"); goto fail; } - base_offset = - globals[data_seg->base_offset.u.global_index].initial_value.i32; +#if WASM_ENABLE_MEMORY64 != 0 + if (memory->is_memory64) { + base_offset = + (uint64)globals[data_seg->base_offset.u.global_index] + .initial_value.i64; + } + else +#endif + { + base_offset = + (uint32)globals[data_seg->base_offset.u.global_index] + .initial_value.i32; + } } else { - base_offset = (uint32)data_seg->base_offset.u.i32; +#if WASM_ENABLE_MEMORY64 != 0 + if (memory->is_memory64) { + base_offset = (uint64)data_seg->base_offset.u.i64; + } + else +#endif + { + base_offset = (uint32)data_seg->base_offset.u.i32; + } } /* check offset */ if (base_offset > memory_size) { - LOG_DEBUG("base_offset(%d) > memory_size(%d)", base_offset, +#if WASM_ENABLE_MEMORY64 != 0 + LOG_DEBUG("base_offset(%" PRIu64 ") > memory_size(%" PRIu64 ")", + base_offset, memory_size); +#else + LOG_DEBUG("base_offset(%u) > memory_size(%" PRIu64 ")", base_offset, memory_size); +#endif #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 set_error_buf(error_buf, error_buf_size, "out of bounds memory access"); @@ -2342,8 +2400,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, /* check offset + length(could be zero) */ length = data_seg->data_length; if ((uint64)base_offset + length > memory_size) { - LOG_DEBUG("base_offset(%d) + length(%d) > memory_size(%d)", +#if WASM_ENABLE_MEMORY64 != 0 + LOG_DEBUG("base_offset(%" PRIu64 + ") + length(%d) > memory_size(%" PRIu64 ")", + base_offset, length, memory_size); +#else + LOG_DEBUG("base_offset(%u) + length(%d) > memory_size(%" PRIu64 ")", base_offset, length, memory_size); +#endif #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 set_error_buf(error_buf, error_buf_size, "out of bounds memory access"); @@ -2960,8 +3024,8 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) } #endif - if (module_inst->e->common.c_api_func_imports) - wasm_runtime_free(module_inst->e->common.c_api_func_imports); + if (module_inst->c_api_func_imports) + wasm_runtime_free(module_inst->c_api_func_imports); if (!is_sub_inst) { #if WASM_ENABLE_WASI_NN != 0 @@ -2981,14 +3045,12 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) } WASMFunctionInstance * -wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name, - const char *signature) +wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name) { uint32 i; for (i = 0; i < module_inst->export_func_count; i++) if (!strcmp(module_inst->export_functions[i].name, name)) return module_inst->export_functions[i].function; - (void)signature; return NULL; } @@ -3162,8 +3224,8 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, hw bound check is enabled */ #endif - /* Set exec env so it can be later retrieved from instance */ - module_inst->e->common.cur_exec_env = exec_env; + /* Set exec env, so it can be later retrieved from instance */ + module_inst->cur_exec_env = exec_env; interp_call_wasm(module_inst, exec_env, function, argc, argv); return !wasm_copy_exception(module_inst, NULL); @@ -3267,27 +3329,30 @@ wasm_get_wasm_func_exec_time(const WASMModuleInstance *inst, } #endif /*WASM_ENABLE_PERF_PROFILING != 0*/ -uint32 +uint64 wasm_module_malloc_internal(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, uint32 size, + WASMExecEnv *exec_env, uint64 size, void **p_native_addr) { WASMMemoryInstance *memory = wasm_get_default_memory(module_inst); uint8 *addr = NULL; uint32 offset = 0; + /* TODO: Memory64 size check based on memory idx type */ + bh_assert(size <= UINT32_MAX); + if (!memory) { wasm_set_exception(module_inst, "uninitialized memory"); return 0; } if (memory->heap_handle) { - addr = mem_allocator_malloc(memory->heap_handle, size); + addr = mem_allocator_malloc(memory->heap_handle, (uint32)size); } else if (module_inst->e->malloc_function && module_inst->e->free_function) { if (!execute_malloc_function( module_inst, exec_env, module_inst->e->malloc_function, - module_inst->e->retain_function, size, &offset)) { + module_inst->e->retain_function, (uint32)size, &offset)) { return 0; } /* If we use app's malloc function, @@ -3303,24 +3368,29 @@ wasm_module_malloc_internal(WASMModuleInstance *module_inst, wasm_set_exception(module_inst, "app heap corrupted"); } else { - LOG_WARNING("warning: allocate %u bytes memory failed", size); + LOG_WARNING("warning: allocate %" PRIu64 " bytes memory failed", + size); } return 0; } if (p_native_addr) *p_native_addr = addr; - return (uint32)(addr - memory->memory_data); + return (uint64)(addr - memory->memory_data); } -uint32 +uint64 wasm_module_realloc_internal(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, uint32 ptr, uint32 size, + WASMExecEnv *exec_env, uint64 ptr, uint64 size, void **p_native_addr) { WASMMemoryInstance *memory = wasm_get_default_memory(module_inst); uint8 *addr = NULL; + /* TODO: Memory64 ptr and size check based on memory idx type */ + bh_assert(ptr <= UINT32_MAX); + bh_assert(size <= UINT32_MAX); + if (!memory) { wasm_set_exception(module_inst, "uninitialized memory"); return 0; @@ -3328,7 +3398,9 @@ wasm_module_realloc_internal(WASMModuleInstance *module_inst, if (memory->heap_handle) { addr = mem_allocator_realloc( - memory->heap_handle, ptr ? memory->memory_data + ptr : NULL, size); + memory->heap_handle, + (uint32)ptr ? memory->memory_data + (uint32)ptr : NULL, + (uint32)size); } /* Only support realloc in WAMR's app heap */ @@ -3347,21 +3419,24 @@ wasm_module_realloc_internal(WASMModuleInstance *module_inst, if (p_native_addr) *p_native_addr = addr; - return (uint32)(addr - memory->memory_data); + return (uint64)(addr - memory->memory_data); } void wasm_module_free_internal(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, uint32 ptr) + WASMExecEnv *exec_env, uint64 ptr) { WASMMemoryInstance *memory = wasm_get_default_memory(module_inst); + /* TODO: Memory64 ptr and size check based on memory idx type */ + bh_assert(ptr <= UINT32_MAX); + if (!memory) { return; } if (ptr) { - uint8 *addr = memory->memory_data + ptr; + uint8 *addr = memory->memory_data + (uint32)ptr; uint8 *memory_data_end; /* memory->memory_data_end may be changed in memory grow */ @@ -3377,20 +3452,20 @@ wasm_module_free_internal(WASMModuleInstance *module_inst, && module_inst->e->free_function && memory->memory_data <= addr && addr < memory_data_end) { execute_free_function(module_inst, exec_env, - module_inst->e->free_function, ptr); + module_inst->e->free_function, (uint32)ptr); } } } -uint32 -wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size, +uint64 +wasm_module_malloc(WASMModuleInstance *module_inst, uint64 size, void **p_native_addr) { return wasm_module_malloc_internal(module_inst, NULL, size, p_native_addr); } -uint32 -wasm_module_realloc(WASMModuleInstance *module_inst, uint32 ptr, uint32 size, +uint64 +wasm_module_realloc(WASMModuleInstance *module_inst, uint64 ptr, uint64 size, void **p_native_addr) { return wasm_module_realloc_internal(module_inst, NULL, ptr, size, @@ -3398,22 +3473,27 @@ wasm_module_realloc(WASMModuleInstance *module_inst, uint32 ptr, uint32 size, } void -wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr) +wasm_module_free(WASMModuleInstance *module_inst, uint64 ptr) { wasm_module_free_internal(module_inst, NULL, ptr); } -uint32 +uint64 wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src, - uint32 size) + uint64 size) { char *buffer; - uint32 buffer_offset = - wasm_module_malloc(module_inst, size, (void **)&buffer); + uint64 buffer_offset; + + /* TODO: Memory64 size check based on memory idx type */ + bh_assert(size <= UINT32_MAX); + + buffer_offset = wasm_module_malloc(module_inst, size, (void **)&buffer); + if (buffer_offset != 0) { buffer = wasm_runtime_addr_app_to_native( (WASMModuleInstanceCommon *)module_inst, buffer_offset); - bh_memcpy_s(buffer, size, src, size); + bh_memcpy_s(buffer, (uint32)size, src, (uint32)size); } return buffer_offset; } @@ -3488,7 +3568,7 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 tbl_elem_idx, } #if WASM_ENABLE_GC == 0 - func_idx = tbl_elem_val; + func_idx = (uint32)tbl_elem_val; #else func_idx = wasm_func_obj_get_func_idx_bound((WASMFuncObjectRef)tbl_elem_val); @@ -3536,7 +3616,7 @@ wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, #if WASM_ENABLE_THREAD_MGR != 0 bool -wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) +wasm_set_aux_stack(WASMExecEnv *exec_env, uint64 start_offset, uint32 size) { WASMModuleInstance *module_inst = (WASMModuleInstance *)exec_env->module_inst; @@ -3544,8 +3624,8 @@ wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0 /* Check the aux stack space */ - uint32 data_end = module_inst->module->aux_data_end; - uint32 stack_bottom = module_inst->module->aux_stack_bottom; + uint64 data_end = module_inst->module->aux_data_end; + uint64 stack_bottom = module_inst->module->aux_stack_bottom; bool is_stack_before_data = stack_bottom < data_end ? true : false; if ((is_stack_before_data && (size > start_offset)) || ((!is_stack_before_data) && (start_offset - data_end < size))) @@ -3558,11 +3638,11 @@ wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) uint8 *global_addr = module_inst->global_data + module_inst->e->globals[stack_top_idx].data_offset; - *(int32 *)global_addr = start_offset; + *(int32 *)global_addr = (uint32)start_offset; /* The aux stack boundary is a constant value, set the value to exec_env */ - exec_env->aux_stack_boundary.boundary = start_offset - size; - exec_env->aux_stack_bottom.bottom = start_offset; + exec_env->aux_stack_boundary = (uintptr_t)start_offset - size; + exec_env->aux_stack_bottom = (uintptr_t)start_offset; return true; } @@ -3570,14 +3650,14 @@ wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) } bool -wasm_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size) +wasm_get_aux_stack(WASMExecEnv *exec_env, uint64 *start_offset, uint32 *size) { WASMModuleInstance *module_inst = (WASMModuleInstance *)exec_env->module_inst; /* The aux stack information is resolved in loader and store in module */ - uint32 stack_bottom = module_inst->module->aux_stack_bottom; + uint64 stack_bottom = module_inst->module->aux_stack_bottom; uint32 total_aux_stack_size = module_inst->module->aux_stack_size; if (stack_bottom != 0 && total_aux_stack_size != 0) { @@ -3671,7 +3751,8 @@ void wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst, WASMModuleInstMemConsumption *mem_conspn) { - uint32 i, size; + uint32 i; + uint64 size; memset(mem_conspn, 0, sizeof(*mem_conspn)); @@ -3951,7 +4032,7 @@ jit_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id) bool jit_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, - uint32 app_buf_addr, uint32 app_buf_size, + uint64 app_buf_addr, uint64 app_buf_size, void **p_native_addr) { bool ret = wasm_check_app_addr_and_convert( @@ -4025,9 +4106,8 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, import_func = &module->import_functions[func_idx].u.function; if (import_func->call_conv_wasm_c_api) { - if (module_inst->e->common.c_api_func_imports) { - c_api_func_import = - module_inst->e->common.c_api_func_imports + func_idx; + if (module_inst->c_api_func_imports) { + c_api_func_import = module_inst->c_api_func_imports + func_idx; func_ptr = c_api_func_import->func_ptr_linked; } else { @@ -4097,7 +4177,7 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index, } if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst, - dst, len)) + (uint64)dst, (uint64)len)) return false; if ((uint64)offset + (uint64)len > seg_len) { @@ -4106,10 +4186,11 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index, } maddr = wasm_runtime_addr_app_to_native( - (WASMModuleInstanceCommon *)module_inst, dst); + (WASMModuleInstanceCommon *)module_inst, (uint64)dst); SHARED_MEMORY_LOCK(memory_inst); - bh_memcpy_s(maddr, memory_inst->memory_data_size - dst, data + offset, len); + bh_memcpy_s(maddr, (uint32)(memory_inst->memory_data_size - dst), + data + offset, len); SHARED_MEMORY_UNLOCK(memory_inst); return true; } @@ -4377,3 +4458,154 @@ wasm_propagate_wasi_args(WASMModule *module) } } #endif + +bool +wasm_check_utf8_str(const uint8 *str, uint32 len) +{ + /* The valid ranges are taken from page 125, below link + https://www.unicode.org/versions/Unicode9.0.0/ch03.pdf */ + const uint8 *p = str, *p_end = str + len; + uint8 chr; + + while (p < p_end) { + chr = *p; + + if (chr == 0) { + LOG_WARNING( + "LIMITATION: a string which contains '\\00' is unsupported"); + return false; + } + else if (chr < 0x80) { + p++; + } + else if (chr >= 0xC2 && chr <= 0xDF && p + 1 < p_end) { + if (p[1] < 0x80 || p[1] > 0xBF) { + return false; + } + p += 2; + } + else if (chr >= 0xE0 && chr <= 0xEF && p + 2 < p_end) { + if (chr == 0xE0) { + if (p[1] < 0xA0 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { + return false; + } + } + else if (chr == 0xED) { + if (p[1] < 0x80 || p[1] > 0x9F || p[2] < 0x80 || p[2] > 0xBF) { + return false; + } + } + else { /* chr >= 0xE1 && chr <= 0xEF */ + if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { + return false; + } + } + p += 3; + } + else if (chr >= 0xF0 && chr <= 0xF4 && p + 3 < p_end) { + if (chr == 0xF0) { + if (p[1] < 0x90 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF + || p[3] < 0x80 || p[3] > 0xBF) { + return false; + } + } + else if (chr <= 0xF3) { /* and also chr >= 0xF1 */ + if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF + || p[3] < 0x80 || p[3] > 0xBF) { + return false; + } + } + else { /* chr == 0xF4 */ + if (p[1] < 0x80 || p[1] > 0x8F || p[2] < 0x80 || p[2] > 0xBF + || p[3] < 0x80 || p[3] > 0xBF) { + return false; + } + } + p += 4; + } + else { + return false; + } + } + return (p == p_end); +} + +char * +wasm_const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, + bool is_load_from_file_buf, char *error_buf, + uint32 error_buf_size) +{ + StringNode *node, *node_next; + + if (!wasm_check_utf8_str(str, len)) { + set_error_buf(error_buf, error_buf_size, "invalid UTF-8 encoding"); + return NULL; + } + + if (len == 0) { + return ""; + } + else if (is_load_from_file_buf) { + /* As the file buffer can be referred to after loading, we use + the previous byte of leb encoded size to adjust the string: + move string 1 byte backward and then append '\0' */ + char *c_str = (char *)str - 1; + bh_memmove_s(c_str, len + 1, c_str + 1, len); + c_str[len] = '\0'; + return c_str; + } + + /* Search const str list */ + node = module->const_str_list; + while (node) { + node_next = node->next; + if (strlen(node->str) == len && !memcmp(node->str, str, len)) + break; + node = node_next; + } + + if (node) { + return node->str; + } + + if (!(node = runtime_malloc(sizeof(StringNode) + len + 1, error_buf, + error_buf_size))) { + return NULL; + } + + node->str = ((char *)node) + sizeof(StringNode); + bh_memcpy_s(node->str, len + 1, str, len); + node->str[len] = '\0'; + + if (!module->const_str_list) { + /* set as head */ + module->const_str_list = node; + node->next = NULL; + } + else { + /* insert it */ + node->next = module->const_str_list; + module->const_str_list = node; + } + + return node->str; +} + +bool +wasm_set_module_name(WASMModule *module, const char *name, char *error_buf, + uint32_t error_buf_size) +{ + if (!name) + return false; + + module->name = + wasm_const_str_list_insert((const uint8 *)name, (uint32)strlen(name), + module, false, error_buf, error_buf_size); + return module->name != NULL; +} + +const char * +wasm_get_module_name(WASMModule *module) +{ + return module->name; +} diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index fb2beb1d44..db0b2b42d3 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -108,13 +108,17 @@ struct WASMMemoryInstance { /* Whether the memory is shared */ uint8 is_shared_memory; - /* One byte padding */ - uint8 __padding__; + /* Whether the memory has 64-bit memory addresses */ + uint8 is_memory64; /* Reference count of the memory instance: 0: non-shared memory, > 0: shared memory */ bh_atomic_16_t ref_count; + /* Four-byte paddings to ensure the layout of WASMMemoryInstance is the same + * in both 64-bit and 32-bit */ + uint8 __paddings[4]; + /* Number bytes per page */ uint32 num_bytes_per_page; /* Current page count */ @@ -122,7 +126,7 @@ struct WASMMemoryInstance { /* Maximum page count */ uint32 max_page_count; /* Memory data size */ - uint32 memory_data_size; + uint64 memory_data_size; /** * Memory data begin address, Note: * the app-heap might be inserted in to the linear memory, @@ -139,6 +143,8 @@ struct WASMMemoryInstance { DefPointer(uint8 *, heap_data_end); /* The heap created */ DefPointer(void *, heap_handle); + /* TODO: use it to replace the g_shared_memory_lock */ + DefPointer(korp_mutex *, memory_lock); #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ || WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_AOT != 0 @@ -180,7 +186,8 @@ struct WASMGlobalInstance { uint8 type; /* mutable or constant */ bool is_mutable; - /* data offset to base_addr of WASMMemoryInstance */ + /* data offset to the address of initial_value, started from the end of + * WASMMemoryInstance(start of WASMGlobalInstance)*/ uint32 data_offset; /* initial value */ WASMValue initial_value; @@ -297,10 +304,9 @@ typedef struct CApiFuncImport { /* The common part of WASMModuleInstanceExtra and AOTModuleInstanceExtra */ typedef struct WASMModuleInstanceExtraCommon { - CApiFuncImport *c_api_func_imports; +#if WASM_ENABLE_MODULE_INST_CONTEXT != 0 void *contexts[WASM_MAX_INSTANCE_CONTEXTS]; - /* pointer to the exec env currently used */ - WASMExecEnv *cur_exec_env; +#endif #if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0 /* Disable bounds checks or not */ bool disable_bounds_checks; @@ -406,8 +412,6 @@ struct WASMModuleInstance { it denotes `AOTModule *` */ DefPointer(WASMModule *, module); - DefPointer(void *, used_to_be_wasi_ctx); /* unused */ - DefPointer(WASMExecEnv *, exec_env_singleton); /* Array of function pointers to import functions, not available in AOTModuleInstance */ @@ -426,13 +430,16 @@ struct WASMModuleInstance { /* Function performance profiling info list, only available in AOTModuleInstance */ DefPointer(struct AOTFuncPerfProfInfo *, func_perf_profilings); + DefPointer(CApiFuncImport *, c_api_func_imports); + /* Pointer to the exec env currently used */ + DefPointer(WASMExecEnv *, cur_exec_env); /* WASM/AOT module extra info, for AOTModuleInstance, it denotes `AOTModuleInstanceExtra *` */ DefPointer(WASMModuleInstanceExtra *, e); /* Default WASM operand stack size */ uint32 default_wasm_stack_size; - uint32 reserved[3]; + uint32 reserved[7]; /* * +------------------------------+ <-- memories @@ -506,7 +513,7 @@ wasm_load(uint8 *buf, uint32 size, #if WASM_ENABLE_MULTI_MODULE != 0 bool main_module, #endif - char *error_buf, uint32 error_buf_size); + const LoadArgs *args, char *error_buf, uint32 error_buf_size); WASMModule * wasm_load_from_sections(WASMSection *section_list, char *error_buf, @@ -518,7 +525,8 @@ wasm_unload(WASMModule *module); WASMModuleInstance * wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, - uint32 heap_size, char *error_buf, uint32 error_buf_size); + uint32 heap_size, uint32 max_memory_pages, char *error_buf, + uint32 error_buf_size); void wasm_dump_perf_profiling(const WASMModuleInstance *module_inst); @@ -538,8 +546,7 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode); WASMFunctionInstance * -wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name, - const char *signature); +wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name); #if WASM_ENABLE_MULTI_MODULE != 0 WASMGlobalInstance * @@ -581,34 +588,34 @@ wasm_get_exception(WASMModuleInstance *module); bool wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf); -uint32 +uint64 wasm_module_malloc_internal(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, uint32 size, + WASMExecEnv *exec_env, uint64 size, void **p_native_addr); -uint32 +uint64 wasm_module_realloc_internal(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, uint32 ptr, uint32 size, + WASMExecEnv *exec_env, uint64 ptr, uint64 size, void **p_native_addr); void wasm_module_free_internal(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, uint32 ptr); + WASMExecEnv *exec_env, uint64 ptr); -uint32 -wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size, +uint64 +wasm_module_malloc(WASMModuleInstance *module_inst, uint64 size, void **p_native_addr); -uint32 -wasm_module_realloc(WASMModuleInstance *module_inst, uint32 ptr, uint32 size, +uint64 +wasm_module_realloc(WASMModuleInstance *module_inst, uint64 ptr, uint64 size, void **p_native_addr); void -wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr); +wasm_module_free(WASMModuleInstance *module_inst, uint64 ptr); -uint32 +uint64 wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src, - uint32 size); + uint64 size); /** * Check whether the app address and the buf is inside the linear memory, @@ -616,7 +623,7 @@ wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src, */ bool wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, - uint32 app_buf_addr, uint32 app_buf_size, + uint64 app_buf_addr, uint64 app_buf_size, void **p_native_addr); WASMMemoryInstance * @@ -631,10 +638,10 @@ wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, #if WASM_ENABLE_THREAD_MGR != 0 bool -wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size); +wasm_set_aux_stack(WASMExecEnv *exec_env, uint64 start_offset, uint32 size); bool -wasm_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size); +wasm_get_aux_stack(WASMExecEnv *exec_env, uint64 *start_offset, uint32 *size); #endif void @@ -731,7 +738,7 @@ jit_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id); */ bool jit_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, - uint32 app_buf_addr, uint32 app_buf_size, + uint64 app_buf_addr, uint64 app_buf_size, void **p_native_addr); #endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ || WASM_ENABLE_WAMR_COMPILER != 0 */ @@ -834,6 +841,21 @@ exception_unlock(WASMModuleInstance *module_inst); #define exception_unlock(module_inst) (void)(module_inst) #endif +bool +wasm_check_utf8_str(const uint8 *str, uint32 len); + +char * +wasm_const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, + bool is_load_from_file_buf, char *error_buf, + uint32 error_buf_size); + +bool +wasm_set_module_name(WASMModule *module, const char *name, char *error_buf, + uint32_t error_buf_size); + +const char * +wasm_get_module_name(WASMModule *module); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/libraries/ckpt-restore/wamr.cpp b/core/iwasm/libraries/ckpt-restore/wamr.cpp index 29183e2fc0..9b3be1d6e5 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr.cpp +++ b/core/iwasm/libraries/ckpt-restore/wamr.cpp @@ -213,7 +213,7 @@ WAMRInstance::~WAMRInstance() void WAMRInstance::find_func(const char *name) { - if (!(func = wasm_runtime_lookup_function(module_inst, name, nullptr))) { + if (!(func = wasm_runtime_lookup_function(module_inst, name))) { LOG_DEBUG("The wasi\"{}\"function is not found.", name); auto target_module = get_module_instance()->e; for (int i = 0; i < target_module->function_count; i++) { @@ -252,7 +252,7 @@ void WAMRInstance::invoke_init_c() { auto name1 = "__wasm_call_ctors"; - if (!(func = wasm_runtime_lookup_function(module_inst, name1, nullptr))) { + if (!(func = wasm_runtime_lookup_function(module_inst, name1))) { LOG_DEBUG("The wasi ", name1, " function is not found."); } else { @@ -1144,7 +1144,7 @@ serialize_to_file(WASMExecEnv *instance) } // finish filling vector #endif -#if __linux__ +#if defined(BH_PLATFORM_LINUX) if (dynamic_cast(writer)) { auto buffer = struct_pack::serialize(as); ((RDMAWriteStream *)writer)->buffer = buffer; diff --git a/core/iwasm/libraries/ckpt-restore/wamr.h b/core/iwasm/libraries/ckpt-restore/wamr.h index 2ea8b3a2c2..960f962bb8 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr.h +++ b/core/iwasm/libraries/ckpt-restore/wamr.h @@ -13,7 +13,6 @@ #ifndef MVVM_WAMR_H #define MVVM_WAMR_H - #include "wamr_exec_env.h" #include "wamr_wasi_arguments.h" #include "wasm_runtime.h" diff --git a/core/iwasm/libraries/ckpt-restore/wamr_branch_block.h b/core/iwasm/libraries/ckpt-restore/wamr_branch_block.h index 709757b7ed..8bde3be978 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_branch_block.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_branch_block.h @@ -27,10 +27,16 @@ struct WAMRBranchBlock { #if __has_include() && __cplusplus > 202002L template T> void -dump(T t, WASMBranchBlock *env); +dump(T t, WASMBranchBlock *env) +{ + t->dump_impl(env); +}; template T> void -restore(T t, WASMBranchBlock *env); +restore(T t, WASMBranchBlock *env) +{ + t->restore_impl(env); +}; #else void dump(WAMRBranchBlock *t, WASMBranchBlock *env); diff --git a/core/iwasm/libraries/ckpt-restore/wamr_exec_env.cpp b/core/iwasm/libraries/ckpt-restore/wamr_exec_env.cpp index 7f5e2c6f94..787da2d87d 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_exec_env.cpp +++ b/core/iwasm/libraries/ckpt-restore/wamr_exec_env.cpp @@ -22,8 +22,8 @@ WAMRExecEnv::dump_impl(WASMExecEnv *env) dump(&this->module_inst, reinterpret_cast(env->module_inst)); flags = env->suspend_flags.flags; - aux_boundary = env->aux_stack_boundary.boundary; - aux_bottom = env->aux_stack_bottom.bottom; + aux_boundary = env->aux_stack_boundary; + aux_bottom = env->aux_stack_bottom; auto cur_frame = env->cur_frame; while (cur_frame) { auto dumped_frame = new WAMRInterpFrame(); @@ -41,8 +41,8 @@ void WAMRExecEnv::restore_impl(WASMExecEnv *env) { env->suspend_flags.flags = flags; - env->aux_stack_boundary.boundary = aux_boundary; - env->aux_stack_bottom.bottom = aux_bottom; + env->aux_stack_boundary = aux_boundary; + env->aux_stack_bottom = aux_bottom; restore(&this->module_inst, reinterpret_cast(env->module_inst)); diff --git a/core/iwasm/libraries/ckpt-restore/wamr_exec_env.h b/core/iwasm/libraries/ckpt-restore/wamr_exec_env.h index df6f1cd41a..bcc983a244 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_exec_env.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_exec_env.h @@ -24,12 +24,12 @@ struct WAMRExecEnv { // multiple WAMRModuleInstance module_inst{}; /* The thread id of wasm interpreter for current thread. */ uint64 cur_count{}; - uint32 flags; + uint32 flags{}; /* Auxiliary stack boundary */ - uint32 aux_boundary; + uint32 aux_boundary{}; /* Auxiliary stack bottom */ - uint32 aux_bottom; + uint32 aux_bottom{}; /* Auxiliary stack top */ std::vector> frames; @@ -39,10 +39,16 @@ struct WAMRExecEnv { // multiple #if __has_include() && __cplusplus > 202002L template T> void -dump(T t, WASMExecEnv *env); +dump(T t, WASMExecEnv *env) +{ + t->dump_impl(env); +} template T> void -restore(T t, WASMExecEnv *env); +restore(T t, WASMExecEnv *env) +{ + t->restore_impl(env); +}; #else void dump(WAMRExecEnv *t, WASMExecEnv *env); diff --git a/core/iwasm/libraries/ckpt-restore/wamr_export.cpp b/core/iwasm/libraries/ckpt-restore/wamr_export.cpp index a833165c83..2dc500a6c9 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_export.cpp +++ b/core/iwasm/libraries/ckpt-restore/wamr_export.cpp @@ -169,8 +169,7 @@ replay_sock_recv_from_data(uint32_t sock, uint8 **ri_data, wamr->socket_fd_map_[sock] .socketRecvFromDatas[wamr->socket_fd_map_[sock].replay_start_index]; wamr->socket_fd_map_[sock].replay_start_index++; - std::memcpy(*ri_data, recvFromData.ri_data.data(), - recvFromData.ri_data.size()); + memcpy(*ri_data, recvFromData.ri_data.data(), recvFromData.ri_data.size()); *recv_size = recvFromData.ri_data.size(); if (src_addr->kind == IPv4) { src_addr->addr.ip4.addr.n0 = recvFromData.src_addr.ip.ip4[0]; @@ -361,7 +360,7 @@ init_gateway(SocketAddrPool *address) ssize_t rc; wamr->op_data.op = MVVM_SOCK_INIT; wamr->op_data.addr[0][0] = wamr->local_addr; - std::memcpy(&wamr->op_data.addr[0][1], address, sizeof(SocketAddrPool)); + memcpy(&wamr->op_data.addr[0][1], address, sizeof(SocketAddrPool)); // Create a socket if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { diff --git a/core/iwasm/libraries/ckpt-restore/wamr_interp_frame.h b/core/iwasm/libraries/ckpt-restore/wamr_interp_frame.h index 9145f88121..03b2c3866b 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_interp_frame.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_interp_frame.h @@ -46,17 +46,29 @@ struct WAMRInterpFrame { #if __has_include() && __cplusplus > 202002L template T> void -dump(T t, WASMInterpFrame *env); +dump(T t, WASMInterpFrame *env) +{ + t->dump_impl(env); +}; template T> void -restore(T t, WASMInterpFrame *env); +restore(T t, WASMInterpFrame *env) +{ + t->dump_impl(env); +}; template T> void -dump(T t, AOTFrame *env); +dump(T t, AOTFrame *env) +{ + t->dump_impl(env); +}; template T> void -restore(T t, AOTFrame *env); +restore(T t, AOTFrame *env) +{ + t->dump_impl(env); +}; #else void dump(WAMRInterpFrame *t, WASMInterpFrame *env); diff --git a/core/iwasm/libraries/ckpt-restore/wamr_memory_instance.h b/core/iwasm/libraries/ckpt-restore/wamr_memory_instance.h index 6734c001de..ba77b28f36 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_memory_instance.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_memory_instance.h @@ -59,10 +59,16 @@ struct WAMRMemoryInstance { #if __has_include() && __cplusplus > 202002L template T> void -dump(T t, WASMMemoryInstance *env); +dump(T t, WASMMemoryInstance *env) +{ + t->dump_impl(env); +}; template T> void -restore(T t, WASMMemoryInstance *env); +restore(T t, WASMMemoryInstance *env) +{ + t->restore_impl(env); +}; #else void dump(WAMRMemoryInstance *t, WASMMemoryInstance *env); diff --git a/core/iwasm/libraries/ckpt-restore/wamr_module_instance.cpp b/core/iwasm/libraries/ckpt-restore/wamr_module_instance.cpp index bd350d6864..0aac0d9741 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_module_instance.cpp +++ b/core/iwasm/libraries/ckpt-restore/wamr_module_instance.cpp @@ -78,13 +78,11 @@ WAMRModuleInstance::restore_impl(WASMModuleInstance *env) env->global_data_size = global_data.size(); memcpy(env->global_data, global_data.data(), global_data.size()); for (int i = 0; i < env->table_count; i++) { - env->tables[i] = new WASMTableInstance - { - .elem_type = tables[i].elem_type, - .cur_size = tables[i].cur_size, - .max_size = tables[i].max_size, - .elems = { tables[i].elems[0] } - }; + env->tables[i] = + new WASMTableInstance{ .elem_type = tables[i].elem_type, + .cur_size = tables[i].cur_size, + .max_size = tables[i].max_size, + .elems = { tables[i].elems[0] } }; } env->table_count = tables.size(); } @@ -94,8 +92,7 @@ WAMRModuleInstance::restore_impl(WASMModuleInstance *env) memcpy(env->global_data, global_data.data(), global_data.size()); env->global_data_size = global_data.size(); for (int i = 0; i < env->table_count; i++) { - env->tables[i] = new WASMTableInstance - { + env->tables[i] = new WASMTableInstance{ .elem_type = (*env->tables[i]).elem_type, .cur_size = (*env->tables[i]).cur_size, .max_size = (*env->tables[i]).max_size, diff --git a/core/iwasm/libraries/ckpt-restore/wamr_module_instance.h b/core/iwasm/libraries/ckpt-restore/wamr_module_instance.h index ecae9f7408..9c44a002b5 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_module_instance.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_module_instance.h @@ -65,10 +65,16 @@ struct WAMRModuleInstance { #if __has_include() && __cplusplus > 202002L template T> void -dump(T t, WASMModuleInstance *env); +dump(T t, WASMModuleInstance *env) +{ + t->dump_impl(env); +}; template T> void -restore(T t, WASMModuleInstance *env); +restore(T t, WASMModuleInstance *env) +{ + t->restore_impl(env); +}; #else void dump(WAMRModuleInstance *t, WASMModuleInstance *env); diff --git a/core/iwasm/libraries/ckpt-restore/wamr_module_instance_extra.h b/core/iwasm/libraries/ckpt-restore/wamr_module_instance_extra.h index 267fff5a5d..2516e32eae 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_module_instance_extra.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_module_instance_extra.h @@ -92,7 +92,10 @@ dump(T t, WASMModuleInstanceExtra *env) template T> void -restore(T t, WASMModuleInstanceExtra *env); +restore(T t, WASMModuleInstanceExtra *env) +{ + t->restore_impl(env); +} #else void dump(WAMRModuleInstanceExtra *t, WASMModuleInstanceExtra *env); diff --git a/core/iwasm/libraries/ckpt-restore/wamr_read_write.h b/core/iwasm/libraries/ckpt-restore/wamr_read_write.h index 0c96201313..fc2a55f1ee 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_read_write.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_read_write.h @@ -73,9 +73,9 @@ struct FreadStream : public ReadStream { ~FreadStream() override { fclose(file); } }; // static_assert(ReaderStreamTrait, - // "Reader must conform to ReaderStreamTrait"); +// "Reader must conform to ReaderStreamTrait"); // static_assert(WriterStreamTrait, - // "Writer must conform to WriterStreamTrait"); +// "Writer must conform to WriterStreamTrait"); #ifndef BH_PLATFORM_WINDOWS struct SocketWriteStream : public WriteStream { int sock_fd; @@ -194,12 +194,12 @@ struct SocketReadStream : public ReadStream { ~SocketReadStream() override { close(sock_fd); } }; // static_assert(ReaderStreamTrait, - // "Reader must conform to ReaderStreamTrait"); +// "Reader must conform to ReaderStreamTrait"); // static_assert(WriterStreamTrait, - // "Writer must conform to WriterStreamTrait"); +// "Writer must conform to WriterStreamTrait"); #endif -#if __linux__ +#if defined(BH_PLATFORM_LINUX) #include #include struct __attribute((packed)) rdma_buffer_attr { @@ -1102,9 +1102,9 @@ class RDMAWriteStream }; }; // static_assert(ReaderStreamTrait, - // "Reader must conform to ReaderStreamTrait"); +// "Reader must conform to ReaderStreamTrait"); // static_assert(WriterStreamTrait, - // "Writer must conform to WriterStreamTrait"); +// "Writer must conform to WriterStreamTrait"); #endif #endif /* MVVM_WAMR_READ_WRITE_H */ diff --git a/core/iwasm/libraries/ckpt-restore/wamr_serializer.h b/core/iwasm/libraries/ckpt-restore/wamr_serializer.h index feb9396971..c0956051c9 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_serializer.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_serializer.h @@ -16,32 +16,52 @@ #if __has_include() && __cplusplus > 202002L #include -template +template concept SerializerTrait = requires(T &t, K k) { - { t->dump_impl(k) } -> std::same_as; - { t->restore_impl(k) } -> std::same_as; + { + t->dump_impl(k) + } -> std::same_as; + { + t->restore_impl(k) + } -> std::same_as; }; -template +template concept CheckerTrait = requires(T &t, K k) { - { t->dump_impl(k) } -> std::same_as; - { t->equal_impl(k) } -> std::convertible_to; + { + t->dump_impl(k) + } -> std::same_as; + { + t->equal_impl(k) + } -> std::convertible_to; }; -template -concept WriterStreamTrait = requires(T &t, const WriteDataType *data, std::size_t size) { - // Requires a write method that accepts WriteDataType and returns void or a boolean. - { t.write(data, size) } -> std::same_as; -}; +template +concept WriterStreamTrait = + requires(T &t, const WriteDataType *data, std::size_t size) { + // Requires a write method that accepts WriteDataType and returns void + // or a boolean. + { + t.write(data, size) + } -> std::same_as; + }; -template -concept ReaderStreamTrait = requires(T &t, ReadDataType *data, std::size_t size) { - // Requires a read method that accepts a pointer to ReadDataType and size, returns bool. - { t.read(data, size) } -> std::same_as; - // Requires an ignore method that accepts size and returns bool. - { t.ignore(size) } -> std::same_as; - // Requires a tellg method that returns std::size_t. - { t.tellg() } -> std::same_as; -}; +template +concept ReaderStreamTrait = + requires(T &t, ReadDataType *data, std::size_t size) { + // Requires a read method that accepts a pointer to ReadDataType and + // size, returns bool. + { + t.read(data, size) + } -> std::same_as; + // Requires an ignore method that accepts size and returns bool. + { + t.ignore(size) + } -> std::same_as; + // Requires a tellg method that returns std::size_t. + { + t.tellg() + } -> std::same_as; + }; #endif #endif // MVVM_WAMR_SERIALIZER_H diff --git a/core/iwasm/libraries/ckpt-restore/wamr_type.h b/core/iwasm/libraries/ckpt-restore/wamr_type.h index 87bc03049b..c7ee72009c 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_type.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_type.h @@ -42,10 +42,16 @@ struct WAMRType { #if __has_include() && __cplusplus > 202002L template T> void -dump(T t, WASMType *env); +dump(T t, WASMType *env) +{ + t->dump_impl(env); +} template T> bool -equal(T t, WASMType *env); +equal(T t, WASMType *env) +{ + t->equal_impl(env); +} #else void dump(WAMRType *t, WASMType *env) diff --git a/core/iwasm/libraries/ckpt-restore/wamr_wasi_arguments.h b/core/iwasm/libraries/ckpt-restore/wamr_wasi_arguments.h index 2ad1d3535d..3fcadb33ff 100644 --- a/core/iwasm/libraries/ckpt-restore/wamr_wasi_arguments.h +++ b/core/iwasm/libraries/ckpt-restore/wamr_wasi_arguments.h @@ -91,10 +91,16 @@ struct WAMRWASIArguments { #if __has_include() && __cplusplus > 202002L template T> void -dump(T t, WASIArguments *env); +dump(T t, WASIArguments *env) +{ + t->dump_impl(env); +} template T> void -restore(T t, WASIArguments *env); +restore(T t, WASIArguments *env) +{ + t->restore_impl(env); +}; #else void dump(WAMRWASIArguments *t, WASIArguments *env); diff --git a/core/iwasm/libraries/ckpt-restore/wamr_wasi_context.h b/core/iwasm/libraries/ckpt-restore/wamr_wasi_context.h deleted file mode 100644 index 31f311b47b..0000000000 --- a/core/iwasm/libraries/ckpt-restore/wamr_wasi_context.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * The WebAssembly Live Migration Project - * - * By: Aibo Hu - * Yiwei Yang - * Brian Zhao - * Andrew Quinn - * - * Copyright 2024 Regents of the Univeristy of California - * UC Santa Cruz Sluglab. - */ - -#ifndef MVVM_WAMR_WASI_CONTEXT_H -#define MVVM_WAMR_WASI_CONTEXT_H - -#include "ckpt_restore.h" -#include "wamr_serializer.h" -#include "wasm_runtime.h" -#include -#include -#include -#include -#include -#include -#include -#include - -struct WAMRAddrPool { - uint8 ip4[4]; - uint16 ip6[8]; - bool is_4; - uint8 mask; -}; -struct WAMRWasiAddr { - WAMRAddrPool ip; - uint16 port; -}; -struct WasiSockOpenData { - uint32 poolfd; - int af; - int socktype; - uint32 sockfd; -}; -struct WasiSockSendToData { - uint32 sock; - std::vector si_data; - uint16_t si_flags; - WAMRWasiAddr dest_addr; - uint32 so_data_len; -}; - -struct WasiSockRecvFromData { - uint32_t sock; - std::vector ri_data; - uint16_t ri_flags; - WAMRWasiAddr src_addr; - uint32 ro_data_len; -}; -struct SocketMetaData { - int domain{}; - int type{}; - int protocol{}; - SocketAddrPool socketAddress{}; - WasiSockOpenData socketOpenData{}; - int replay_start_index{}; - bool is_server = false; - bool is_collection = false; - WasiSockSendToData socketSentToData{}; // - std::vector socketRecvFromDatas; -}; -struct WAMRWASIArguments { - std::map>>> - fd_map; - std::map socket_fd_map; - std::vector sync_ops; - std::vector dir; - std::vector map_dir; - std::vector arg; - std::vector argv_list; - std::vector env_list; - std::vector addr_pool; - std::vector ns_lookup_list; - std::map> tid_start_arg_map; - std::map child_tid_map; - uint32_t exit_code; - - void dump_impl(WASIArguments *env); - void restore_impl(WASIArguments *env); -}; -#if __has_include() && __cplusplus > 202002L -template T> -void -dump(T t, WASIArguments *env); -template T> -void -restore(T t, WASIArguments *env); -#else -void -dump(WAMRWASIArguments *t, WASMWASIArguments *env); -void -restore(WAMRWASIArguments *t, WASMWASIArguments *env); -#endif -#endif // MVVM_WAMR_WASI_CONTEXT_H diff --git a/core/iwasm/libraries/ckpt-restore/ylt/struct_pack/util.h b/core/iwasm/libraries/ckpt-restore/ylt/struct_pack/util.h index 730d292580..d2837cd4c3 100644 --- a/core/iwasm/libraries/ckpt-restore/ylt/struct_pack/util.h +++ b/core/iwasm/libraries/ckpt-restore/ylt/struct_pack/util.h @@ -25,99 +25,113 @@ namespace struct_pack::detail { -template -constexpr std::string_view get_raw_name() { +template +constexpr std::string_view +get_raw_name() +{ #ifdef _MSC_VER - return __FUNCSIG__; + return __FUNCSIG__; #else - return __PRETTY_FUNCTION__; + return __PRETTY_FUNCTION__; #endif } -template -constexpr std::string_view get_raw_name() { +template +constexpr std::string_view +get_raw_name() +{ #ifdef _MSC_VER - return __FUNCSIG__; + return __FUNCSIG__; #else - return __PRETTY_FUNCTION__; + return __PRETTY_FUNCTION__; #endif } -template -inline constexpr std::string_view type_string() { - constexpr std::string_view sample = get_raw_name(); - constexpr size_t pos = sample.find("int"); - constexpr std::string_view str = get_raw_name(); - constexpr auto next1 = str.rfind(sample[pos + 3]); +template +inline constexpr std::string_view +type_string() +{ + constexpr std::string_view sample = get_raw_name(); + constexpr size_t pos = sample.find("int"); + constexpr std::string_view str = get_raw_name(); + constexpr auto next1 = str.rfind(sample[pos + 3]); #if defined(_MSC_VER) - constexpr std::size_t npos = str.find_first_of(" ", pos); - if (npos != std::string_view::npos) - return str.substr(npos + 1, next1 - npos - 1); - else - return str.substr(pos, next1 - pos); + constexpr std::size_t npos = str.find_first_of(" ", pos); + if (npos != std::string_view::npos) + return str.substr(npos + 1, next1 - npos - 1); + else + return str.substr(pos, next1 - pos); #else - return str.substr(pos, next1 - pos); + return str.substr(pos, next1 - pos); #endif } constexpr bool is_string_reserve_shrink = true; -template +template using remove_cvref_t = std::remove_cv_t>; -[[noreturn]] inline void unreachable() { - // Uses compiler specific extensions if possible. - // Even if no extension is used, undefined behavior is still raised by - // an empty function body and the noreturn attribute. -#ifdef __GNUC__ // GCC, Clang, ICC - __builtin_unreachable(); -#elif defined(_MSC_VER) // msvc - __assume(false); +[[noreturn]] inline void +unreachable() +{ + // Uses compiler specific extensions if possible. + // Even if no extension is used, undefined behavior is still raised by + // an empty function body and the noreturn attribute. +#ifdef __GNUC__ // GCC, Clang, ICC + __builtin_unreachable(); +#elif defined(_MSC_VER) // msvc + __assume(false); #endif } -template -[[noreturn]] constexpr T declval() { - unreachable(); +template +[[noreturn]] constexpr T +declval() +{ + unreachable(); } -template -constexpr void STRUCT_PACK_INLINE compile_time_sort(std::array &array) { - // FIXME: use faster compile-time sort - for (std::size_t i = 0; i < array.size(); ++i) { - for (std::size_t j = i + 1; j < array.size(); ++j) { - if (array[i] > array[j]) { - auto tmp = array[i]; - array[i] = array[j]; - array[j] = tmp; - } +template +constexpr void STRUCT_PACK_INLINE +compile_time_sort(std::array &array) +{ + // FIXME: use faster compile-time sort + for (std::size_t i = 0; i < array.size(); ++i) { + for (std::size_t j = i + 1; j < array.size(); ++j) { + if (array[i] > array[j]) { + auto tmp = array[i]; + array[i] = array[j]; + array[j] = tmp; + } + } } - } - return; + return; } -template +template constexpr std::size_t STRUCT_PACK_INLINE -calculate_uniqued_size(const std::array &input) { - std::size_t unique_cnt = sz; - for (std::size_t i = 1; i < input.size(); ++i) { - if (input[i] == input[i - 1]) { - --unique_cnt; +calculate_uniqued_size(const std::array &input) +{ + std::size_t unique_cnt = sz; + for (std::size_t i = 1; i < input.size(); ++i) { + if (input[i] == input[i - 1]) { + --unique_cnt; + } } - } - return unique_cnt; + return unique_cnt; } -template -constexpr void STRUCT_PACK_INLINE compile_time_unique( - const std::array &input, std::array &output) { - std::size_t j = 0; - static_assert(sz1 != 0, "not allow empty input!"); - output[0] = input[0]; - for (std::size_t i = 1; i < input.size(); ++i) { - if (input[i] != input[i - 1]) { - output[++j] = input[i]; +template +constexpr void STRUCT_PACK_INLINE +compile_time_unique(const std::array &input, std::array &output) +{ + std::size_t j = 0; + static_assert(sz1 != 0, "not allow empty input!"); + output[0] = input[0]; + for (std::size_t i = 1; i < input.size(); ++i) { + if (input[i] != input[i - 1]) { + output[++j] = input[i]; + } } - } } #ifndef __clang__ @@ -127,40 +141,42 @@ constexpr void STRUCT_PACK_INLINE compile_time_unique( #endif #if __cpp_lib_string_resize_and_overwrite >= 202110L -template -inline void resize(std::basic_string &str, std::size_t sz) { - str.resize_and_overwrite(sz, [sz](ch *, std::size_t) { - return sz; - }); +template +inline void +resize(std::basic_string &str, std::size_t sz) +{ + str.resize_and_overwrite(sz, [sz](ch *, std::size_t) { return sz; }); } #elif (defined(_MSC_VER) && _MSC_VER <= 1920) // old msvc don't support visit private, discard it. #else -template -class string_thief { - public: - friend void string_set_length_hacker(std::string &self, std::size_t sz) { +template +class string_thief +{ + public: + friend void string_set_length_hacker(std::string &self, std::size_t sz) + { #if defined(_MSVC_STL_VERSION) - (self.*func_ptr)._Myval2._Mysize = sz; + (self.*func_ptr)._Myval2._Mysize = sz; #else #if defined(_LIBCPP_VERSION) - (self.*func_ptr)(sz); + (self.*func_ptr)(sz); #else #if (_GLIBCXX_USE_CXX11_ABI == 0) && defined(__GLIBCXX__) - (self.*func_ptr)()->_M_set_length_and_sharable(sz); + (self.*func_ptr)()->_M_set_length_and_sharable(sz); #else #if defined(__GLIBCXX__) - (self.*func_ptr)(sz); + (self.*func_ptr)(sz); #endif #endif #endif #endif - } + } }; -#if defined(__GLIBCXX__) // libstdc++ +#if defined(__GLIBCXX__) // libstdc++ #if (_GLIBCXX_USE_CXX11_ABI == 0) template class string_thief; @@ -176,75 +192,81 @@ template class string_thief; #endif -void string_set_length_hacker(std::string &, std::size_t); +void +string_set_length_hacker(std::string &, std::size_t); -template -inline void resize(std::basic_string &raw_str, std::size_t sz) { +template +inline void +resize(std::basic_string &raw_str, std::size_t sz) +{ #if defined(_GLIBCXX_USE_CXX11_ABI) - constexpr bool is_use_cxx11_abi = _GLIBCXX_USE_CXX11_ABI; + constexpr bool is_use_cxx11_abi = _GLIBCXX_USE_CXX11_ABI; #else - constexpr bool is_use_cxx11_abi = true; + constexpr bool is_use_cxx11_abi = true; #endif - if constexpr (std::is_same_v == false && - is_use_cxx11_abi == false) { - raw_str.resize(sz); - } - else { -#if defined(__SANITIZE_ADDRESS__) || \ - struct_pack_has_feature(address_sanitizer) || \ - (!defined(NDEBUG) && defined(_MSVC_STL_VERSION)) - raw_str.resize(sz); -#elif defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) || \ - defined(_MSVC_STL_VERSION) - if constexpr (is_string_reserve_shrink) { - if (sz > raw_str.capacity()) { - raw_str.reserve(sz); - } + if constexpr (std::is_same_v == false + && is_use_cxx11_abi == false) { + raw_str.resize(sz); } else { - raw_str.reserve(sz); - } - std::string &str = *reinterpret_cast(&raw_str); - string_set_length_hacker(str, sz); - *(raw_str.data() + sz) = 0; +#if defined(__SANITIZE_ADDRESS__) \ + || struct_pack_has_feature(address_sanitizer) \ + || (!defined(NDEBUG) && defined(_MSVC_STL_VERSION)) + raw_str.resize(sz); +#elif defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) \ + || defined(_MSVC_STL_VERSION) + if constexpr (is_string_reserve_shrink) { + if (sz > raw_str.capacity()) { + raw_str.reserve(sz); + } + } + else { + raw_str.reserve(sz); + } + std::string &str = *reinterpret_cast(&raw_str); + string_set_length_hacker(str, sz); + *(raw_str.data() + sz) = 0; #else - raw_str.resize(sz); + raw_str.resize(sz); #endif - } + } } #endif #if (defined(_MSC_VER) && _MSC_VER <= 1920) #else -void vector_set_length_hacker(std::vector &self, std::size_t sz); +void +vector_set_length_hacker(std::vector &self, std::size_t sz); -template -class vector_thief { - public: - friend void vector_set_length_hacker(std::vector &self, - std::size_t sz) { +template +class vector_thief +{ + public: + friend void vector_set_length_hacker(std::vector &self, + std::size_t sz) + { #if defined(_MSVC_STL_VERSION) - (self.*func_ptr)._Myval2._Mylast = self.data() + sz; + (self.*func_ptr)._Myval2._Mylast = self.data() + sz; #else #if defined(_LIBCPP_VERSION) #if _LIBCPP_VERSION < 14000 - ((*(std::__vector_base> *)(&self)).*func_ptr) = - self.data() + sz; + ((*(std::__vector_base> *)(&self)) + .*func_ptr) = self.data() + sz; #else - (self.*func_ptr) = self.data() + sz; + (self.*func_ptr) = self.data() + sz; #endif #else #if defined(__GLIBCXX__) - ((*(std::_Vector_base> *)(&self)).*func_ptr) - ._M_finish = self.data() + sz; + ((*(std::_Vector_base> *)(&self)).*func_ptr) + ._M_finish = self.data() + sz; #endif #endif #endif - } + } }; -#if defined(__GLIBCXX__) // libstdc++ +#if defined(__GLIBCXX__) // libstdc++ template class vector_thief::_M_impl), &std::vector::_M_impl>; #elif defined(_LIBCPP_VERSION) @@ -255,27 +277,31 @@ template class vector_thief::_Mypair), &std::vector::_Mypair>; #endif -template -inline void resize(std::vector &raw_vec, std::size_t sz) { +template +inline void +resize(std::vector &raw_vec, std::size_t sz) +{ #if defined(__SANITIZE_ADDRESS__) || struct_pack_has_feature(address_sanitizer) - raw_vec.resize(sz); -#elif defined(__GLIBCXX__) || \ - (defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_ASAN)) || \ - defined(_MSVC_STL_VERSION) - std::vector &vec = *reinterpret_cast *>(&raw_vec); - vec.reserve(sz * sizeof(ch)); - vector_set_length_hacker(vec, sz * sizeof(ch)); + raw_vec.resize(sz); +#elif defined(__GLIBCXX__) \ + || (defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_ASAN)) \ + || defined(_MSVC_STL_VERSION) + std::vector &vec = *reinterpret_cast *>(&raw_vec); + vec.reserve(sz * sizeof(ch)); + vector_set_length_hacker(vec, sz * sizeof(ch)); #else - raw_vec.resize(sz); + raw_vec.resize(sz); #endif } #endif #undef struct_pack_has_feature -template -inline void resize(T &str, std::size_t sz) { - str.resize(sz); +template +inline void +resize(T &str, std::size_t sz) +{ + str.resize(sz); } -} // namespace struct_pack::detail \ No newline at end of file +} // namespace struct_pack::detail \ No newline at end of file diff --git a/core/iwasm/libraries/debug-engine/debug_engine.c b/core/iwasm/libraries/debug-engine/debug_engine.c index 1b3db1d496..0ffc78ad92 100644 --- a/core/iwasm/libraries/debug-engine/debug_engine.c +++ b/core/iwasm/libraries/debug-engine/debug_engine.c @@ -409,7 +409,7 @@ wasm_debug_instance_create(WASMCluster *cluster, int32 port) * expressions */ instance->exec_mem_info.size = DEBUG_EXECUTION_MEMORY_SIZE; instance->exec_mem_info.start_offset = wasm_runtime_module_malloc( - module_inst, instance->exec_mem_info.size, NULL); + module_inst, (uint64)instance->exec_mem_info.size, NULL); if (instance->exec_mem_info.start_offset == 0) { LOG_WARNING( "WASM Debug Engine warning: failed to allocate linear memory for " @@ -1393,7 +1393,7 @@ wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size, return 0; } - if ((uint64)instance->exec_mem_info.current_pos + if (instance->exec_mem_info.current_pos - instance->exec_mem_info.start_offset + size <= (uint64)instance->exec_mem_info.size) { offset = instance->exec_mem_info.current_pos; diff --git a/core/iwasm/libraries/debug-engine/debug_engine.h b/core/iwasm/libraries/debug-engine/debug_engine.h index e12f827bde..68738213ef 100644 --- a/core/iwasm/libraries/debug-engine/debug_engine.h +++ b/core/iwasm/libraries/debug-engine/debug_engine.h @@ -53,9 +53,9 @@ typedef enum debug_state_t { } debug_state_t; typedef struct WASMDebugExecutionMemory { - uint32 start_offset; + uint64 start_offset; + uint64 current_pos; uint32 size; - uint32 current_pos; } WASMDebugExecutionMemory; struct WASMDebugInstance { diff --git a/core/iwasm/libraries/debug-engine/handler.c b/core/iwasm/libraries/debug-engine/handler.c index 8d451b1a35..905ca2f7c2 100644 --- a/core/iwasm/libraries/debug-engine/handler.c +++ b/core/iwasm/libraries/debug-engine/handler.c @@ -309,9 +309,11 @@ handle_general_query(WASMGDBServer *server, char *payload) } if (!strcmp(name, "WasmData")) { + write_packet(server, ""); } if (!strcmp(name, "WasmMem")) { + write_packet(server, ""); } if (!strcmp(name, "Symbol")) { @@ -447,7 +449,7 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid) "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc, pc_string, "trace"); } - else if (status > 0) { + else { /* status > 0 (== 0 is checked at the function beginning) */ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc, pc_string, "signal"); diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index e1e0cd12e9..0c412904e5 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -566,7 +566,8 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, ThreadRoutineArgs *routine_args = NULL; uint32 thread_handle; uint32 stack_size = 8192; - uint32 aux_stack_start = 0, aux_stack_size; + uint32 aux_stack_size; + uint64 aux_stack_start = 0; int32 ret = -1; bh_assert(module); @@ -586,10 +587,9 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, } #endif - new_module_inst = wasm_exec_env_get_module_inst(exec_env); - // if (!(new_module_inst = wasm_runtime_instantiate_internal( - // module, module_inst, exec_env, stack_size, 0, NULL, 0))) - // return -1; + if (!(new_module_inst = wasm_runtime_instantiate_internal( + module, module_inst, exec_env, stack_size, 0, 0, NULL, 0))) + return -1; // /* Set custom_data to new module instance */ // wasm_runtime_set_custom_data_internal( @@ -681,14 +681,14 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread, /* validate addr, we can use current thread's module instance here as the memory is shared */ - if (!validate_app_addr(retval_offset, sizeof(int32))) { + if (!validate_app_addr((uint64)retval_offset, (uint64)sizeof(int32))) { /* Join failed, but we don't want to terminate all threads, do not spread exception here */ wasm_runtime_set_exception(module_inst, NULL); return -1; } - retval = (void **)addr_app_to_native(retval_offset); + retval = (void **)addr_app_to_native((uint64)retval_offset); node = get_thread_info(exec_env, thread); if (!node) { @@ -1159,7 +1159,8 @@ posix_memalign_wrapper(wasm_exec_env_t exec_env, void **memptr, int32 align, wasm_module_inst_t module_inst = get_module_inst(exec_env); void *p = NULL; - *((int32 *)memptr) = module_malloc(size, (void **)&p); + /* TODO: for memory 64, module_malloc may return uint64 offset */ + *((uint32 *)memptr) = (uint32)module_malloc(size, (void **)&p); if (!p) return -1; @@ -1300,7 +1301,7 @@ sem_getvalue_wrapper(wasm_exec_env_t exec_env, uint32 sem, int32 *sval) (void)exec_env; SemCallbackArgs args = { sem, NULL }; - if (validate_native_addr(sval, sizeof(int32))) { + if (validate_native_addr(sval, (uint64)sizeof(int32))) { bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args); diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c index a0d20a5b4e..e4d84d1f5c 100644 --- a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c +++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c @@ -98,7 +98,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size; if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, module_inst, exec_env, stack_size, 0, NULL, 0))) + module, module_inst, exec_env, stack_size, 0, 0, NULL, 0))) return -1; wasm_runtime_set_custom_data_internal( @@ -109,8 +109,8 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) wasm_native_inherit_contexts(new_module_inst, module_inst); - start_func = wasm_runtime_lookup_function(new_module_inst, - THREAD_START_FUNCTION, NULL); + start_func = + wasm_runtime_lookup_function(new_module_inst, THREAD_START_FUNCTION); if (!start_func) { LOG_ERROR("Failed to find thread start function %s", THREAD_START_FUNCTION); diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index d19e1bbbbb..2ac3810337 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -17,7 +17,7 @@ void wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); uint32 -wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, uint32 size, +wasm_runtime_module_realloc(wasm_module_inst_t module, uint64 ptr, uint64 size, void **p_native_addr); /* clang-format off */ @@ -233,7 +233,7 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, return false; } - s = start = addr_app_to_native(s_offset); + s = start = addr_app_to_native((uint64)s_offset); str_len = (uint32)strlen(start); if (str_len >= UINT32_MAX - 64) { @@ -401,7 +401,7 @@ printf_wrapper(wasm_exec_env_t exec_env, const char *format, _va_list va_args) struct str_context ctx = { NULL, 0, 0 }; /* format has been checked by runtime */ - if (!validate_native_addr(va_args, sizeof(int32))) + if (!validate_native_addr(va_args, (uint64)sizeof(int32))) return 0; if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args, @@ -420,13 +420,13 @@ sprintf_wrapper(wasm_exec_env_t exec_env, char *str, const char *format, struct str_context ctx; /* str and format have been checked by runtime */ - if (!validate_native_addr(va_args, sizeof(uint32))) + if (!validate_native_addr(va_args, (uint64)sizeof(uint32))) return 0; if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)str, NULL, &native_end_offset)) { wasm_runtime_set_exception(module_inst, "out of bounds memory access"); - return false; + return 0; } ctx.str = str; @@ -452,7 +452,7 @@ snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size, struct str_context ctx; /* str and format have been checked by runtime */ - if (!validate_native_addr(va_args, sizeof(uint32))) + if (!validate_native_addr(va_args, (uint64)sizeof(uint32))) return 0; ctx.str = str; @@ -499,7 +499,7 @@ strdup_wrapper(wasm_exec_env_t exec_env, const char *str) if (str) { len = (uint32)strlen(str) + 1; - str_ret_offset = module_malloc(len, (void **)&str_ret); + str_ret_offset = (uint32)module_malloc((uint64)len, (void **)&str_ret); if (str_ret_offset) { bh_memcpy_s(str_ret, len, str, len); } @@ -521,7 +521,7 @@ memcmp_wrapper(wasm_exec_env_t exec_env, const void *s1, const void *s2, wasm_module_inst_t module_inst = get_module_inst(exec_env); /* s2 has been checked by runtime */ - if (!validate_native_addr((void *)s1, size)) + if (!validate_native_addr((void *)s1, (uint64)size)) return 0; return memcmp(s1, s2, size); @@ -532,13 +532,13 @@ memcpy_wrapper(wasm_exec_env_t exec_env, void *dst, const void *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - uint32 dst_offset = addr_native_to_app(dst); + uint32 dst_offset = (uint32)addr_native_to_app(dst); if (size == 0) return dst_offset; /* src has been checked by runtime */ - if (!validate_native_addr(dst, size)) + if (!validate_native_addr(dst, (uint64)size)) return dst_offset; bh_memcpy_s(dst, size, src, size); @@ -549,13 +549,13 @@ static uint32 memmove_wrapper(wasm_exec_env_t exec_env, void *dst, void *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - uint32 dst_offset = addr_native_to_app(dst); + uint32 dst_offset = (uint32)addr_native_to_app(dst); if (size == 0) return dst_offset; /* src has been checked by runtime */ - if (!validate_native_addr(dst, size)) + if (!validate_native_addr(dst, (uint64)size)) return dst_offset; memmove(dst, src, size); @@ -566,9 +566,9 @@ static uint32 memset_wrapper(wasm_exec_env_t exec_env, void *s, int32 c, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - uint32 s_offset = addr_native_to_app(s); + uint32 s_offset = (uint32)addr_native_to_app(s); - if (!validate_native_addr(s, size)) + if (!validate_native_addr(s, (uint64)size)) return s_offset; memset(s, c, size); @@ -583,7 +583,7 @@ strchr_wrapper(wasm_exec_env_t exec_env, const char *s, int32 c) /* s has been checked by runtime */ ret = strchr(s, c); - return ret ? addr_native_to_app(ret) : 0; + return ret ? (uint32)addr_native_to_app(ret) : 0; } static int32 @@ -602,7 +602,7 @@ strncmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2, wasm_module_inst_t module_inst = get_module_inst(exec_env); /* s2 has been checked by runtime */ - if (!validate_native_addr((void *)s1, size)) + if (!validate_native_addr((void *)s1, (uint64)size)) return 0; return strncmp(s1, s2, size); @@ -615,7 +615,7 @@ strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src) uint32 len = (uint32)strlen(src) + 1; /* src has been checked by runtime */ - if (!validate_native_addr(dst, len)) + if (!validate_native_addr(dst, (uint64)len)) return 0; #ifndef BH_PLATFORM_WINDOWS @@ -623,7 +623,7 @@ strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src) #else strncpy_s(dst, len, src, len); #endif - return addr_native_to_app(dst); + return (uint32)addr_native_to_app(dst); } static uint32 @@ -633,7 +633,7 @@ strncpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src, wasm_module_inst_t module_inst = get_module_inst(exec_env); /* src has been checked by runtime */ - if (!validate_native_addr(dst, size)) + if (!validate_native_addr(dst, (uint64)size)) return 0; #ifndef BH_PLATFORM_WINDOWS @@ -641,7 +641,7 @@ strncpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src, #else strncpy_s(dst, size, src, size); #endif - return addr_native_to_app(dst); + return (uint32)addr_native_to_app(dst); } static uint32 @@ -657,7 +657,7 @@ static uint32 malloc_wrapper(wasm_exec_env_t exec_env, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - return module_malloc(size, NULL); + return (uint32)module_malloc((uint64)size, NULL); } static uint32 @@ -671,7 +671,7 @@ calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size) if (total_size >= UINT32_MAX) return 0; - ret_offset = module_malloc((uint32)total_size, (void **)&ret_ptr); + ret_offset = (uint32)module_malloc(total_size, (void **)&ret_ptr); if (ret_offset) { memset(ret_ptr, 0, (uint32)total_size); } @@ -692,7 +692,7 @@ free_wrapper(wasm_exec_env_t exec_env, void *ptr) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!validate_native_addr(ptr, sizeof(uint32))) + if (!validate_native_addr(ptr, (uint64)sizeof(uint32))) return; module_free(addr_native_to_app(ptr)); @@ -723,11 +723,11 @@ strtol_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr, int32 num = 0; /* nptr has been checked by runtime */ - if (!validate_native_addr(endptr, sizeof(uint32))) + if (!validate_native_addr(endptr, (uint64)sizeof(uint32))) return 0; num = (int32)strtol(nptr, endptr, base); - *(uint32 *)endptr = addr_native_to_app(*endptr); + *(uint32 *)endptr = (uint32)addr_native_to_app(*endptr); return num; } @@ -740,11 +740,11 @@ strtoul_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr, uint32 num = 0; /* nptr has been checked by runtime */ - if (!validate_native_addr(endptr, sizeof(uint32))) + if (!validate_native_addr(endptr, (uint64)sizeof(uint32))) return 0; num = (uint32)strtoul(nptr, endptr, base); - *(uint32 *)endptr = addr_native_to_app(*endptr); + *(uint32 *)endptr = (uint32)addr_native_to_app(*endptr); return num; } @@ -755,11 +755,11 @@ memchr_wrapper(wasm_exec_env_t exec_env, const void *s, int32 c, uint32 n) wasm_module_inst_t module_inst = get_module_inst(exec_env); void *res; - if (!validate_native_addr((void *)s, n)) + if (!validate_native_addr((void *)s, (uint64)n)) return 0; res = memchr(s, c, n); - return addr_native_to_app(res); + return (uint32)addr_native_to_app(res); } static int32 @@ -796,7 +796,7 @@ strstr_wrapper(wasm_exec_env_t exec_env, const char *s, const char *find) wasm_module_inst_t module_inst = get_module_inst(exec_env); /* s and find have been checked by runtime */ char *res = strstr(s, find); - return addr_native_to_app(res); + return (uint32)addr_native_to_app(res); } static int32 @@ -884,10 +884,10 @@ emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, void *dst, const void *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - uint32 dst_offset = addr_native_to_app(dst); + uint32 dst_offset = (uint32)addr_native_to_app(dst); /* src has been checked by runtime */ - if (!validate_native_addr(dst, size)) + if (!validate_native_addr(dst, (uint64)size)) return dst_offset; bh_memcpy_s(dst, size, src, size); @@ -925,7 +925,7 @@ static uint32 __cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - uint32 exception = module_malloc(thrown_size, NULL); + uint32 exception = (uint32)module_malloc((uint64)thrown_size, NULL); if (!exception) return 0; @@ -968,7 +968,7 @@ clock_gettime_wrapper(wasm_exec_env_t exec_env, uint32 clk_id, (void)clk_id; - if (!validate_native_addr(ts_app, sizeof(struct timespec_app))) + if (!validate_native_addr(ts_app, (uint64)sizeof(struct timespec_app))) return (uint32)-1; time = os_time_get_boot_us(); diff --git a/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c b/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c index c21b96261f..9699554157 100644 --- a/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c +++ b/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c @@ -184,7 +184,8 @@ __sys_stat64_wrapper(wasm_exec_env_t exec_env, const char *pathname, int ret; struct stat statbuf; - if (!validate_native_addr((void *)statbuf_app, sizeof(struct stat_emcc))) + if (!validate_native_addr((void *)statbuf_app, + (uint64)sizeof(struct stat_emcc))) return -1; if (pathname == NULL) @@ -204,7 +205,8 @@ __sys_fstat64_wrapper(wasm_exec_env_t exec_env, int fd, int ret; struct stat statbuf; - if (!validate_native_addr((void *)statbuf_app, sizeof(struct stat_emcc))) + if (!validate_native_addr((void *)statbuf_app, + (uint64)sizeof(struct stat_emcc))) return -1; if (fd <= 0) @@ -225,7 +227,7 @@ mmap_wrapper(wasm_exec_env_t exec_env, void *addr, int length, int prot, char *buf; int size_read; - buf_offset = module_malloc(length, (void **)&buf); + buf_offset = module_malloc((uint64)length, (void **)&buf); if (buf_offset == 0) return -1; @@ -244,7 +246,7 @@ static int munmap_wrapper(wasm_exec_env_t exec_env, uint32 buf_offset, int length) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - module_free(buf_offset); + module_free((uint64)buf_offset); return 0; } @@ -422,7 +424,7 @@ __sys_getcwd_wrapper(wasm_exec_env_t exec_env, char *buf, uint32 size) return -1; ret = getcwd(buf, size); - return ret ? addr_native_to_app(ret) : 0; + return ret ? (uint32)addr_native_to_app(ret) : 0; } #include @@ -443,7 +445,7 @@ __sys_uname_wrapper(wasm_exec_env_t exec_env, struct utsname_app *uname_app) struct utsname uname_native = { 0 }; uint32 length; - if (!validate_native_addr(uname_app, sizeof(struct utsname_app))) + if (!validate_native_addr(uname_app, (uint64)sizeof(struct utsname_app))) return -1; if (uname(&uname_native) != 0) { diff --git a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c index 6ead654066..35d091e78d 100644 --- a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c +++ b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c @@ -115,9 +115,9 @@ wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) total_size = sizeof(int32) * ((uint64)argc + 1); if (total_size >= UINT32_MAX - || !validate_native_addr(argv_offsets, (uint32)total_size) + || !validate_native_addr(argv_offsets, total_size) || argv_buf_size >= UINT32_MAX - || !validate_native_addr(argv_buf, (uint32)argv_buf_size)) + || !validate_native_addr(argv_buf, (uint64)argv_buf_size)) return (wasi_errno_t)-1; total_size = sizeof(char *) * ((uint64)argc + 1); @@ -132,7 +132,7 @@ wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) } for (i = 0; i < argc; i++) - argv_offsets[i] = addr_native_to_app(argv[i]); + argv_offsets[i] = (uint32)addr_native_to_app(argv[i]); wasm_runtime_free(argv); return 0; @@ -150,8 +150,8 @@ wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(argc_app, sizeof(uint32)) - || !validate_native_addr(argv_buf_size_app, sizeof(uint32))) + if (!validate_native_addr(argc_app, (uint64)sizeof(uint32)) + || !validate_native_addr(argv_buf_size_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; err = uvwasi_args_sizes_get(uvwasi, &argc, &argv_buf_size); @@ -170,7 +170,7 @@ wasi_clock_res_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id, wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); - if (!validate_native_addr(resolution, sizeof(wasi_timestamp_t))) + if (!validate_native_addr(resolution, (uint64)sizeof(wasi_timestamp_t))) return (wasi_errno_t)-1; return uvwasi_clock_res_get(uvwasi, clock_id, resolution); @@ -183,7 +183,7 @@ wasi_clock_time_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id, wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); - if (!validate_native_addr(time, sizeof(wasi_timestamp_t))) + if (!validate_native_addr(time, (uint64)sizeof(wasi_timestamp_t))) return (wasi_errno_t)-1; return uvwasi_clock_time_get(uvwasi, clock_id, precision, time); @@ -212,9 +212,9 @@ wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets, total_size = sizeof(int32) * ((uint64)environ_count + 1); if (total_size >= UINT32_MAX - || !validate_native_addr(environ_offsets, (uint32)total_size) + || !validate_native_addr(environ_offsets, total_size) || environ_buf_size >= UINT32_MAX - || !validate_native_addr(environ_buf, (uint32)environ_buf_size)) + || !validate_native_addr(environ_buf, (uint64)environ_buf_size)) return (wasi_errno_t)-1; total_size = sizeof(char *) * (((uint64)environ_count + 1)); @@ -230,7 +230,7 @@ wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets, } for (i = 0; i < environ_count; i++) - environ_offsets[i] = addr_native_to_app(environs[i]); + environ_offsets[i] = (uint32)addr_native_to_app(environs[i]); wasm_runtime_free(environs); return 0; @@ -248,8 +248,8 @@ wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(environ_count_app, sizeof(uint32)) - || !validate_native_addr(environ_buf_size_app, sizeof(uint32))) + if (!validate_native_addr(environ_count_app, (uint64)sizeof(uint32)) + || !validate_native_addr(environ_buf_size_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; err = uvwasi_environ_sizes_get(uvwasi, &environ_count, &environ_buf_size); @@ -273,7 +273,7 @@ wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t))) + if (!validate_native_addr(prestat_app, (uint64)sizeof(wasi_prestat_app_t))) return (wasi_errno_t)-1; err = uvwasi_fd_prestat_get(uvwasi, fd, &prestat); @@ -338,9 +338,9 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) + if (!validate_native_addr(nread_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr(iovec_app, (uint32)total_size)) + || !validate_native_addr(iovec_app, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; @@ -350,11 +350,12 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, iovec = iovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { - if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + if (!validate_app_addr((uint64)iovec_app->buf_offset, + (uint64)iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); + iovec->buf = (void *)addr_app_to_native((uint64)iovec_app->buf_offset); iovec->buf_len = iovec_app->buf_len; } @@ -389,9 +390,9 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) + if (!validate_native_addr(nwritten_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; @@ -401,11 +402,12 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec = ciovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) { - if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + if (!validate_app_addr((uint64)iovec_app->buf_offset, + (uint64)iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf = (char *)addr_app_to_native((uint64)iovec_app->buf_offset); ciovec->buf_len = iovec_app->buf_len; } @@ -440,9 +442,9 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) + if (!validate_native_addr(nread_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; @@ -452,11 +454,12 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec = iovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { - if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + if (!validate_app_addr((uint64)iovec_app->buf_offset, + (uint64)iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); + iovec->buf = (void *)addr_app_to_native((uint64)iovec_app->buf_offset); iovec->buf_len = iovec_app->buf_len; } @@ -496,7 +499,7 @@ wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) + if (!validate_native_addr(newoffset, (uint64)sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; return uvwasi_fd_seek(uvwasi, fd, offset, whence, newoffset); @@ -511,7 +514,7 @@ wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset) if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) + if (!validate_native_addr(newoffset, (uint64)sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; return uvwasi_fd_tell(uvwasi, fd, newoffset); @@ -529,7 +532,7 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t))) + if (!validate_native_addr(fdstat_app, (uint64)sizeof(wasi_fdstat_t))) return (wasi_errno_t)-1; err = uvwasi_fd_fdstat_get(uvwasi, fd, &fdstat); @@ -597,9 +600,9 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) + if (!validate_native_addr(nwritten_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; @@ -609,11 +612,12 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec = ciovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) { - if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + if (!validate_app_addr((uint64)iovec_app->buf_offset, + (uint64)iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf = (char *)addr_app_to_native((uint64)iovec_app->buf_offset); ciovec->buf_len = iovec_app->buf_len; } @@ -725,7 +729,7 @@ wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(fd_app, sizeof(wasi_fd_t))) + if (!validate_native_addr(fd_app, (uint64)sizeof(wasi_fd_t))) return (wasi_errno_t)-1; err = uvwasi_path_open(uvwasi, dirfd, dirflags, path, path_len, oflags, @@ -747,7 +751,7 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(bufused_app, sizeof(uint32))) + if (!validate_native_addr(bufused_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; err = uvwasi_fd_readdir(uvwasi, fd, buf, buf_len, cookie, &bufused); @@ -771,7 +775,7 @@ wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(bufused_app, sizeof(uint32))) + if (!validate_native_addr(bufused_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; err = uvwasi_path_readlink(uvwasi, fd, path, path_len, buf, buf_len, @@ -808,7 +812,7 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) + if (!validate_native_addr(filestat, (uint64)sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; return uvwasi_fd_filestat_get(uvwasi, fd, filestat); @@ -852,7 +856,7 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) + if (!validate_native_addr(filestat, (uint64)sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; return uvwasi_path_filestat_get(uvwasi, fd, flags, path, path_len, @@ -928,9 +932,9 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t)) - || !validate_native_addr(out, sizeof(wasi_event_t)) - || !validate_native_addr(nevents_app, sizeof(uint32))) + if (!validate_native_addr((void *)in, (uint64)sizeof(wasi_subscription_t)) + || !validate_native_addr(out, (uint64)sizeof(wasi_event_t)) + || !validate_native_addr(nevents_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; err = uvwasi_poll_oneoff(uvwasi, in, out, nsubscriptions, &nevents); @@ -1002,11 +1006,12 @@ wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data, iovec = iovec_begin; for (i = 0; i < ri_data_len; i++, ri_data++, iovec++) { - if (!validate_app_addr(ri_data->buf_offset, ri_data->buf_len)) { + if (!validate_app_addr((uint64)ri_data->buf_offset, + (uint64)ri_data->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void *)addr_app_to_native(ri_data->buf_offset); + iovec->buf = (void *)addr_app_to_native((uint64)ri_data->buf_offset); iovec->buf_len = ri_data->buf_len; } @@ -1042,9 +1047,9 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)si_data_len; - if (!validate_native_addr(so_datalen_app, sizeof(uint32)) + if (!validate_native_addr(so_datalen_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void *)si_data, (uint32)total_size)) + || !validate_native_addr((void *)si_data, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len; @@ -1054,11 +1059,12 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, ciovec = ciovec_begin; for (i = 0; i < si_data_len; i++, si_data++, ciovec++) { - if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) { + if (!validate_app_addr((uint64)si_data->buf_offset, + (uint64)si_data->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char *)addr_app_to_native(si_data->buf_offset); + ciovec->buf = (char *)addr_app_to_native((uint64)si_data->buf_offset); ciovec->buf_len = si_data->buf_len; } diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 808d15ccaf..70e1afa5f9 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -133,9 +133,9 @@ wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) total_size = sizeof(int32) * ((uint64)argc + 1); if (total_size >= UINT32_MAX - || !validate_native_addr(argv_offsets, (uint32)total_size) + || !validate_native_addr(argv_offsets, total_size) || argv_buf_size >= UINT32_MAX - || !validate_native_addr(argv_buf, (uint32)argv_buf_size)) + || !validate_native_addr(argv_buf, (uint64)argv_buf_size)) return (wasi_errno_t)-1; total_size = sizeof(char *) * ((uint64)argc + 1); @@ -150,7 +150,7 @@ wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) } for (i = 0; i < argc; i++) - argv_offsets[i] = addr_native_to_app(argv[i]); + argv_offsets[i] = (uint32)addr_native_to_app(argv[i]); wasm_runtime_free(argv); return 0; @@ -169,8 +169,8 @@ wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(argc_app, sizeof(uint32)) - || !validate_native_addr(argv_buf_size_app, sizeof(uint32))) + if (!validate_native_addr(argc_app, (uint64)sizeof(uint32)) + || !validate_native_addr(argv_buf_size_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; argv_environ = wasi_ctx->argv_environ; @@ -191,7 +191,7 @@ wasi_clock_res_get(wasm_exec_env_t exec_env, { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!validate_native_addr(resolution, sizeof(wasi_timestamp_t))) + if (!validate_native_addr(resolution, (uint64)sizeof(wasi_timestamp_t))) return (wasi_errno_t)-1; return os_clock_res_get(clock_id, resolution); @@ -205,7 +205,7 @@ wasi_clock_time_get(wasm_exec_env_t exec_env, { wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (!validate_native_addr(time, sizeof(wasi_timestamp_t))) + if (!validate_native_addr(time, (uint64)sizeof(wasi_timestamp_t))) return (wasi_errno_t)-1; return os_clock_time_get(clock_id, precision, time); @@ -234,9 +234,9 @@ wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets, total_size = sizeof(int32) * ((uint64)environ_count + 1); if (total_size >= UINT32_MAX - || !validate_native_addr(environ_offsets, (uint32)total_size) + || !validate_native_addr(environ_offsets, total_size) || environ_buf_size >= UINT32_MAX - || !validate_native_addr(environ_buf, (uint32)environ_buf_size)) + || !validate_native_addr(environ_buf, (uint64)environ_buf_size)) return (wasi_errno_t)-1; total_size = sizeof(char *) * (((uint64)environ_count + 1)); @@ -252,7 +252,7 @@ wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets, } for (i = 0; i < environ_count; i++) - environ_offsets[i] = addr_native_to_app(environs[i]); + environ_offsets[i] = (uint32)addr_native_to_app(environs[i]); wasm_runtime_free(environs); return 0; @@ -272,8 +272,8 @@ wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(environ_count_app, sizeof(uint32)) - || !validate_native_addr(environ_buf_size_app, sizeof(uint32))) + if (!validate_native_addr(environ_count_app, (uint64)sizeof(uint32)) + || !validate_native_addr(environ_buf_size_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count, @@ -301,7 +301,7 @@ wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t))) + if (!validate_native_addr(prestat_app, (uint64)sizeof(wasi_prestat_app_t))) return (wasi_errno_t)-1; err = wasmtime_ssp_fd_prestat_get(prestats, fd, &prestat); @@ -383,9 +383,9 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) + if (!validate_native_addr(nread_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr(iovec_app, (uint32)total_size)) + || !validate_native_addr(iovec_app, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; @@ -396,11 +396,12 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, iovec = iovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { - if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + if (!validate_app_addr((uint64)iovec_app->buf_offset, + (uint64)iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); + iovec->buf = (void *)addr_app_to_native((uint64)iovec_app->buf_offset); iovec->buf_len = iovec_app->buf_len; } @@ -438,9 +439,9 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) + if (!validate_native_addr(nwritten_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; @@ -451,11 +452,12 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec = ciovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) { - if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + if (!validate_app_addr((uint64)iovec_app->buf_offset, + (uint64)iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf = (char *)addr_app_to_native((uint64)iovec_app->buf_offset); ciovec->buf_len = iovec_app->buf_len; } @@ -494,9 +496,9 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) + if (!validate_native_addr(nread_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; @@ -507,11 +509,12 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec = iovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { - if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + if (!validate_app_addr((uint64)iovec_app->buf_offset, + (uint64)iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); + iovec->buf = (void *)addr_app_to_native((uint64)iovec_app->buf_offset); iovec->buf_len = iovec_app->buf_len; } @@ -563,7 +566,7 @@ wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) + if (!validate_native_addr(newoffset, (uint64)sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; wasi_errno_t res = wasmtime_ssp_fd_seek(exec_env, curfds, fd, offset, whence, newoffset); @@ -587,7 +590,7 @@ wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset) if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) + if (!validate_native_addr(newoffset, (uint64)sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; #if WASM_ENABLE_CHECKPOINT_RESTORE != 0 @@ -615,7 +618,7 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t))) + if (!validate_native_addr(fdstat_app, (uint64)sizeof(wasi_fdstat_t))) return (wasi_errno_t)-1; err = wasmtime_ssp_fd_fdstat_get(exec_env, curfds, fd, &fdstat); @@ -698,9 +701,9 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, return (wasi_errno_t)-1; total_size = sizeof(iovec_app_t) * (uint64)iovs_len; - if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) + if (!validate_native_addr(nwritten_app, (uint64)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void *)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; @@ -711,11 +714,12 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec = ciovec_begin; for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) { - if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + if (!validate_app_addr((uint64)iovec_app->buf_offset, + (uint64)iovec_app->buf_len)) { err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf = (char *)addr_app_to_native((uint64)iovec_app->buf_offset); ciovec->buf_len = iovec_app->buf_len; } @@ -832,7 +836,7 @@ wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(fd_app, sizeof(wasi_fd_t))) + if (!validate_native_addr(fd_app, (uint64)sizeof(wasi_fd_t))) return (wasi_errno_t)-1; err = wasmtime_ssp_path_open(exec_env, curfds, dirfd, dirflags, path, @@ -869,7 +873,7 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(bufused_app, sizeof(uint32))) + if (!validate_native_addr(bufused_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; err = wasmtime_ssp_fd_readdir(exec_env, curfds, fd, buf, buf_len, cookie, @@ -901,7 +905,7 @@ wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(bufused_app, sizeof(uint32))) + if (!validate_native_addr(bufused_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; err = wasmtime_ssp_path_readlink(exec_env, curfds, fd, path, path_len, buf, @@ -954,7 +958,7 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) + if (!validate_native_addr(filestat, (uint64)sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; return wasmtime_ssp_fd_filestat_get(exec_env, curfds, fd, filestat); @@ -1013,7 +1017,7 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) + if (!validate_native_addr(filestat, (uint64)sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; return wasmtime_ssp_path_filestat_get(exec_env, curfds, fd, flags, path, @@ -1229,9 +1233,9 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t)) - || !validate_native_addr(out, sizeof(wasi_event_t)) - || !validate_native_addr(nevents_app, sizeof(uint32))) + if (!validate_native_addr((void *)in, (uint64)sizeof(wasi_subscription_t)) + || !validate_native_addr(out, (uint64)sizeof(wasi_event_t)) + || !validate_native_addr(nevents_app, (uint64)sizeof(uint32))) return (wasi_errno_t)-1; #if WASM_ENABLE_THREAD_MGR == 0 @@ -1318,7 +1322,7 @@ wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(addr, sizeof(__wasi_addr_t))) + if (!validate_native_addr(addr, (uint64)sizeof(__wasi_addr_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1349,7 +1353,7 @@ wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(addr, sizeof(__wasi_addr_t))) + if (!validate_native_addr(addr, (uint64)sizeof(__wasi_addr_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1518,7 +1522,7 @@ wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1542,7 +1546,7 @@ wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1572,8 +1576,8 @@ wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool)) - || !validate_native_addr(linger_s, sizeof(int))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool)) + || !validate_native_addr(linger_s, (uint64)sizeof(int))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1599,7 +1603,7 @@ wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(size, sizeof(wasi_size_t))) + if (!validate_native_addr(size, (uint64)sizeof(wasi_size_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1626,7 +1630,7 @@ wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(timeout_us, sizeof(uint64_t))) + if (!validate_native_addr(timeout_us, (uint64)sizeof(uint64_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1650,7 +1654,7 @@ wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1674,7 +1678,7 @@ wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1698,7 +1702,7 @@ wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(size, sizeof(__wasi_size_t))) + if (!validate_native_addr(size, (uint64)sizeof(__wasi_size_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1722,7 +1726,7 @@ wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(timeout_us, sizeof(uint64_t))) + if (!validate_native_addr(timeout_us, (uint64)sizeof(uint64_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1747,7 +1751,7 @@ wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1772,7 +1776,7 @@ wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1797,7 +1801,7 @@ wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1822,7 +1826,7 @@ wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(time_s, sizeof(uint32_t))) + if (!validate_native_addr(time_s, (uint64)sizeof(uint32_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1846,7 +1850,7 @@ wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(time_s, sizeof(uint32_t))) + if (!validate_native_addr(time_s, (uint64)sizeof(uint32_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1871,7 +1875,7 @@ wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1895,7 +1899,7 @@ wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s) if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(ttl_s, sizeof(uint8_t))) + if (!validate_native_addr(ttl_s, (uint64)sizeof(uint8_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1919,7 +1923,7 @@ wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(ttl_s, sizeof(uint8_t))) + if (!validate_native_addr(ttl_s, (uint64)sizeof(uint8_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -1943,7 +1947,7 @@ wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(is_enabled, sizeof(bool))) + if (!validate_native_addr(is_enabled, (uint64)sizeof(bool))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -2307,7 +2311,7 @@ wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t))) + if (!validate_native_addr(imr_multiaddr, (uint64)sizeof(__wasi_addr_ip_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -2332,7 +2336,7 @@ wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t))) + if (!validate_native_addr(imr_multiaddr, (uint64)sizeof(__wasi_addr_ip_t))) return __WASI_EINVAL; curfds = wasi_ctx_get_curfds(wasi_ctx); @@ -2416,7 +2420,7 @@ allocate_iovec_app_buffer(wasm_module_inst_t module_inst, total_size = sizeof(iovec_app_t) * (uint64)data_len; if (total_size >= UINT32_MAX - || !validate_native_addr((void *)data, (uint32)total_size)) + || !validate_native_addr((void *)data, total_size)) return __WASI_EINVAL; for (total_size = 0, i = 0; i < data_len; i++, data++) { @@ -2454,7 +2458,8 @@ copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin, for (i = 0; i < data_len; data++, i++) { char *native_addr; - if (!validate_app_addr(data->buf_offset, data->buf_len)) { + if (!validate_app_addr((uint64)data->buf_offset, + (uint64)data->buf_len)) { return __WASI_EINVAL; } @@ -2473,7 +2478,7 @@ copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin, */ size_to_copy_into_iovec = min_uint32(data->buf_len, size_to_copy); - native_addr = (void *)addr_app_to_native(data->buf_offset); + native_addr = (void *)addr_app_to_native((uint64)data->buf_offset); bh_memcpy_s(native_addr, size_to_copy_into_iovec, buf, size_to_copy_into_iovec); buf += size_to_copy_into_iovec; @@ -2505,7 +2510,7 @@ wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock, return __WASI_EINVAL; } - if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32))) + if (!validate_native_addr(ro_data_len, (uint64)sizeof(uint32))) return __WASI_EINVAL; err = allocate_iovec_app_buffer(module_inst, ri_data, ri_data_len, @@ -2590,7 +2595,6 @@ wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data, ro_flags); set_tcp(); #endif - if (!validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t))) return __WASI_EINVAL; @@ -2622,12 +2626,13 @@ convert_iovec_app_to_buffer(wasm_module_inst_t module_inst, for (i = 0; i < si_data_len; i++, si_data++) { char *native_addr; - if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) { + if (!validate_app_addr((uint64)si_data->buf_offset, + (uint64)si_data->buf_len)) { wasm_runtime_free(*buf_ptr); return __WASI_EINVAL; } - native_addr = (char *)addr_app_to_native(si_data->buf_offset); + native_addr = (char *)addr_app_to_native((uint64)si_data->buf_offset); bh_memcpy_s(buf, si_data->buf_len, native_addr, si_data->buf_len); buf += si_data->buf_len; } @@ -2667,7 +2672,7 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, return __WASI_EINVAL; } - if (!validate_native_addr(so_data_len, sizeof(uint32))) + if (!validate_native_addr(so_data_len, (uint64)sizeof(uint32))) return __WASI_EINVAL; err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf, @@ -2708,7 +2713,7 @@ wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock, return __WASI_EINVAL; } - if (!validate_native_addr(so_data_len, sizeof(uint32))) + if (!validate_native_addr(so_data_len, (uint64)sizeof(uint32))) return __WASI_EINVAL; err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf, diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h index 9c36d7df6f..a32e5d662e 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h @@ -3,6 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#ifndef _BLOCKING_OP_H_ +#define _BLOCKING_OP_H_ + #include "bh_platform.h" #include "wasm_export.h" @@ -57,3 +60,5 @@ __wasi_errno_t blocking_op_poll(wasm_exec_env_t exec_env, struct pollfd *pfds, nfds_t nfds, int timeout, int *retp); #endif + +#endif /* end of _BLOCKING_OP_H_ */ 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 d23132a4a8..c9b8c5da8e 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 @@ -915,7 +915,6 @@ wasmtime_ssp_fd_renumber(wasm_exec_env_t exec_env, struct fd_table *curfds, struct fd_object *fo; struct fd_object *fo_from = fe_from->object; - fd_table_detach(ft, to, &fo); refcount_acquire(&fo_from->refcount); fd_table_attach(ft, to, fo_from, fe_from->rights_base, @@ -2990,7 +2989,8 @@ argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf, void argv_environ_destroy(struct argv_environ_values *argv_environ) -{} +{ +} void fd_table_destroy(struct fd_table *ft) diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index ee1bc97d91..507a672826 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -143,14 +143,14 @@ safe_traverse_exec_env_list(WASMCluster *cluster, list_visitor visitor, /* The caller must not have any locks */ bool -wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint32 *p_start, +wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint64 *p_start, uint32 *p_size) { WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0 WASMModuleInstanceCommon *module_inst = wasm_exec_env_get_module_inst(exec_env); - uint32 stack_end; + uint64 stack_end; stack_end = wasm_runtime_module_malloc_internal(module_inst, exec_env, cluster->stack_size, NULL); @@ -189,7 +189,7 @@ wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint32 *p_start, /* The caller must not have any locks */ bool -wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint32 start) +wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint64 start) { WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); @@ -227,7 +227,8 @@ WASMCluster * wasm_cluster_create(WASMExecEnv *exec_env) { WASMCluster *cluster; - uint32 aux_stack_start, aux_stack_size; + uint32 aux_stack_size; + uint64 aux_stack_start; bh_assert(exec_env->cluster == NULL); if (!(cluster = wasm_runtime_malloc(sizeof(WASMCluster)))) { @@ -284,7 +285,7 @@ wasm_cluster_create(WASMExecEnv *exec_env) #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0 if (cluster_max_thread_num != 0) { - uint64 total_size = cluster_max_thread_num * sizeof(uint32); + uint64 total_size = cluster_max_thread_num * sizeof(uint64); uint32 i; if (total_size >= UINT32_MAX || !(cluster->stack_tops = @@ -500,7 +501,8 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) wasm_module_t module; wasm_module_inst_t new_module_inst; WASMExecEnv *new_exec_env; - uint32 aux_stack_start, aux_stack_size; + uint32 aux_stack_size; + uint64 aux_stack_start; uint32 stack_size = 8192; if (!module_inst || !(module = wasm_exec_env_get_module(exec_env))) { @@ -508,7 +510,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) } if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, module_inst, exec_env, stack_size, 0, NULL, 0))) { + module, module_inst, exec_env, stack_size, 0, 0, NULL, 0))) { return NULL; } @@ -560,6 +562,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) aux_stack_size)) { goto fail3; } + new_exec_env->is_aux_stack_allocated = true; /* Inherit suspend_flags of parent thread */ new_exec_env->suspend_flags.flags = @@ -605,9 +608,11 @@ wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env) exec_env_tls = exec_env; } - /* Free aux stack space */ + /* Free aux stack space which was allocated in + wasm_cluster_spawn_exec_env */ + bh_assert(exec_env_tls->is_aux_stack_allocated); wasm_cluster_free_aux_stack(exec_env_tls, - exec_env->aux_stack_bottom.bottom); + (uint64)exec_env->aux_stack_bottom); os_mutex_lock(&cluster->lock); @@ -663,7 +668,9 @@ thread_manager_start_routine(void *arg) #endif /* Free aux stack space */ - wasm_cluster_free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); + if (exec_env->is_aux_stack_allocated) + wasm_cluster_free_aux_stack(exec_env, + (uint64)exec_env->aux_stack_bottom); os_mutex_lock(&cluster_list_lock); @@ -707,7 +714,7 @@ restore_env(WASMModuleInstanceCommon *module_inst); int32 wasm_cluster_create_thread(WASMExecEnv *exec_env, wasm_module_inst_t module_inst, - bool is_aux_stack_allocated, uint32 aux_stack_start, + bool is_aux_stack_allocated, uint64 aux_stack_start, uint32 aux_stack_size, void *(*thread_routine)(void *), void *arg) { @@ -764,12 +771,14 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, } } #if WASM_ENABLE_CHECKPOINT_RESTORE != 0 - } + new_exec_env->is_aux_stack_allocated = true; #endif + } else { /* Disable aux stack */ - new_exec_env->aux_stack_boundary.boundary = 0; - new_exec_env->aux_stack_bottom.bottom = UINT32_MAX; + new_exec_env->aux_stack_boundary = 0; + new_exec_env->aux_stack_bottom = UINTPTR_MAX; + new_exec_env->is_aux_stack_allocated = false; } /* Inherit suspend_flags of parent thread */ @@ -830,10 +839,10 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, #if WASM_ENABLE_INTERP != 0 if (module_inst_src->module_type == Wasm_Module_Bytecode) { - new_c_api_func_imports = &(((WASMModuleInstance *)module_inst_dst) - ->e->common.c_api_func_imports); - c_api_func_imports = ((const WASMModuleInstance *)module_inst_src) - ->e->common.c_api_func_imports; + new_c_api_func_imports = + &(((WASMModuleInstance *)module_inst_dst)->c_api_func_imports); + c_api_func_imports = + ((const WASMModuleInstance *)module_inst_src)->c_api_func_imports; import_func_count = ((WASMModule *)(((const WASMModuleInstance *)module_inst_src) ->module)) @@ -842,13 +851,10 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, #endif #if WASM_ENABLE_AOT != 0 if (module_inst_src->module_type == Wasm_Module_AoT) { - AOTModuleInstanceExtra *e = - (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_dst)->e; - new_c_api_func_imports = &(e->common.c_api_func_imports); - - e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_src)->e; - c_api_func_imports = e->common.c_api_func_imports; - + new_c_api_func_imports = + &(((AOTModuleInstance *)module_inst_dst)->c_api_func_imports); + c_api_func_imports = + ((const AOTModuleInstance *)module_inst_src)->c_api_func_imports; import_func_count = ((AOTModule *)(((AOTModuleInstance *)module_inst_src)->module)) ->import_func_count; @@ -1101,7 +1107,9 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) #endif /* Free aux stack space */ - wasm_cluster_free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); + if (exec_env->is_aux_stack_allocated) + wasm_cluster_free_aux_stack(exec_env, + (uint64)exec_env->aux_stack_bottom); /* App exit the thread, free the resources before exit native thread */ diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 06d2088364..ee2383a33f 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -30,7 +30,7 @@ struct WASMCluster { /* The aux stack of a module with shared memory will be divided into several segments. This array store the stack top of different segments */ - uint32 *stack_tops; + uint64 *stack_tops; /* Record which segments are occupied */ bool *stack_segment_occupied; #endif @@ -89,7 +89,7 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, int32 wasm_cluster_create_thread(WASMExecEnv *exec_env, wasm_module_inst_t module_inst, - bool is_aux_stack_allocated, uint32 aux_stack_start, + bool is_aux_stack_allocated, uint64 aux_stack_start, uint32 aux_stack_size, void *(*thread_routine)(void *), void *arg); @@ -231,11 +231,11 @@ void wasm_cluster_traverse_unlock(WASMExecEnv *exec_env); bool -wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint32 *p_start, +wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint64 *p_start, uint32 *p_size); bool -wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint32 start); +wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint64 start); #ifdef __cplusplus } diff --git a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c index fe04b657bb..44aef53593 100644 --- a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c +++ b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c @@ -10,49 +10,75 @@ graph_builder_app_native(wasm_module_inst_t instance, graph_builder_wasm *builder_wasm, graph_builder *builder) { - if (!wasm_runtime_validate_app_addr(instance, builder_wasm->buf_offset, - builder_wasm->size * sizeof(uint8_t))) { + if (!wasm_runtime_validate_app_addr( + instance, (uint64)builder_wasm->buf_offset, + (uint64)builder_wasm->size * sizeof(uint8_t))) { NN_ERR_PRINTF("builder_wasm->buf_offset is invalid"); return invalid_argument; } builder->buf = (uint8_t *)wasm_runtime_addr_app_to_native( - instance, builder_wasm->buf_offset); + instance, (uint64)builder_wasm->buf_offset); builder->size = builder_wasm->size; return success; } +/** + * builder_array_wasm is consisted of {builder_wasm, size} + */ +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 +error +graph_builder_array_app_native(wasm_module_inst_t instance, + graph_builder_wasm *builder_wasm, uint32_t size, + graph_builder_array *builder_array) +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ error graph_builder_array_app_native(wasm_module_inst_t instance, graph_builder_array_wasm *builder_array_wasm, graph_builder_array *builder_array) +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ { - if (!wasm_runtime_validate_native_addr(instance, builder_array_wasm, - sizeof(graph_builder_array_wasm))) { +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 +#define array_size size +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ +#define array_size builder_array_wasm->size + + if (!wasm_runtime_validate_native_addr( + instance, builder_array_wasm, + (uint64)sizeof(graph_builder_array_wasm))) { NN_ERR_PRINTF("builder_array_wasm is invalid"); return invalid_argument; } +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ - NN_DBG_PRINTF("Graph builder array contains %d elements", - builder_array_wasm->size); + NN_DBG_PRINTF("Graph builder array contains %d elements", array_size); +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + if (!wasm_runtime_validate_native_addr(instance, builder_wasm, + (uint64)array_size + * sizeof(graph_builder_wasm))) { + NN_ERR_PRINTF("builder_wasm is invalid"); + return invalid_argument; + } +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ if (!wasm_runtime_validate_app_addr( - instance, builder_array_wasm->buf_offset, - builder_array_wasm->size * sizeof(graph_builder_wasm))) { + instance, (uint64)builder_array_wasm->buf_offset, + (uint64)array_size * sizeof(graph_builder_wasm))) { NN_ERR_PRINTF("builder_array_wasm->buf_offset is invalid"); return invalid_argument; } graph_builder_wasm *builder_wasm = (graph_builder_wasm *)wasm_runtime_addr_app_to_native( - instance, builder_array_wasm->buf_offset); + instance, (uint64)builder_array_wasm->buf_offset); +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ graph_builder *builder = (graph_builder *)wasm_runtime_malloc( - builder_array_wasm->size * sizeof(graph_builder)); + array_size * sizeof(graph_builder)); if (builder == NULL) return missing_memory; - for (uint32_t i = 0; i < builder_array_wasm->size; ++i) { + for (uint32_t i = 0; i < array_size; ++i) { error res; if (success != (res = graph_builder_app_native(instance, &builder_wasm[i], @@ -66,22 +92,31 @@ graph_builder_array_app_native(wasm_module_inst_t instance, } builder_array->buf = builder; - builder_array->size = builder_array_wasm->size; + builder_array->size = array_size; return success; +#undef array_size } static error tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements, tensor_wasm *input_tensor_wasm, tensor_data *data) { - if (!wasm_runtime_validate_app_addr( - instance, input_tensor_wasm->data_offset, total_elements)) { +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 +#define data_size input_tensor_wasm->data_size +#else +#define data_size total_elements +#endif + + if (!wasm_runtime_validate_app_addr(instance, + (uint64)input_tensor_wasm->data_offset, + (uint64)data_size)) { NN_ERR_PRINTF("input_tensor_wasm->data_offset is invalid"); return invalid_argument; } *data = (tensor_data)wasm_runtime_addr_app_to_native( - instance, input_tensor_wasm->data_offset); + instance, (uint64)input_tensor_wasm->data_offset); return success; +#undef data_size } static error @@ -89,19 +124,24 @@ tensor_dimensions_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm, tensor_dimensions **dimensions) { - if (!wasm_runtime_validate_app_addr(instance, - input_tensor_wasm->dimensions_offset, - sizeof(tensor_dimensions_wasm))) { +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + tensor_dimensions_wasm *dimensions_wasm = &input_tensor_wasm->dimensions; +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ + if (!wasm_runtime_validate_app_addr( + instance, (uint64)input_tensor_wasm->dimensions_offset, + (uint64)sizeof(tensor_dimensions_wasm))) { NN_ERR_PRINTF("input_tensor_wasm->dimensions_offset is invalid"); return invalid_argument; } tensor_dimensions_wasm *dimensions_wasm = (tensor_dimensions_wasm *)wasm_runtime_addr_app_to_native( - instance, input_tensor_wasm->dimensions_offset); + instance, (uint64)input_tensor_wasm->dimensions_offset); +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ - if (!wasm_runtime_validate_app_addr(instance, dimensions_wasm->buf_offset, - sizeof(tensor_dimensions))) { + if (!wasm_runtime_validate_app_addr(instance, + (uint64)dimensions_wasm->buf_offset, + (uint64)sizeof(tensor_dimensions))) { NN_ERR_PRINTF("dimensions_wasm->buf_offset is invalid"); return invalid_argument; } @@ -113,7 +153,7 @@ tensor_dimensions_app_native(wasm_module_inst_t instance, (*dimensions)->size = dimensions_wasm->size; (*dimensions)->buf = (uint32_t *)wasm_runtime_addr_app_to_native( - instance, dimensions_wasm->buf_offset); + instance, (uint64)dimensions_wasm->buf_offset); NN_DBG_PRINTF("Number of dimensions: %d", (*dimensions)->size); return success; @@ -125,7 +165,7 @@ tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm, { NN_DBG_PRINTF("Converting tensor_wasm to tensor"); if (!wasm_runtime_validate_native_addr(instance, input_tensor_wasm, - sizeof(tensor_wasm))) { + (uint64)sizeof(tensor_wasm))) { NN_ERR_PRINTF("input_tensor_wasm is invalid"); return invalid_argument; } diff --git a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h index 15154bd310..f0930a8837 100644 --- a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h +++ b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h @@ -34,15 +34,29 @@ typedef struct { } tensor_dimensions_wasm; typedef struct { +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + tensor_dimensions_wasm dimensions; + tensor_type type; + uint32_t data_offset; + uint32_t data_size; +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ uint32_t dimensions_offset; tensor_type type; uint32_t data_offset; +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ } tensor_wasm; +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 +error +graph_builder_array_app_native(wasm_module_inst_t instance, + graph_builder_wasm *builder_wasm, uint32_t size, + graph_builder_array *builder_array); +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ error graph_builder_array_app_native(wasm_module_inst_t instance, graph_builder_array_wasm *builder, graph_builder_array *builder_native); +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ error tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor, diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c index c234e450a1..1fbb944286 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c @@ -189,9 +189,16 @@ is_model_initialized(WASINNContext *wasi_nn_ctx) /* WASI-NN implementation */ +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 +error +wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_wasm *builder, + uint32_t builder_wasm_size, graph_encoding encoding, + execution_target target, graph *g) +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ error wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder, graph_encoding encoding, execution_target target, graph *g) +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ { NN_DBG_PRINTF("Running wasi_nn_load [encoding=%d, target=%d]...", encoding, target); @@ -206,12 +213,20 @@ wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder, error res; graph_builder_array builder_native = { 0 }; +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + if (success + != (res = graph_builder_array_app_native( + instance, builder, builder_wasm_size, &builder_native))) + return res; +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ if (success != (res = graph_builder_array_app_native(instance, builder, &builder_native))) return res; +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ - if (!wasm_runtime_validate_native_addr(instance, g, sizeof(graph))) { + if (!wasm_runtime_validate_native_addr(instance, g, + (uint64)sizeof(graph))) { NN_ERR_PRINTF("graph is invalid"); res = invalid_argument; goto fail; @@ -248,8 +263,8 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g, if (success != (res = is_model_initialized(wasi_nn_ctx))) return res; - if (!wasm_runtime_validate_native_addr(instance, ctx, - sizeof(graph_execution_context))) { + if (!wasm_runtime_validate_native_addr( + instance, ctx, (uint64)sizeof(graph_execution_context))) { NN_ERR_PRINTF("ctx is invalid"); return invalid_argument; } @@ -314,10 +329,17 @@ wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx) return res; } +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 +error +wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, + uint32_t index, tensor_data output_tensor, + uint32_t output_tensor_len, uint32_t *output_tensor_size) +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ error wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, uint32_t index, tensor_data output_tensor, uint32_t *output_tensor_size) +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ { NN_DBG_PRINTF("Running wasi_nn_get_output [ctx=%d, index=%d]...", ctx, index); @@ -331,13 +353,19 @@ wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, return res; if (!wasm_runtime_validate_native_addr(instance, output_tensor_size, - sizeof(uint32_t))) { + (uint64)sizeof(uint32_t))) { NN_ERR_PRINTF("output_tensor_size is invalid"); return invalid_argument; } +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + res = lookup[wasi_nn_ctx->current_encoding].get_output( + wasi_nn_ctx->tflite_ctx, ctx, index, output_tensor, &output_tensor_len); + *output_tensor_size = output_tensor_len; +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ res = lookup[wasi_nn_ctx->current_encoding].get_output( wasi_nn_ctx->tflite_ctx, ctx, index, output_tensor, output_tensor_size); +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ NN_DBG_PRINTF("wasi_nn_get_output finished with status %d [data_size=%d]", res, *output_tensor_size); return res; @@ -351,11 +379,19 @@ wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, /* clang-format on */ static NativeSymbol native_symbols_wasi_nn[] = { +#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 + REG_NATIVE_FUNC(load, "(*iii*)i"), + REG_NATIVE_FUNC(init_execution_context, "(i*)i"), + REG_NATIVE_FUNC(set_input, "(ii*)i"), + REG_NATIVE_FUNC(compute, "(i)i"), + REG_NATIVE_FUNC(get_output, "(ii*i*)i"), +#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ REG_NATIVE_FUNC(load, "(*ii*)i"), REG_NATIVE_FUNC(init_execution_context, "(i*)i"), REG_NATIVE_FUNC(set_input, "(ii*)i"), REG_NATIVE_FUNC(compute, "(i)i"), REG_NATIVE_FUNC(get_output, "(ii**)i"), +#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ }; uint32_t diff --git a/core/shared/mem-alloc/ems/ems_alloc.c b/core/shared/mem-alloc/ems/ems_alloc.c index b667fbe9fc..4863527d62 100644 --- a/core/shared/mem-alloc/ems/ems_alloc.c +++ b/core/shared/mem-alloc/ems/ems_alloc.c @@ -785,8 +785,8 @@ gc_alloc_wo_internal(void *vheap, gc_size_t size, const char *file, int line) if (!hmu) goto finish; - /* Do we need to memset the memory to 0? */ - /* memset((char *)hmu + sizeof(*hmu), 0, tot_size - sizeof(*hmu)); */ + /* Don't memset the memory to improve performance, the caller should + decide whether to memset it or not */ bh_assert(hmu_get_size(hmu) >= tot_size); /* the total size allocated may be larger than diff --git a/core/shared/mem-alloc/ems/ems_gc.c b/core/shared/mem-alloc/ems/ems_gc.c index b0f14772bb..26e83a975c 100644 --- a/core/shared/mem-alloc/ems/ems_gc.c +++ b/core/shared/mem-alloc/ems/ems_gc.c @@ -114,8 +114,8 @@ sweep_instance_heap(gc_heap_t *heap) else { /* current block is still live */ if (last) { - tot_free += (char *)cur - (char *)last; - gci_add_fc(heap, last, (char *)cur - (char *)last); + tot_free += (gc_size_t)((char *)cur - (char *)last); + gci_add_fc(heap, last, (gc_size_t)((char *)cur - (char *)last)); hmu_mark_pinuse(last); last = NULL; } @@ -132,8 +132,8 @@ sweep_instance_heap(gc_heap_t *heap) bh_assert(cur == end); if (last) { - tot_free += (char *)cur - (char *)last; - gci_add_fc(heap, last, (char *)cur - (char *)last); + tot_free += (gc_size_t)((char *)cur - (char *)last); + gci_add_fc(heap, last, (gc_size_t)((char *)cur - (char *)last)); hmu_mark_pinuse(last); } @@ -449,7 +449,9 @@ gci_gc_heap(void *h) LOG_VERBOSE("#reclaim instance heap %p", heap); - gct_vm_gc_prepare(); + /* TODO: get exec_env of current thread when GC multi-threading + is enabled, and pass it to runtime */ + gct_vm_gc_prepare(NULL); gct_vm_mutex_lock(&heap->lock); heap->is_doing_reclaim = 1; @@ -459,7 +461,9 @@ gci_gc_heap(void *h) heap->is_doing_reclaim = 0; gct_vm_mutex_unlock(&heap->lock); - gct_vm_gc_finished(); + /* TODO: get exec_env of current thread when GC multi-threading + is enabled, and pass it to runtime */ + gct_vm_gc_finished(NULL); LOG_VERBOSE("#reclaim instance heap %p done", heap); diff --git a/core/shared/mem-alloc/mem_alloc.c b/core/shared/mem-alloc/mem_alloc.c index 1f9e03d5ac..df1a4de4cf 100644 --- a/core/shared/mem-alloc/mem_alloc.c +++ b/core/shared/mem-alloc/mem_alloc.c @@ -77,13 +77,13 @@ mem_allocator_free_with_gc(mem_allocator_t allocator, void *ptr) void mem_allocator_enable_gc_reclaim(mem_allocator_t allocator, void *exec_env) { - return gc_enable_gc_reclaim((gc_handle_t)allocator, exec_env); + gc_enable_gc_reclaim((gc_handle_t)allocator, exec_env); } #else void mem_allocator_enable_gc_reclaim(mem_allocator_t allocator, void *cluster) { - return gc_enable_gc_reclaim((gc_handle_t)allocator, cluster); + gc_enable_gc_reclaim((gc_handle_t)allocator, cluster); } #endif diff --git a/core/shared/platform/common/posix/posix_file.c b/core/shared/platform/common/posix/posix_file.c index ad5589f739..20f94fba34 100644 --- a/core/shared/platform/common/posix/posix_file.c +++ b/core/shared/platform/common/posix/posix_file.c @@ -384,7 +384,7 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket. if (openat_errno == ENXIO) { struct stat sb; - int ret = fstatat(fd, path, &sb, + int ret = fstatat(handle, path, &sb, (lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) ? 0 : AT_SYMLINK_NOFOLLOW); @@ -396,7 +396,7 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, if (openat_errno == ENOTDIR && (open_flags & (O_NOFOLLOW | O_DIRECTORY)) != 0) { struct stat sb; - int ret = fstatat(fd, path, &sb, AT_SYMLINK_NOFOLLOW); + int ret = fstatat(handle, path, &sb, AT_SYMLINK_NOFOLLOW); if (S_ISLNK(sb.st_mode)) { return __WASI_ELOOP; } diff --git a/core/shared/platform/common/posix/posix_memmap.c b/core/shared/platform/common/posix/posix_memmap.c index 72c8d70e65..c76abf1378 100644 --- a/core/shared/platform/common/posix/posix_memmap.c +++ b/core/shared/platform/common/posix/posix_memmap.c @@ -65,9 +65,11 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) /* integer overflow */ return NULL; +#if WASM_ENABLE_MEMORY64 == 0 if (request_size > 16 * (uint64)UINT32_MAX) - /* at most 16 G is allowed */ + /* at most 64 G is allowed */ return NULL; +#endif if (prot & MMAP_PROT_READ) map_prot |= PROT_READ; @@ -134,7 +136,7 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) } #endif /* end of BUILD_TARGET_RISCV64_LP64D || BUILD_TARGET_RISCV64_LP64 */ - /* memory has't been mapped or was mapped failed previously */ + /* memory hasn't been mapped or was mapped failed previously */ if (addr == MAP_FAILED) { /* try 5 times */ for (i = 0; i < 5; i++) { diff --git a/core/shared/platform/esp-idf/espidf_memmap.c b/core/shared/platform/esp-idf/espidf_memmap.c index 9f3ec47a6a..6b1b6f0458 100644 --- a/core/shared/platform/esp-idf/espidf_memmap.c +++ b/core/shared/platform/esp-idf/espidf_memmap.c @@ -59,6 +59,12 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) } } +void * +os_mremap(void *old_addr, size_t old_size, size_t new_size) +{ + return os_mremap_slow(old_addr, old_size, new_size); +} + void os_munmap(void *addr, size_t size) { diff --git a/core/shared/platform/esp-idf/espidf_platform.c b/core/shared/platform/esp-idf/espidf_platform.c index 8d3a9b87c1..9c0d02e629 100644 --- a/core/shared/platform/esp-idf/espidf_platform.c +++ b/core/shared/platform/esp-idf/espidf_platform.c @@ -234,7 +234,7 @@ unlinkat(int fd, const char *path, int flag) } int -utimensat(int fd, const char *path, const struct timespec *ts, int flag) +utimensat(int fd, const char *path, const struct timespec ts[2], int flag) { errno = ENOSYS; return -1; @@ -257,7 +257,7 @@ ftruncate(int fd, off_t length) #endif int -futimens(int fd, const struct timespec *times) +futimens(int fd, const struct timespec times[2]) { errno = ENOSYS; return -1; @@ -268,4 +268,4 @@ nanosleep(const struct timespec *req, struct timespec *rem) { errno = ENOSYS; return -1; -} \ No newline at end of file +} diff --git a/core/shared/platform/esp-idf/platform_internal.h b/core/shared/platform/esp-idf/platform_internal.h index 70c4fe7b1d..0f873810ee 100644 --- a/core/shared/platform/esp-idf/platform_internal.h +++ b/core/shared/platform/esp-idf/platform_internal.h @@ -109,6 +109,12 @@ typedef unsigned int korp_sem; #define DT_LNK DTYPE_LINK #define DT_SOCK DTYPE_SOCK +static inline int +os_getpagesize() +{ + return 4096; +} + typedef int os_file_handle; typedef DIR *os_dir_stream; typedef int os_raw_file_handle; diff --git a/core/shared/platform/nuttx/shared_platform.cmake b/core/shared/platform/nuttx/shared_platform.cmake index ff70cc0311..d691068f2f 100644 --- a/core/shared/platform/nuttx/shared_platform.cmake +++ b/core/shared/platform/nuttx/shared_platform.cmake @@ -8,6 +8,10 @@ add_definitions(-DBH_PLATFORM_NUTTX) include_directories(${PLATFORM_SHARED_DIR}) include_directories(${PLATFORM_SHARED_DIR}/../include) +include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) if (WAMR_BUILD_LIBC_WASI EQUAL 1) @@ -16,6 +20,7 @@ if (WAMR_BUILD_LIBC_WASI EQUAL 1) set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) endif () -include (${CMAKE_CURRENT_LIST_DIR}/../common/memory/platform_api_memory.cmake) -set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE} ${PLATFORM_COMMON_MEMORY_SOURCE}) +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE} ${PLATFORM_COMMON_POSIX_SOURCE} ${UNCOMMON_SHARED_SOURCE}) +# remove posix_memmap.c for NuttX +list(REMOVE_ITEM ${PLATFORM_SHARED_SOURCE} ${PLATFORM_COMMON_POSIX_DIR}/posix_memmap.c) diff --git a/core/shared/platform/zephyr/platform_internal.h b/core/shared/platform/zephyr/platform_internal.h index 00bb49567d..3c0f55266d 100644 --- a/core/shared/platform/zephyr/platform_internal.h +++ b/core/shared/platform/zephyr/platform_internal.h @@ -51,9 +51,7 @@ #endif /* end of KERNEL_VERSION_NUMBER < 0x030200 */ #if KERNEL_VERSION_NUMBER >= 0x030300 /* version 3.3.0 */ -#if defined(CONFIG_CPU_CORTEX_M7) && defined(CONFIG_ARM_MPU) #include -#endif #endif /* end of KERNEL_VERSION_NUMBER > 0x030300 */ #ifdef CONFIG_ARM_MPU @@ -177,4 +175,15 @@ os_get_invalid_handle() return -1; } +static inline int +os_getpagesize() +{ +#ifdef CONFIG_MMU + return CONFIG_MMU_PAGE_SIZE; +#else + /* Return a default page size if the MMU is not enabled */ + return 4096; /* 4KB */ +#endif +} + #endif diff --git a/core/shared/platform/zephyr/zephyr_platform.c b/core/shared/platform/zephyr/zephyr_platform.c index 156ce537a9..fc54ba5598 100644 --- a/core/shared/platform/zephyr/zephyr_platform.c +++ b/core/shared/platform/zephyr/zephyr_platform.c @@ -25,9 +25,11 @@ disable_mpu_rasr_xn(void) would most likely be set at index 2. */ for (index = 0U; index < 8; index++) { MPU->RNR = index; +#ifdef MPU_RASR_XN_Msk if (MPU->RASR & MPU_RASR_XN_Msk) { MPU->RASR |= ~MPU_RASR_XN_Msk; } +#endif } } #endif /* end of CONFIG_ARM_MPU */ @@ -185,6 +187,12 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) return BH_MALLOC(size); } +void * +os_mremap(void *old_addr, size_t old_size, size_t new_size) +{ + return os_mremap_slow(old_addr, old_size, new_size); +} + void os_munmap(void *addr, size_t size) { diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h index 5744a64c03..4f7d9bc833 100644 --- a/core/shared/utils/bh_atomic.h +++ b/core/shared/utils/bh_atomic.h @@ -44,6 +44,7 @@ extern "C" { * #endif */ +typedef uint64 bh_atomic_64_t; typedef uint32 bh_atomic_32_t; typedef uint16 bh_atomic_16_t; @@ -52,6 +53,10 @@ typedef uint16 bh_atomic_16_t; * If left undefined, it will be automatically defined * according to the platform. */ +#ifdef WASM_UINT64_IS_ATOMIC +#define BH_ATOMIC_64_IS_ATOMIC WASM_UINT64_IS_ATOMIC +#endif /* WASM_UINT64_IS_ATOMIC */ + #ifdef WASM_UINT32_IS_ATOMIC #define BH_ATOMIC_32_IS_ATOMIC WASM_UINT32_IS_ATOMIC #endif /* WASM_UINT32_IS_ATOMIC */ @@ -71,6 +76,9 @@ typedef uint16 bh_atomic_16_t; #endif #if defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) +#ifndef BH_ATOMIC_64_IS_ATOMIC +#define BH_ATOMIC_64_IS_ATOMIC 1 +#endif #ifndef BH_ATOMIC_32_IS_ATOMIC #define BH_ATOMIC_32_IS_ATOMIC 1 #endif @@ -78,6 +86,9 @@ typedef uint16 bh_atomic_16_t; #define BH_ATOMIC_16_IS_ATOMIC 1 #endif #else +#ifndef BH_ATOMIC_64_IS_ATOMIC +#define BH_ATOMIC_64_IS_ATOMIC 0 +#endif #ifndef BH_ATOMIC_32_IS_ATOMIC #define BH_ATOMIC_32_IS_ATOMIC 0 #endif @@ -101,6 +112,72 @@ typedef uint16 bh_atomic_16_t; #endif #endif +/* On some 32-bit platform, disable 64-bit atomic operations, otherwise + * undefined reference to `__atomic_load_8' */ +#ifndef WASM_UINT64_IS_ATOMIC +#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) \ + && !defined(__OpenBSD__) && (defined(__riscv) || defined(__arm__)) \ + && UINT32_MAX == UINTPTR_MAX +#undef BH_ATOMIC_64_IS_ATOMIC +#define BH_ATOMIC_64_IS_ATOMIC 0 +#endif +#endif + +#if BH_ATOMIC_64_IS_ATOMIC != 0 + +#define BH_ATOMIC_64_LOAD(v) __atomic_load_n(&(v), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_64_STORE(v, val) __atomic_store_n(&(v), val, __ATOMIC_SEQ_CST) +#define BH_ATOMIC_64_FETCH_OR(v, val) \ + __atomic_fetch_or(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_64_FETCH_AND(v, val) \ + __atomic_fetch_and(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_64_FETCH_ADD(v, val) \ + __atomic_fetch_add(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_64_FETCH_SUB(v, val) \ + __atomic_fetch_sub(&(v), (val), __ATOMIC_SEQ_CST) + +#else /* else of BH_ATOMIC_64_IS_ATOMIC != 0 */ + +#define BH_ATOMIC_64_LOAD(v) (v) +#define BH_ATOMIC_64_STORE(v, val) (v) = val +#define BH_ATOMIC_64_FETCH_OR(v, val) nonatomic_64_fetch_or(&(v), val) +#define BH_ATOMIC_64_FETCH_AND(v, val) nonatomic_64_fetch_and(&(v), val) +#define BH_ATOMIC_64_FETCH_ADD(v, val) nonatomic_64_fetch_add(&(v), val) +#define BH_ATOMIC_64_FETCH_SUB(v, val) nonatomic_64_fetch_sub(&(v), val) + +static inline uint64 +nonatomic_64_fetch_or(bh_atomic_64_t *p, uint64 val) +{ + uint64 old = *p; + *p |= val; + return old; +} + +static inline uint64 +nonatomic_64_fetch_and(bh_atomic_64_t *p, uint64 val) +{ + uint64 old = *p; + *p &= val; + return old; +} + +static inline uint64 +nonatomic_64_fetch_add(bh_atomic_64_t *p, uint64 val) +{ + uint64 old = *p; + *p += val; + return old; +} + +static inline uint64 +nonatomic_64_fetch_sub(bh_atomic_64_t *p, uint64 val) +{ + uint64 old = *p; + *p -= val; + return old; +} +#endif + #if BH_ATOMIC_32_IS_ATOMIC != 0 #define BH_ATOMIC_32_LOAD(v) __atomic_load_n(&(v), __ATOMIC_SEQ_CST) diff --git a/core/shared/utils/runtime_timer.c b/core/shared/utils/runtime_timer.c index b9ace567f2..9d390c2145 100644 --- a/core/shared/utils/runtime_timer.c +++ b/core/shared/utils/runtime_timer.c @@ -394,7 +394,7 @@ handle_expired_timers(timer_ctx_t ctx, app_timer_t *expired) operation may change expired->next */ expired = expired->next; if (t->is_periodic) { - /* if it is repeating, then reschedule it; */ + /* if it is repeating, then reschedule it */ reschedule_timer(ctx, t); } else { diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 1271aab8e9..528ffb503b 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -76,6 +76,11 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM #### **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 + +> Note: Currently, the memory64 feature is only supported in classic interpreter running mode. + #### **Enable thread manager** - **WAMR_BUILD_THREAD_MGR**=1/0, default to disable if not set @@ -107,6 +112,9 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH**=Path to the external delegate shared library (e.g. `libedgetpu.so.1.0` for Coral USB) +#### **Enable lib wasi-nn with `wasi_ephemeral_nn` module support** +- **WAMR_BUILD_WASI_EPHEMERAL_NN**=1/0, default to disable if not set + #### **Disable boundary check with hardware trap** - **WAMR_DISABLE_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform > 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. @@ -126,6 +134,14 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_BUILD_SIMD**=1/0, default to enable if not set > Note: only supported in AOT mode x86-64 target. +#### **Enable Exception Handling** +- **WAMR_BUILD_EXCE_HANDLING**=1/0, default to disable if not set + +> Note: Currently, the exception handling feature is only supported in classic interpreter running mode. + +#### **Enable Garbage Collection** +- **WAMR_BUILD_GC**=1/0, default to disable if not set + #### **Configure Debug** - **WAMR_BUILD_CUSTOM_NAME_SECTION**=1/0, load the function name from custom name section, default to disable if not set @@ -265,6 +281,10 @@ Currently we only profile the memory consumption of module, module_instance and - **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 > 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. +#### **Enable 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. +> Note: See [Tuning the XIP intrinsic functions](./xip.md#tuning-the-xip-intrinsic-functions) for more details. + #### **Configurale memory access boundary check** - **WAMR_CONFIGUABLE_BOUNDS_CHECKS**=1/0, default to disable if not set > Note: If it is enabled, allow to run `iwasm --disable-bounds-checks` to disable the memory access boundary checks for interpreter mode. diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index b83817589b..5e4e3a5122 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -100,7 +100,7 @@ After a module is instantiated, the runtime embedder can lookup the target WASM ```c /* lookup a WASM function by its name The function signature can NULL here */ - func = wasm_runtime_lookup_function(module_inst, "fib", NULL); + func = wasm_runtime_lookup_function(module_inst, "fib"); /* creat an execution environment to execute the WASM functions */ exec_env = wasm_runtime_create_exec_env(module_inst, stack_size); @@ -211,9 +211,9 @@ There are two runtime APIs available for this purpose. * p_native_addr: return the native address of allocated memory * size: the buffer size to allocate */ -uint32_t +uint64_t wasm_runtime_module_malloc(wasm_module_inst_t module_inst, - uint32_t size, void **p_native_addr); + uint64_t size, void **p_native_addr); /** * malloc a buffer from instance's private memory space, @@ -223,28 +223,28 @@ wasm_runtime_module_malloc(wasm_module_inst_t module_inst, * src: the native buffer address * size: the size of buffer to be allocated and copy data */ -uint32_t +uint64_t wasm_runtime_module_dup_data(wasm_module_inst_t module_inst, - const char *src, uint32_t size); + const char *src, uint64_t size); /* free the memory allocated from module memory space */ void -wasm_runtime_module_free(wasm_module_inst_t module_inst, uint32_t ptr); +wasm_runtime_module_free(wasm_module_inst_t module_inst, uint64_t ptr); ``` Usage sample: ```c char * buffer = NULL; -uint32_t buffer_for_wasm; +uint64_t buffer_for_wasm; buffer_for_wasm = wasm_runtime_module_malloc(module_inst, 100, &buffer); if (buffer_for_wasm != 0) { - uint32 argv[2]; + uint32 argv[3]; strncpy(buffer, "hello", 100); /* use native address for accessing in runtime */ argv[0] = buffer_for_wasm; /* pass the buffer address for WASM space */ - argv[1] = 100; /* the size of buffer */ - wasm_runtime_call_wasm(exec_env, func, 2, argv); + argv[2] = 100; /* the size of buffer */ + wasm_runtime_call_wasm(exec_env, func, 3, argv); /* it is runtime embedder's responsibility to release the memory, unless the WASM app will free the passed pointer in its code */ diff --git a/doc/export_native_api.md b/doc/export_native_api.md index a4123d12c9..b8f77f262a 100644 --- a/doc/export_native_api.md +++ b/doc/export_native_api.md @@ -170,12 +170,12 @@ void foo2(wasm_exec_env_t exec_env, if (!wasm_runtime_validate_app_str_add(msg_offset)) return 0; - if (!wasm_runtime_validate_app_addr(buffer_offset, buf_len)) + if (!wasm_runtime_validate_app_addr((uint64)buffer_offset, (uint64)buf_len)) return; // do address conversion - buffer = wasm_runtime_addr_app_to_native(buffer_offset); - msg = wasm_runtime_addr_app_to_native(msg_offset); + buffer = wasm_runtime_addr_app_to_native((uint64)buffer_offset); + msg = wasm_runtime_addr_app_to_native((uint64)msg_offset); strncpy(buffer, msg, buf_len); } diff --git a/doc/multi_module.md b/doc/multi_module.md index 9ab26673e2..ac9e3bbde4 100644 --- a/doc/multi_module.md +++ b/doc/multi_module.md @@ -62,8 +62,7 @@ WAMR hopes that the native host or embedding environment loads/unloads the modul ```c wasm_function_inst_t wasm_runtime_lookup_function(wasm_module_inst_t const module_inst, - const char *name, - const char *signature); + const char *name); ``` Multi-module allows one to look up an exported function of a submodule. There are two ways to indicate the function _name_: diff --git a/doc/perf_tune.md b/doc/perf_tune.md index b366f09c0c..7858cc854e 100644 --- a/doc/perf_tune.md +++ b/doc/perf_tune.md @@ -98,17 +98,22 @@ You should only use this method for well tested wasm applications and make sure Linux perf is a powerful tool to analyze the performance of a program, developer can use it to find the hot functions and optimize them. It is one profiler supported by WAMR. In order to use it, you need to add `--perf-profile` while running _iwasm_. By default, it is disabled. > [!CAUTION] -> For now, only llvm-jit mode supports linux-perf. +> For now, only llvm-jit mode and aot mode supports linux-perf. Here is a basic example, if there is a Wasm application _foo.wasm_, you'll execute. ``` -$ perf record --output=perf.data.raw -- iwasm --perf-profile foo.wasm +$ perf record --output=perf.data.raw -- iwasm --enable-linux-perf foo.wasm ``` -This will create a _perf.data_ and a _jit-xxx.dump_ under _~/.debug.jit/_ folder. This extra file is WAMR generated at runtime, and it contains the mapping between the JIT code and the original Wasm function names. +This will create a _perf.data_ and +- a _jit-xxx.dump_ under _~/.debug/jit/_ folder if running llvm-jit mode +- or _/tmp/perf-.map_ if running AOT mode -The next thing need to do is to merge _jit-xxx.dump_ file into the _perf.data_. + +This file is WAMR generated. It contains information which includes jitted(precompiled) code addresses in memory, names of jitted (precompiled) functions which are named as *aot_func#N* and so on. + +If running with llvm-jit mode, the next thing is to merge _jit-xxx.dump_ file into the _perf.data_. ``` $ perf inject --jit --input=perf.data.raw --output=perf.data @@ -141,28 +146,28 @@ $ perf report --input=perf.data [Flamegraph](https://www.brendangregg.com/flamegraphs.html) is a powerful tool to visualize stack traces of profiled software so that the most frequent code-paths can be identified quickly and accurately. In order to use it, you need to [capture graphs](https://github.com/brendangregg/FlameGraph#1-capture-stacks) when running `perf record` ``` -$ perf record -k mono --call-graph=fp --output=perf.data.raw -- iwasm --perf-profile foo.wasm +$ perf record -k mono --call-graph=fp --output=perf.data.raw -- iwasm --enable-linux-perf foo.wasm ``` -merge the _jit-xxx.dump_ file into the _perf.data.raw_. +If running with llvm-jit mode, merge the _jit-xxx.dump_ file into the _perf.data.raw_. ``` $ perf inject --jit --input=perf.data.raw --output=perf.data ``` -generate the stack trace file. +Generate the stack trace file. ``` $ perf script > out.perf ``` -[fold stacks](https://github.com/brendangregg/FlameGraph#2-fold-stacks). +[Fold stacks](https://github.com/brendangregg/FlameGraph#2-fold-stacks). ``` $ ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded ``` -[render a flamegraph](https://github.com/brendangregg/FlameGraph#3-flamegraphpl) +[Render a flamegraph](https://github.com/brendangregg/FlameGraph#3-flamegraphpl) ``` $ ./FlameGraph/flamegraph.pl out.folded > perf.foo.wasm.svg @@ -288,7 +293,7 @@ And in the host embedder: bool ret; argv[0] = *(uint32 *)&arg_f32; - func = wasm_runtime_lookup_function(module_inst, "foo1", NULL); + func = wasm_runtime_lookup_function(module_inst, "foo1"); ret = wasm_runtime_call_wasm(exec_env, func, 1, argv); if (!ret) { /* handle exception */ diff --git a/language-bindings/go/samples/test.go b/language-bindings/go/samples/test.go index d0fc7d8b24..19b2814a8e 100644 --- a/language-bindings/go/samples/test.go +++ b/language-bindings/go/samples/test.go @@ -87,7 +87,7 @@ func main() { var instance *wamr.Instance var argv []uint32 var results []interface{} - var offset uint32 + var offset uint64 var native_addr *uint8 var err error diff --git a/language-bindings/go/wamr/instance.go b/language-bindings/go/wamr/instance.go index 7c761ee99b..111d795bc7 100644 --- a/language-bindings/go/wamr/instance.go +++ b/language-bindings/go/wamr/instance.go @@ -129,8 +129,7 @@ func (self *Instance) CallFunc(funcName string, cName := C.CString(funcName) defer C.free(unsafe.Pointer(cName)) - _func = C.wasm_runtime_lookup_function(self._instance, - cName, (*C.char)(C.NULL)) + _func = C.wasm_runtime_lookup_function(self._instance, cName) if _func == nil { return fmt.Errorf("CallFunc error: lookup function failed") } @@ -170,8 +169,7 @@ func (self *Instance) CallFuncV(funcName string, cName := C.CString(funcName) defer C.free(unsafe.Pointer(cName)) - _func = C.wasm_runtime_lookup_function(self._instance, - cName, (*C.char)(C.NULL)) + _func = C.wasm_runtime_lookup_function(self._instance, cName) if _func == nil { return fmt.Errorf("CallFunc error: lookup function failed") } @@ -309,62 +307,62 @@ func (self *Instance) GetException() string { } /* Allocate memory from the heap of the instance */ -func (self Instance) ModuleMalloc(size uint32) (uint32, *uint8) { - var offset C.uint32_t +func (self Instance) ModuleMalloc(size uint64) (uint64, *uint8) { + var offset C.uint64_t native_addrs := make([]*uint8, 1, 1) ptr := unsafe.Pointer(&native_addrs[0]) - offset = C.wasm_runtime_module_malloc(self._instance, (C.uint32_t)(size), + offset = C.wasm_runtime_module_malloc(self._instance, (C.uint64_t)(size), (*unsafe.Pointer)(ptr)) - return (uint32)(offset), native_addrs[0] + return (uint64)(offset), native_addrs[0] } /* Free memory to the heap of the instance */ -func (self Instance) ModuleFree(offset uint32) { - C.wasm_runtime_module_free(self._instance, (C.uint32_t)(offset)) +func (self Instance) ModuleFree(offset uint64) { + C.wasm_runtime_module_free(self._instance, (C.uint64_t)(offset)) } -func (self Instance) ValidateAppAddr(app_offset uint32, size uint32) bool { +func (self Instance) ValidateAppAddr(app_offset uint64, size uint64) bool { ret := C.wasm_runtime_validate_app_addr(self._instance, - (C.uint32_t)(app_offset), - (C.uint32_t)(size)) + (C.uint64_t)(app_offset), + (C.uint64_t)(size)) return (bool)(ret) } -func (self Instance) ValidateStrAddr(app_str_offset uint32) bool { +func (self Instance) ValidateStrAddr(app_str_offset uint64) bool { ret := C.wasm_runtime_validate_app_str_addr(self._instance, - (C.uint32_t)(app_str_offset)) + (C.uint64_t)(app_str_offset)) return (bool)(ret) } -func (self Instance) ValidateNativeAddr(native_ptr *uint8, size uint32) bool { +func (self Instance) ValidateNativeAddr(native_ptr *uint8, size uint64) bool { native_ptr_C := (unsafe.Pointer)(native_ptr) ret := C.wasm_runtime_validate_native_addr(self._instance, native_ptr_C, - (C.uint32_t)(size)) + (C.uint64_t)(size)) return (bool)(ret) } -func (self Instance) AddrAppToNative(app_offset uint32) *uint8 { +func (self Instance) AddrAppToNative(app_offset uint64) *uint8 { native_ptr := C.wasm_runtime_addr_app_to_native(self._instance, - (C.uint32_t)(app_offset)) + (C.uint64_t)(app_offset)) return (*uint8)(native_ptr) } -func (self Instance) AddrNativeToApp(native_ptr *uint8) uint32 { +func (self Instance) AddrNativeToApp(native_ptr *uint8) uint64 { native_ptr_C := (unsafe.Pointer)(native_ptr) offset := C.wasm_runtime_addr_native_to_app(self._instance, native_ptr_C) - return (uint32)(offset) + return (uint64)(offset) } -func (self Instance) GetAppAddrRange(app_offset uint32) (bool, - uint32, - uint32) { - var start_offset, end_offset C.uint32_t +func (self Instance) GetAppAddrRange(app_offset uint64) (bool, + uint64, + uint64) { + var start_offset, end_offset C.uint64_t ret := C.wasm_runtime_get_app_addr_range(self._instance, - (C.uint32_t)(app_offset), + (C.uint64_t)(app_offset), &start_offset, &end_offset) - return (bool)(ret), (uint32)(start_offset), (uint32)(end_offset) + return (bool)(ret), (uint64)(start_offset), (uint64)(end_offset) } func (self Instance) GetNativeAddrRange(native_ptr *uint8) (bool, diff --git a/language-bindings/go/wamr/module.go b/language-bindings/go/wamr/module.go index 13480b221c..7fd131ea6c 100644 --- a/language-bindings/go/wamr/module.go +++ b/language-bindings/go/wamr/module.go @@ -117,8 +117,8 @@ func (self *Module) SetWasiArgsEx(dirList [][]byte, mapDirList [][]byte, C.wasm_runtime_set_wasi_args_ex(self.module, dirPtr, dirCount, mapDirPtr, mapDirCount, envPtr, envCount, argvPtr, argc, - C.int(stdinfd), C.int(stdoutfd), - C.int(stderrfd)) + C.int64_t(stdinfd), C.int64_t(stdoutfd), + C.int64_t(stderrfd)) } /* Set module's wasi network address pool */ diff --git a/language-bindings/python/README.md b/language-bindings/python/README.md index 96b7a7ff9b..45604af7f2 100644 --- a/language-bindings/python/README.md +++ b/language-bindings/python/README.md @@ -4,7 +4,7 @@ The WAMR Python package contains a set of high-level bindings for WAMR API and W ## Installation -* **Notice**: This python package need python >= `3.9`. +* **Notice**: This python package need python >= `3.10`. To Install from local source tree in _development mode_ run the following command, diff --git a/language-bindings/python/setup.py b/language-bindings/python/setup.py index ec080e4eed..1087c64251 100755 --- a/language-bindings/python/setup.py +++ b/language-bindings/python/setup.py @@ -62,5 +62,5 @@ def run(self): 'install': PreInstallCommand, 'egg_info': PreEggInfoCommand, }, - python_requires='>=3.9' + python_requires='>=3.10' ) diff --git a/language-bindings/python/src/wamr/wamrapi/wamr.py b/language-bindings/python/src/wamr/wamrapi/wamr.py index 1bd6e547d7..9727faa37b 100644 --- a/language-bindings/python/src/wamr/wamrapi/wamr.py +++ b/language-bindings/python/src/wamr/wamrapi/wamr.py @@ -6,6 +6,7 @@ from ctypes import c_char from ctypes import c_uint from ctypes import c_uint8 +from ctypes import c_uint64 from ctypes import c_void_p from ctypes import cast from ctypes import create_string_buffer @@ -167,14 +168,14 @@ def _create_module_inst( raise Exception("Error while creating module instance") return module_inst - def malloc(self, nbytes: int, native_handler) -> c_uint: + def malloc(self, nbytes: int, native_handler) -> c_uint64: return wasm_runtime_module_malloc(self.module_inst, nbytes, native_handler) def free(self, wasm_handler) -> None: wasm_runtime_module_free(self.module_inst, wasm_handler) def lookup_function(self, name: str) -> wasm_function_inst_t: - func = wasm_runtime_lookup_function(self.module_inst, name, None) + func = wasm_runtime_lookup_function(self.module_inst, name) if not func: raise Exception("Error while looking-up function") return func diff --git a/language-bindings/python/src/wamr/wasmcapi/binding.py b/language-bindings/python/src/wamr/wasmcapi/binding.py index dd7adadf6a..1f4e0cfd03 100644 --- a/language-bindings/python/src/wamr/wasmcapi/binding.py +++ b/language-bindings/python/src/wamr/wasmcapi/binding.py @@ -2013,6 +2013,15 @@ def wasm_instance_new_with_args(arg0,arg1,arg2,arg3,arg4,arg5): _wasm_instance_new_with_args.argtypes = [POINTER(wasm_store_t),POINTER(wasm_module_t),POINTER(wasm_extern_vec_t),POINTER(POINTER(wasm_trap_t)),c_uint32,c_uint32] return _wasm_instance_new_with_args(arg0,arg1,arg2,arg3,arg4,arg5) +class InstantiationArgs(Structure): + pass + +def wasm_instance_new_with_args_ex(arg0,arg1,arg2,arg3,arg4): + _wasm_instance_new_with_args_ex = libiwasm.wasm_instance_new_with_args_ex + _wasm_instance_new_with_args_ex.restype = POINTER(wasm_instance_t) + _wasm_instance_new_with_args_ex.argtypes = [POINTER(wasm_store_t),POINTER(wasm_module_t),POINTER(wasm_extern_vec_t),POINTER(POINTER(wasm_trap_t)),POINTER(InstantiationArgs)] + return _wasm_instance_new_with_args_ex(arg0,arg1,arg2,arg3,arg4) + def wasm_instance_exports(arg0,arg1): _wasm_instance_exports = libiwasm.wasm_instance_exports _wasm_instance_exports.restype = None diff --git a/language-bindings/python/wamr-api/README.md b/language-bindings/python/wamr-api/README.md index 236150ce4c..38a4401440 100644 --- a/language-bindings/python/wamr-api/README.md +++ b/language-bindings/python/wamr-api/README.md @@ -1,6 +1,6 @@ # WARM API -* **Notice**: The python package `wamr.wamrapi.wamr` need python >= `3.9`. +* **Notice**: The python package `wamr.wamrapi.wamr` need python >= `3.10`. ## Setup @@ -8,7 +8,7 @@ Install requirements, -``` +```shell pip install -r requirements.txt ``` @@ -17,6 +17,7 @@ pip install -r requirements.txt The following command builds the iwasm library and generates the Python bindings, ```sh +# In WAMR root directory bash language-bindings/python/utils/create_lib.sh ``` diff --git a/language-bindings/python/wasm-c-api/docs/design.md b/language-bindings/python/wasm-c-api/docs/design.md index 6c3bc9168f..78bf56df0b 100644 --- a/language-bindings/python/wasm-c-api/docs/design.md +++ b/language-bindings/python/wasm-c-api/docs/design.md @@ -431,130 +431,131 @@ In next phase, we will create OOP APIs. Almost follow the ## A big list -| WASM Concept | Procedural APIs | OOP APIs | OOP APIs methods | -| ------------ | ------------------------------ | ---------- | ---------------- | -| XXX_vec | wasm_xxx_vec_new | | list | -| | wasm_xxx_vec_new_uninitialized | | | -| | wasm_xxx_vec_new_empty | | | -| | wasm_xxx_vec_copy | | | -| | wasm_xxx_vec_delete | | | -| valtype | wasm_valtype_new | valtype | \_\_init\_\_ | -| | wasm_valtype_delete | | \_\_del\_\_ | -| | wasm_valtype_kind | | \_\_eq\_\_ | -| | wasm_valtype_copy | | | -| | _vector methods_ | | | -| functype | wasm_functype_new | functype | | -| | wasm_functype_delete | | | -| | wasm_functype_params | | | -| | wasm_functype_results | | | -| | wasm_functype_copy | | | -| | _vector methods_ | | | -| globaltype | wasm_globaltype_new | globaltype | \_\_init\_\_ | -| | wasm_globaltype_delete | | \_\_del\_\_ | -| | wasm_globaltype_content | | \_\_eq\_\_ | -| | wasm_globaltype_mutability | | | -| | wasm_globaltype_copy | | | -| | _vector methods_ | | | -| tabletype | wasm_tabletype_new | tabletype | \_\_init\_\_ | -| | wasm_tabletype_delete | | \_\_del\_\_ | -| | wasm_tabletype_element | | \_\_eq\_\_ | -| | wasm_tabletype_limits | | | -| | wasm_tabletype_copy | | | -| | _vector methods_ | | | -| memorytype | wasm_memorytype_new | memorytype | \_\_init\_\_ | -| | wasm_memorytype_delete | | \_\_del\_\_ | -| | wasm_memorytype_limits | | \_\_eq\_\_ | -| | wasm_memorytype_copy | | | -| | _vector methods_ | | | -| externtype | wasm_externtype_as_XXX | externtype | | -| | wasm_XXX_as_externtype | | | -| | wasm_externtype_copy | | | -| | wasm_externtype_delete | | | -| | wasm_externtype_kind | | | -| | _vector methods_ | | | -| importtype | wasm_importtype_new | importtype | | -| | wasm_importtype_delete | | | -| | wasm_importtype_module | | | -| | wasm_importtype_name | | | -| | wasm_importtype_type | | | -| | wasm_importtype_copy | | | -| | _vector methods_ | | | -| exportype | wasm_exporttype_new | exporttype | | -| | wasm_exporttype_delete | | | -| | wasm_exporttype_name | | | -| | wasm_exporttype_type | | | -| | wasm_exporttype_copy | | | -| | _vector methods_ | | | -| val | wasm_val_delete | val | | -| | wasm_val_copy | | | -| | _vector methods_ | | | -| frame | wasm_frame_delete | frame | | -| | wasm_frame_instance | | | -| | wasm_frame_func_index | | | -| | wasm_frame_func_offset | | | -| | wasm_frame_module_offset | | | -| | wasm_frame_copy | | | -| | _vector methods_ | | | -| trap | wasm_trap_new | trap | | -| | wasm_trap_delete | | | -| | wasm_trap_message | | | -| | wasm_trap_origin | | | -| | wasm_trap_trace | | | -| | _vector methods_ | | | -| foreign | wasm_foreign_new | foreign | | -| | wasm_foreign_delete | | | -| | _vector methods_ | | | -| engine | wasm_engine_new | engine | | -| | wasm_engine_new_with_args\* | | | -| | wasm_engine_new_with_config | | | -| | wasm_engine_delete | | | -| store | wasm_store_new | store | | -| | wasm_store_delete | | | -| | _vector methods_ | | | -| module | wasm_module_new | module | | -| | wasm_module_delete | | | -| | wasm_module_validate | | | -| | wasm_module_imports | | | -| | wasm_module_exports | | | -| instance | wasm_instance_new | instance | | -| | wasm_instance_delete | | | -| | wasm_instance_new_with_args\* | | | -| | wasm_instance_exports | | | -| | _vector methods_ | | | -| func | wasm_func_new | func | | -| | wasm_func_new_with_env | | | -| | wasm_func_delete | | | -| | wasm_func_type | | | -| | wasm_func_call | | | -| | wasm_func_param_arity | | | -| | wasm_func_result_arity | | | -| | _vector methods_ | | | -| global | wasm_global_new | global | | -| | wasm_global_delete | | | -| | wasm_global_type | | | -| | wasm_global_get | | | -| | wasm_global_set | | | -| | _vector methods_ | | | -| table | wasm_table_new | table | | -| | wasm_table_delete | | | -| | wasm_table_type | | | -| | wasm_table_get | | | -| | wasm_table_set | | | -| | wasm_table_size | | | -| | _vector methods_ | | | -| memory | wasm_memory_new | memory | | -| | wasm_memory_delete | | | -| | wasm_memory_type | | | -| | wasm_memory_data | | | -| | wasm_memory_data_size | | | -| | wasm_memory_size | | | -| | _vector methods_ | | | -| extern | wasm_extern_delete | extern | | -| | wasm_extern_as_XXX | | | -| | wasm_XXX_as_extern | | | -| | wasm_extern_kind | | | -| | wasm_extern_type | | | -| | _vector methods_ | | | +| WASM Concept | Procedural APIs | OOP APIs | OOP APIs methods | +| ------------ | -------------------------------- | ---------- | ---------------- | +| XXX_vec | wasm_xxx_vec_new | | list | +| | wasm_xxx_vec_new_uninitialized | | | +| | wasm_xxx_vec_new_empty | | | +| | wasm_xxx_vec_copy | | | +| | wasm_xxx_vec_delete | | | +| valtype | wasm_valtype_new | valtype | \_\_init\_\_ | +| | wasm_valtype_delete | | \_\_del\_\_ | +| | wasm_valtype_kind | | \_\_eq\_\_ | +| | wasm_valtype_copy | | | +| | _vector methods_ | | | +| functype | wasm_functype_new | functype | | +| | wasm_functype_delete | | | +| | wasm_functype_params | | | +| | wasm_functype_results | | | +| | wasm_functype_copy | | | +| | _vector methods_ | | | +| globaltype | wasm_globaltype_new | globaltype | \_\_init\_\_ | +| | wasm_globaltype_delete | | \_\_del\_\_ | +| | wasm_globaltype_content | | \_\_eq\_\_ | +| | wasm_globaltype_mutability | | | +| | wasm_globaltype_copy | | | +| | _vector methods_ | | | +| tabletype | wasm_tabletype_new | tabletype | \_\_init\_\_ | +| | wasm_tabletype_delete | | \_\_del\_\_ | +| | wasm_tabletype_element | | \_\_eq\_\_ | +| | wasm_tabletype_limits | | | +| | wasm_tabletype_copy | | | +| | _vector methods_ | | | +| memorytype | wasm_memorytype_new | memorytype | \_\_init\_\_ | +| | wasm_memorytype_delete | | \_\_del\_\_ | +| | wasm_memorytype_limits | | \_\_eq\_\_ | +| | wasm_memorytype_copy | | | +| | _vector methods_ | | | +| externtype | wasm_externtype_as_XXX | externtype | | +| | wasm_XXX_as_externtype | | | +| | wasm_externtype_copy | | | +| | wasm_externtype_delete | | | +| | wasm_externtype_kind | | | +| | _vector methods_ | | | +| importtype | wasm_importtype_new | importtype | | +| | wasm_importtype_delete | | | +| | wasm_importtype_module | | | +| | wasm_importtype_name | | | +| | wasm_importtype_type | | | +| | wasm_importtype_copy | | | +| | _vector methods_ | | | +| exportype | wasm_exporttype_new | exporttype | | +| | wasm_exporttype_delete | | | +| | wasm_exporttype_name | | | +| | wasm_exporttype_type | | | +| | wasm_exporttype_copy | | | +| | _vector methods_ | | | +| val | wasm_val_delete | val | | +| | wasm_val_copy | | | +| | _vector methods_ | | | +| frame | wasm_frame_delete | frame | | +| | wasm_frame_instance | | | +| | wasm_frame_func_index | | | +| | wasm_frame_func_offset | | | +| | wasm_frame_module_offset | | | +| | wasm_frame_copy | | | +| | _vector methods_ | | | +| trap | wasm_trap_new | trap | | +| | wasm_trap_delete | | | +| | wasm_trap_message | | | +| | wasm_trap_origin | | | +| | wasm_trap_trace | | | +| | _vector methods_ | | | +| foreign | wasm_foreign_new | foreign | | +| | wasm_foreign_delete | | | +| | _vector methods_ | | | +| engine | wasm_engine_new | engine | | +| | wasm_engine_new_with_args\* | | | +| | wasm_engine_new_with_config | | | +| | wasm_engine_delete | | | +| store | wasm_store_new | store | | +| | wasm_store_delete | | | +| | _vector methods_ | | | +| module | wasm_module_new | module | | +| | wasm_module_delete | | | +| | wasm_module_validate | | | +| | wasm_module_imports | | | +| | wasm_module_exports | | | +| instance | wasm_instance_new | instance | | +| | wasm_instance_delete | | | +| | wasm_instance_new_with_args\* | | | +| | wasm_instance_new_with_args_ex\* | | | +| | wasm_instance_exports | | | +| | _vector methods_ | | | +| func | wasm_func_new | func | | +| | wasm_func_new_with_env | | | +| | wasm_func_delete | | | +| | wasm_func_type | | | +| | wasm_func_call | | | +| | wasm_func_param_arity | | | +| | wasm_func_result_arity | | | +| | _vector methods_ | | | +| global | wasm_global_new | global | | +| | wasm_global_delete | | | +| | wasm_global_type | | | +| | wasm_global_get | | | +| | wasm_global_set | | | +| | _vector methods_ | | | +| table | wasm_table_new | table | | +| | wasm_table_delete | | | +| | wasm_table_type | | | +| | wasm_table_get | | | +| | wasm_table_set | | | +| | wasm_table_size | | | +| | _vector methods_ | | | +| memory | wasm_memory_new | memory | | +| | wasm_memory_delete | | | +| | wasm_memory_type | | | +| | wasm_memory_data | | | +| | wasm_memory_data_size | | | +| | wasm_memory_size | | | +| | _vector methods_ | | | +| extern | wasm_extern_delete | extern | | +| | wasm_extern_as_XXX | | | +| | wasm_XXX_as_extern | | | +| | wasm_extern_kind | | | +| | wasm_extern_type | | | +| | _vector methods_ | | | not supported _functions_ diff --git a/language-bindings/rust/README.md b/language-bindings/rust/README.md new file mode 100644 index 0000000000..06bdbd2fc7 --- /dev/null +++ b/language-bindings/rust/README.md @@ -0,0 +1 @@ +We use a separate repository to host the WAMR Rust SDK. Please refer to [WAMR Rust SDK](https://github.com/bytecodealliance/wamr-rust-sdk) for more details. diff --git a/product-mini/README.md b/product-mini/README.md index 8d7e799a43..18813bef57 100644 --- a/product-mini/README.md +++ b/product-mini/README.md @@ -312,7 +312,7 @@ WAMR provides some features which can be easily configured by passing options to ## Android -able to generate a shared library support Android platform. +Able to generate a shared library support Android platform. - need an [android SDK](https://developer.android.com/studio). Go and get the "Command line tools only" - look for a command named *sdkmanager* and download below components. version numbers might need to check and pick others - "build-tools;29.0.3" @@ -326,7 +326,7 @@ able to generate a shared library support Android platform. - export ANDROID_NDK_LATEST_HOME=/the/path/of/downloaded/sdk/ndk/2x.xxx/ - ready to go -Use such commands, you are able to compile with default configurations. Any compiling requirement should be satisfied by modifying product-mini/platforms/android/CMakeList.txt. For example, chaning ${WAMR_BUILD_TARGET} in CMakeList could get different libraries support different ABIs. +Use such commands, you are able to compile with default configurations. ``` shell $ cd product-mini/platforms/android/ @@ -339,6 +339,15 @@ $ # include/ includes all necesary head files $ # lib includes libiwasm.so ``` +To change the target architecture and ABI, you can define `WAMR_BUILD_TARGET` or `ANDROID_ABI` respectively. To build for [supported Android ABIs](https://developer.android.com/ndk/guides/abis#sa): + +```shell +$ cmake .. -DWAMR_BUILD_TARGET=X86_32 -DANDROID_ABI=x86 # 32-bit Intel CPU +$ cmake .. -DWAMR_BUILD_TARGET=X86_64 -DANDROID_ABI=x86_64 # 64-bit Intel CPU +$ cmake .. -DWAMR_BUILD_TARGET=ARMV7A -DANDROID_ABI=armeabi-v7a # 32-bit ARM CPU +$ cmake .. -DWAMR_BUILD_TARGET=AARCH64 -DANDROID_ABI=arm64-v8a # 64-bit ARM CPU +``` + ## NuttX WAMR is intergrated with NuttX, just enable the WAMR in Kconfig option (Application Configuration/Interpreters). diff --git a/product-mini/platforms/android/CMakeLists.txt b/product-mini/platforms/android/CMakeLists.txt index 638b6ab0df..db60e8649a 100644 --- a/product-mini/platforms/android/CMakeLists.txt +++ b/product-mini/platforms/android/CMakeLists.txt @@ -1,53 +1,59 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.4.1) +cmake_minimum_required (VERSION 3.14) -set (CMAKE_VERBOSE_MAKEFILE on) -set (CMAKE_BUILD_TYPE Release) +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") -# https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md#environment-variables-3 -set (CMAKE_TOOLCHAIN_FILE "$ENV{ANDROID_NDK_LATEST_HOME}/build/cmake/android.toolchain.cmake") -set (ANDROID_SDK $ENV{ANDROID_HOME}) -set (ANDROID_NDK $ENV{ANDROID_NDK_LATEST_HOME}) +if (NOT DEFINED WAMR_BUILD_TARGET) + message (FATAL_ERROR "WAMR_BUILD_TARGET isn't set") +endif () + +if (NOT (WAMR_BUILD_TARGET STREQUAL "X86_64" + OR WAMR_BUILD_TARGET STREQUAL "X86_32" + OR WAMR_BUILD_TARGET MATCHES "AARCH64.*" + OR WAMR_BUILD_TARGET MATCHES "ARM.*" + OR WAMR_BUILD_TARGET MATCHES "RISCV64.*")) + message (FATAL_ERROR "Unsupported build target platform ${WAMR_BUILD_TARGET}!") +endif () + +if (NOT DEFINED ANDROID_ABI) + if (WAMR_BUILD_TARGET STREQUAL "X86_64") + set (ANDROID_ABI "x86_64") + elseif (WAMR_BUILD_TARGET STREQUAL "X86_32") + set (ANDROID_ABI "x86") + elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*") + set (ANDROID_ABI "arm64-v8a") + elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") + set (ANDROID_ABI "armeabi-v7a") + else () + set (ANDROID_ABI "riscv64") + endif () +endif () + +if (NOT DEFINED ANDROID_LD) + set (ANDROID_LD lld) +endif () -set (ANDROID_ABI "x86") -set (ANDROID_LD lld) if (NOT DEFINED ANDROID_PLATFORM) set (ANDROID_PLATFORM 24) endif () -project (iwasm) +# https://android.googlesource.com/platform/ndk/+/master/build/cmake/android.toolchain.cmake +set (CMAKE_TOOLCHAIN_FILE "$ENV{ANDROID_NDK_LATEST_HOME}/build/cmake/android.toolchain.cmake") +set (ANDROID_SDK $ENV{ANDROID_HOME}) +set (ANDROID_NDK $ENV{ANDROID_NDK_LATEST_HOME}) -set (WAMR_BUILD_PLATFORM "android") -set (WAMR_BUILD_TARGET "X86_32") -set (WAMR_BUILD_TYPE Release) -set (WAMR_BUILD_INTERP 1) -set (WAMR_BUILD_AOT 1) -set (WAMR_BUILD_JIT 0) -set (WAMR_BUILD_LIBC_BUILTIN 1) -set (WAMR_BUILD_LIBC_WASI 1) +project (iwasm) -# Reset default linker flags -set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") +set (WAMR_BUILD_PLATFORM "android") -# Set WAMR_BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" -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") - 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_VERBOSE_MAKEFILE ON) if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) + set (CMAKE_BUILD_TYPE Release) endif () if (NOT DEFINED WAMR_BUILD_INTERP) @@ -55,6 +61,11 @@ if (NOT DEFINED WAMR_BUILD_INTERP) set (WAMR_BUILD_INTERP 1) endif () +if (NOT DEFINED WAMR_BUILD_FAST_INTERP) + # Enable fast interpreter + set (WAMR_BUILD_FAST_INTERP 1) +endif () + if (NOT DEFINED WAMR_BUILD_AOT) # Enable AOT by default. set (WAMR_BUILD_AOT 1) @@ -75,6 +86,21 @@ if (NOT DEFINED WAMR_BUILD_LIBC_WASI) set (WAMR_BUILD_LIBC_WASI 1) endif () +if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) + # Disable multiple modules by default + set (WAMR_BUILD_MULTI_MODULE 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD) + # Disable pthread library by default + set (WAMR_BUILD_LIB_PTHREAD 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS) + # Disable wasi threads library by default + set (WAMR_BUILD_LIB_WASI_THREADS 0) +endif() + set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) diff --git a/product-mini/platforms/esp-idf/build_and_run.sh b/product-mini/platforms/esp-idf/build_and_run.sh index f764a30130..7ce1b57a53 100755 --- a/product-mini/platforms/esp-idf/build_and_run.sh +++ b/product-mini/platforms/esp-idf/build_and_run.sh @@ -6,6 +6,7 @@ ESP32_TARGET="esp32" ESP32C3_TARGET="esp32c3" ESP32S3_TARGET="esp32s3" +ESP32C6_TARGET="esp32c6" usage () { @@ -15,6 +16,7 @@ usage () echo " $0 $ESP32_TARGET" echo " $0 $ESP32C3_TARGET" echo " $0 $ESP32S3_TARGET" + echo " $0 $ESP32C6_TARGET" exit 1 } diff --git a/product-mini/platforms/nuttx/CMakeLists.txt b/product-mini/platforms/nuttx/CMakeLists.txt new file mode 100644 index 0000000000..f83e799162 --- /dev/null +++ b/product-mini/platforms/nuttx/CMakeLists.txt @@ -0,0 +1,199 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# select platform configuration setting WAMR_BUILD_TARGET +set(WAMR_BUILD_PLATFORM nuttx) + +if(CONFIG_ARCH_ARMV6M) + set(WAMR_BUILD_TARGET THUMBV6M) +elseif(CONFIG_ARCH_ARMV7A) + set(WAMR_BUILD_TARGET THUMBV7) +elseif(CONFIG_ARCH_ARMV7M) + set(WAMR_BUILD_TARGET THUMBV7EM) +elseif(CONFIG_ARCH_ARMV8M) + set(WAMR_BUILD_TARGET THUMBV8M) +elseif(CONFIG_ARCH_X86) + set(WAMR_BUILD_TARGET X86_32) +elseif(CONFIG_ARCH_X86_64) + set(WAMR_BUILD_TARGET X86_64) +elseif(CONFIG_ARCH_XTENSA) + set(WAMR_BUILD_TARGET XTENSA) +elseif(CONFIG_ARCH_RV64GC OR CONFIG_ARCH_RV64) + set(WAMR_BUILD_TARGET RISCV64) +elseif(CONFIG_ARCH_RV32IM OR CONFIG_ARCH_RV32) + set(WAMR_BUILD_TARGET RISCV32) +elseif(CONFIG_ARCH_SIM) + if(CONFIG_SIM_M32 OR CONFIG_HOST_X86) + set(WAMR_BUILD_TARGET X86_32) + elseif(CONFIG_HOST_ARM) + set(WAMR_BUILD_TARGET ARM) + elseif(CONFIG_HOST_ARM64) + set(WAMR_BUILD_TARGET AARCH64) + else() + set(WAMR_BUILD_TARGET X86_64) + endif() + if(CONFIG_HOST_MACOS) + add_definitions(-DBH_PLATFORM_DARWIN) + endif() +endif() + +if(CONFIG_INTERPRETERS_WAMR_LOG) + add_definitions(-DWASM_ENABLE_LOG=1) +else() + add_definitions(-DWASM_ENABLE_LOG=0) +endif() + +if(CONFIG_INTERPRETERS_WAMR_AOT_WORD_ALIGN_READ) + add_definitions(-DWASM_ENABLE_WORD_ALIGN_READ=1) +else() + add_definitions(-DWASM_ENABLE_WORD_ALIGN_READ=0) +endif() + +if(CONFIG_INTERPRETERS_WAMR_STACK_GUARD_SIZE) + add_definitions(-DWASM_STACK_GUARD_SIZE=0) +else() + add_definitions( + -DWASM_STACK_GUARD_SIZE=${CONFIG_INTERPRETERS_WAMR_STACK_GUARD_SIZE}) +endif() + +if(CONFIG_INTERPRETERS_WAMR_MEMORY_TRACING) + add_definitions(-DWASM_ENABLE_MEMORY_TRACING=1) +else() + add_definitions(-DWASM_ENABLE_MEMORY_TRACING=0) +endif() + +if(CONFIG_INTERPRETERS_WAMR_SHARED_MEMORY) + set(WAMR_BUILD_SHARED_MEMORY 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_BULK_MEMORY) + set(WAMR_BUILD_BULK_MEMORY 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_AOT_STACK_FRAME) + set(WAMR_BUILD_AOT_STACK_FRAME 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_PERF_PROFILING) + set(WAMR_BUILD_PERF_PROFILING 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_GC) + set(WAMR_BUILD_GC 1) + set(WAMR_BUILD_STRINGREF 1) + set(WAMR_BUILD_REF_TYPES 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_GC_MANUALLY) + add_definitions(-DWASM_GC_MANUALLY=1) +else() + add_definitions(-DWASM_GC_MANUALLY=0) +endif() + +if(CONFIG_INTERPRETERS_WAMR_GC_PERF_PROFILING) + set(WAMR_BUILD_GC_PERF_PROFILING 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_ENABLE_EXCE_HANDLING) + set(WAMR_BUILD_EXCE_HANDLING 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_TAIL_CALL) + set(WAMR_BUILD_TAIL_CALL 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_MEMORY_PROFILING) + set(WAMR_BUILD_MEMORY_PROFILING 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_MULTI_MODULE) + set(WAMR_BUILD_MULTI_MODULE 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_LIB_PTHREAD_SEMAPHORE) + set(WAMR_BUILD_LIB_PTHREAD_SEMAPHORE 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_DISABLE_HW_BOUND_CHECK) + set(WAMR_DISABLE_HW_BOUND_CHECK 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_CUSTOM_NAME_SECTIONS) + set(WAMR_BUILD_CUSTOM_NAME_SECTION 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_GLOBAL_HEAP_POOL) + set(WAMR_BUILD_GLOBAL_HEAP_POOL 1) + math(EXPR _HEAP_SIZE_ + "${CONFIG_INTERPRETERS_WAMR_GLOBAL_HEAP_POOL_SIZE} * 1024") + set(WAMR_BUILD_GLOBAL_HEAP_SIZE ${_HEAP_SIZE_}) +endif() + +if(CONFIG_INTERPRETERS_WAMR_ENABLE_SPEC_TEST) + set(WAMR_BUILD_SPEC_TEST 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_REF_TYPES) + set(WAMR_BUILD_REF_TYPES 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_CLASSIC) + # include iwasm_interp.cmake + set(WAMR_BUILD_INTERP 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_FAST) + # enable iwasm_interp.cmake + set(WAMR_BUILD_FAST_INTERP 1) +endif() + +if((CONFIG_INTERPRETERS_WAMR_FAST OR CONFIG_INTERPRETERS_WAMR_CLASSIC) + AND CONFIG_INTERPRETERS_WAMR_MINILOADER) + # enable iwasm_interp.cmake + set(WAMR_BUILD_MINI_LOADER 1) +else() + set(WAMR_BUILD_MINI_LOADER 0) +endif() + +if(CONFIG_INTERPRETERS_WAMR_AOT) + # include iwasm_aot.cmake + set(WAMR_BUILD_AOT 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_DEBUG_INTERP) + # include debug_engine.cmake + set(WAMR_BUILD_DEBUG_INTERP 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN) + # include libc_builtin.cmake + set(WAMR_BUILD_LIBC_BUILTIN 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_LIBC_WASI) + # include libc_wasi.cmake + set(WAMR_BUILD_LIBC_WASI 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_THREAD_MGR) + # include thread_mgr.cmake + set(WAMR_BUILD_THREAD_MGR 1) +endif() + +if(CONFIG_INTERPRETERS_WAMR_LIB_PTHREAD) + # include lib_pthread.cmake + set(WAMR_BUILD_LIB_PTHREAD 1) +endif() + +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) + +# enable WAMR build system +include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +# NuttX wamr lib complie required: `WAMR_SOURCES` `WAMR_CFLAGS` `WAMR_INCDIRS` +# `WAMR_DEFINITIONS` +set(WAMR_SOURCES ${WAMR_RUNTIME_LIB_SOURCE}) +set(WAMR_CFLAGS -Wno-strict-prototypes -Wno-shadow -Wno-unused-variable + -Wno-int-conversion -Wno-implicit-function-declaration) +get_directory_property(WAMR_INCDIRS INCLUDE_DIRECTORIES) +get_directory_property(WAMR_DEFINITIONS COMPILE_DEFINITIONS) diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index df8fa2ece3..05772d2b66 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -681,7 +681,6 @@ main(int argc, char *argv[]) wasm_restore_file1 = file; } } - printf("restore file: %s, %s\n", wasm_restore_file, wasm_restore_file1); } #endif else if (!strncmp(argv[0], "--stack-size=", 13)) { @@ -703,7 +702,7 @@ main(int argc, char *argv[]) #endif #if WASM_ENABLE_GC != 0 else if (!strncmp(argv[0], "--gc-heap-size=", 15)) { - if (argv[0][21] == '\0') + if (argv[0][15] == '\0') return print_help(); gc_heap_size = atoi(argv[0] + 15); } @@ -879,7 +878,8 @@ main(int argc, char *argv[]) #if WASM_ENABLE_DEBUG_INTERP != 0 init_args.instance_port = instance_port; if (ip_addr) - strcpy(init_args.ip_addr, ip_addr); + /* ensure that init_args.ip_addr is null terminated */ + strncpy(init_args.ip_addr, ip_addr, sizeof(init_args.ip_addr) - 1); #endif /* initialize runtime environment */ diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 6461e9172e..35a4897217 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -464,7 +464,9 @@ main(int argc, char *argv[]) #if WASM_ENABLE_DEBUG_INTERP != 0 init_args.instance_port = instance_port; if (ip_addr) - strcpy(init_args.ip_addr, ip_addr); + /* ensure that init_args.ip_addr is null terminated */ + strncpy_s(init_args.ip_addr, sizeof(init_args.ip_addr) - 1, ip_addr, + strlen(ip_addr)); #endif /* initialize runtime environment */ diff --git a/product-mini/platforms/zephyr/simple/src/main.c b/product-mini/platforms/zephyr/simple/src/main.c index e70bb5caba..3b389826f1 100644 --- a/product-mini/platforms/zephyr/simple/src/main.c +++ b/product-mini/platforms/zephyr/simple/src/main.c @@ -65,14 +65,12 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_exec_env_t exec_env; unsigned argv[2] = { 0 }; - if (wasm_runtime_lookup_function(module_inst, "main", NULL) - || wasm_runtime_lookup_function(module_inst, "__main_argc_argv", - NULL)) { + if (wasm_runtime_lookup_function(module_inst, "main") + || wasm_runtime_lookup_function(module_inst, "__main_argc_argv")) { LOG_VERBOSE("Calling main function\n"); wasm_application_execute_main(module_inst, app_argc, app_argv); } - else if ((func = wasm_runtime_lookup_function(module_inst, "app_main", - NULL))) { + else if ((func = wasm_runtime_lookup_function(module_inst, "app_main"))) { exec_env = wasm_runtime_create_exec_env(module_inst, CONFIG_APP_HEAP_SIZE); if (!exec_env) { diff --git a/samples/README.md b/samples/README.md index 4113fcad14..872e1798f9 100644 --- a/samples/README.md +++ b/samples/README.md @@ -1,5 +1,5 @@ - # Samples + - [**basic**](./basic): Demonstrating how to use runtime exposed API's to call WASM functions, how to register native functions and call them, and how to call WASM function from native function. - **[file](./file/README.md)**: Demonstrating the supported file interaction API of WASI. This sample can also demonstrate the SGX IPFS (Intel Protected File System), enabling an enclave to seal and unseal data at rest. - **[multi-thread](./multi-thread/)**: Demonstrating how to run wasm application which creates multiple threads to execute wasm functions concurrently, and uses mutex/cond by calling pthread related API's. @@ -12,3 +12,4 @@ - **[native-lib](./native-lib/README.md)**: Demonstrating how to write required interfaces in native library, build it into a shared library and register the shared library to iwasm. - **[sgx-ra](./sgx-ra/README.md)**: Demonstrating how to execute Remote Attestation on SGX with [librats](https://github.com/inclavare-containers/librats), which enables mutual attestation with other runtimes or other entities that support librats to ensure that each is running within the TEE. - **[workload](./workload/README.md)**: Demonstrating how to build and run some complex workloads, e.g. tensorflow-lite, XNNPACK, wasm-av1, meshoptimizer and bwa. +- **[debug-tools](./debug-tools/README.md)**: Demonstrating how to symbolicate a stack trace. diff --git a/samples/basic/src/main.c b/samples/basic/src/main.c index ca580af330..406b2427cd 100644 --- a/samples/basic/src/main.c +++ b/samples/basic/src/main.c @@ -61,7 +61,7 @@ main(int argc, char *argv_main[]) wasm_function_inst_t func = NULL; wasm_function_inst_t func2 = NULL; char *native_buffer = NULL; - uint32_t wasm_buffer = 0; + uint64_t wasm_buffer = 0; RuntimeInitArgs init_args; memset(&init_args, 0, sizeof(RuntimeInitArgs)); @@ -149,8 +149,7 @@ main(int argc, char *argv_main[]) goto fail; } - if (!(func = wasm_runtime_lookup_function(module_inst, "generate_float", - NULL))) { + if (!(func = wasm_runtime_lookup_function(module_inst, "generate_float"))) { printf("The generate_float wasm function is not found.\n"); goto fail; } @@ -176,7 +175,7 @@ main(int argc, char *argv_main[]) ret_val); // Next we will pass a buffer to the WASM function - uint32 argv2[4]; + uint32 argv2[5]; // must allocate buffer from wasm instance memory space (never use pointer // from host runtime) @@ -185,12 +184,12 @@ main(int argc, char *argv_main[]) memcpy(argv2, &ret_val, sizeof(float)); // the first argument argv2[1] = wasm_buffer; // the second argument is the wasm buffer address - argv2[2] = 100; // the third argument is the wasm buffer size - argv2[3] = 3; // the last argument is the digits after decimal point for + argv2[3] = 100; // the third argument is the wasm buffer size + argv2[4] = 3; // the last argument is the digits after decimal point for // converting float to string - if (!(func2 = wasm_runtime_lookup_function(module_inst, "float_to_string", - NULL))) { + if (!(func2 = + wasm_runtime_lookup_function(module_inst, "float_to_string"))) { printf( "The wasm function float_to_string wasm function is not found.\n"); goto fail; @@ -208,7 +207,7 @@ main(int argc, char *argv_main[]) } wasm_function_inst_t func3 = - wasm_runtime_lookup_function(module_inst, "calculate", NULL); + wasm_runtime_lookup_function(module_inst, "calculate"); if (!func3) { printf("The wasm function calculate is not found.\n"); goto fail; @@ -231,7 +230,7 @@ main(int argc, char *argv_main[]) wasm_runtime_destroy_exec_env(exec_env); if (module_inst) { if (wasm_buffer) - wasm_runtime_module_free(module_inst, wasm_buffer); + wasm_runtime_module_free(module_inst, (uint64)wasm_buffer); wasm_runtime_deinstantiate(module_inst); } if (module) diff --git a/samples/debug-tools/CMakeLists.txt b/samples/debug-tools/CMakeLists.txt new file mode 100644 index 0000000000..5143462a31 --- /dev/null +++ b/samples/debug-tools/CMakeLists.txt @@ -0,0 +1,76 @@ +# Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +include(CheckPIESupported) + +project(debug_tools_sample) + +################ runtime settings ################ +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if (APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif () + +# Resetdefault linker flags +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch + +# 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 () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Release) +endif () + +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_LIBC_WASI 1) +set(WAMR_BUILD_FAST_INTERP 0) # Otherwise addresses don't match llvm-dwarfdump (addr2line) +set(WAMR_BUILD_AOT 1) +set(WAMR_BUILD_DUMP_CALL_STACK 1) # Otherwise stack trace is not printed (addr2line) + +# compiling and linking flags +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 () +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") + +# build out vmlib +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +################ wasm application ################ +add_subdirectory(wasm-apps) + +################ wamr runtime ################ +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +set (RUNTIME_SOURCE_ALL + ${CMAKE_CURRENT_LIST_DIR}/../../product-mini/platforms/linux/main.c + ${UNCOMMON_SHARED_SOURCE} +) +add_executable (iwasm ${RUNTIME_SOURCE_ALL}) +check_pie_supported() +set_target_properties (iwasm PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_link_libraries(iwasm vmlib -lm -ldl) diff --git a/samples/debug-tools/README.md b/samples/debug-tools/README.md new file mode 100644 index 0000000000..634d311970 --- /dev/null +++ b/samples/debug-tools/README.md @@ -0,0 +1,100 @@ +# "debug-tools" sample introduction + +Tool to symoblicate stack traces. When using wasm in production, debug info are usually stripped using tools like `wasm-opt`, to decrease the binary size. If a corresponding unstripped wasm file is kept, location information (function, file, line, column) can be retrieved from the stripped stack trace. + +## Build and run the sample + +### Generate the stack trace + +Build `iwasm` with `WAMR_BUILD_DUMP_CALL_STACK=1` and `WAMR_BUILD_FAST_INTERP=0` and the wasm file with debug info (e.g. `clang -g`). As it is done in [CMakeLists.txt](./CMakeLists.txt) and [wasm-apps/CMakeLists.txt](./wasm-apps/CMakeLists.txt) (look for `addr2line`): + +```bash +$ mkdir build && cd build +$ cmake .. +$ make +$ ./iwasm wasm-apps/trap.wasm +``` + +The output should be something like + +```text +#00: 0x0159 - $f5 +#01: 0x01b2 - $f6 +#02: 0x0200 - $f7 +#03: 0x026b - $f8 +#04: 0x236b - $f15 +#05: 0x011f - _start + +Exception: unreachable +``` + +Copy the stack trace printed to stdout into a separate file (`call_stack.txt`): + +```bash +$ ./iwasm wasm-apps/trap.wasm | grep "#" > call_stack.txt +``` + +Same for AOT. The AOT binary has to be generated using the `--enable-dump-call-stack` option of `wamrc`, as in [CMakeLists.txt](./wasm-apps/CMakeLists.txt). Then run: + +```bash +$ ./iwasm wasm-apps/trap.aot | grep "#" > call_stack.txt +``` + +### Symbolicate the stack trace + +Run the [addr2line](../../test-tools/addr2line/addr2line.py) script to symbolicate the stack trace: + +```bash +$ python3 ../../../test-tools/addr2line/addr2line.py \ + --wasi-sdk /opt/wasi-sdk \ + --wabt /opt/wabt \ + --wasm-file wasm-apps/trap.wasm \ + call_stack.txt +``` + +The output should be something like: + +```text +0: c + at wasm-micro-runtime/samples/debug-tools/wasm-apps/trap.c:5:1 +1: b + at wasm-micro-runtime/samples/debug-tools/wasm-apps/trap.c:11:12 +2: a + at wasm-micro-runtime/samples/debug-tools/wasm-apps/trap.c:17:12 +3: main + at wasm-micro-runtime/samples/debug-tools/wasm-apps/trap.c:24:5 +4: __main_void + at unknown:?:? +5: _start +``` + +If WAMR is run in fast interpreter mode (`WAMR_BUILD_FAST_INTERP=1`), addresses in the stack trace cannot be tracked back to location info. +If WAMR <= `1.3.2` is used, the stack trace does not contain addresses. +In those two cases, run the script with `--no-addr`: the line info returned refers to the start of the function + +```bash +$ python3 ../../../test-tools/addr2line/addr2line.py \ + --wasi-sdk /opt/wasi-sdk \ + --wabt /opt/wabt \ + --wasm-file wasm-apps/trap.wasm \ + call_stack.txt --no-addr +``` + +### Another approach + +If the wasm file is with "name" section, it is able to output function name in the stack trace. To achieve that, need to enable `WAMR_BUILD_LOAD_CUSTOM_SECTION` and `WAMR_BUILD_CUSTOM_NAME_SECTION`. If using .aot file, need to add `--emit-custom-sections=name` into wamrc command line options. + +Then the output should be something like + +```text +#00: 0x0159 - c +#01: 0x01b2 - b +#02: 0x0200 - a +#03: 0x026b - main +#04: 0x236b - __main_void +#05: 0x011f - _start + +Exception: unreachable +``` + +Also, it is able to use *addr2line.py* to add file and line info to the stack trace. diff --git a/samples/debug-tools/symbolicate.sh b/samples/debug-tools/symbolicate.sh new file mode 100644 index 0000000000..709622f03d --- /dev/null +++ b/samples/debug-tools/symbolicate.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -euox pipefail + +# Symbolicate .wasm +python3 ../../../test-tools/addr2line/addr2line.py \ + --wasi-sdk /opt/wasi-sdk \ + --wabt /opt/wabt \ + --wasm-file wasm-apps/trap.wasm \ + call_stack.txt + +# Symbolicate .wasm with `--no-addr` +python3 ../../../test-tools/addr2line/addr2line.py \ + --wasi-sdk /opt/wasi-sdk \ + --wabt /opt/wabt \ + --wasm-file wasm-apps/trap.wasm \ + call_stack.txt --no-addr + +# Symbolicate .aot +python3 ../../../test-tools/addr2line/addr2line.py \ + --wasi-sdk /opt/wasi-sdk \ + --wabt /opt/wabt \ + --wasm-file wasm-apps/trap.wasm \ + call_stack_aot.txt \ No newline at end of file diff --git a/samples/debug-tools/wasm-apps/CMakeLists.txt b/samples/debug-tools/wasm-apps/CMakeLists.txt new file mode 100644 index 0000000000..3ca8aff2a6 --- /dev/null +++ b/samples/debug-tools/wasm-apps/CMakeLists.txt @@ -0,0 +1,91 @@ +# Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +if (APPLE) + set (HAVE_FLAG_SEARCH_PATHS_FIRST 0) + set (CMAKE_C_LINK_FLAGS "") + set (CMAKE_CXX_LINK_FLAGS "") +endif () + +if (NOT DEFINED WASI_SDK_DIR) + set (WASI_SDK_DIR "/opt/wasi-sdk") +endif () + +if (DEFINED WASI_SYSROOT) + set (CMAKE_SYSROOT "${WASI_SYSROOT}") +endif () + +set (CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang") +set (CMAKE_ASM_COMPILER "${WASI_SDK_DIR}/bin/clang") +set (CMAKE_EXE_LINKER_FLAGS "-target wasm32-wasi") + +################ wabt and wamrc dependencies ################ +message(CHECK_START "Detecting WABT") +if(NOT (DEFINED WABT_DIR OR DEFINED CACHE{WABT_DIR})) + find_path(WABT_DIR + wabt + PATHS /opt + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH + ) + if(DEFINED WABT_DIR) + set(WABT_DIR ${WABT_DIR}/wabt) + endif() +endif() +if(WABT_DIR) + message(CHECK_PASS "found") +else() + message(CHECK_FAIL "not found") +endif() + +message(CHECK_START "Detecting WASM_OBJDUMP at ${WABT_DIR}") +find_program(WASM_OBJDUMP + wasm-objdump + PATHS "${WABT_DIR}/bin" + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH +) +if(WASM_OBJDUMP) + message(CHECK_PASS "found") +else() + message(CHECK_FAIL "not found") +endif() +if((NOT EXISTS ${WASM_OBJDUMP}) ) + message(FATAL_ERROR "Please make sure to have wasm-objdump under the path=${WABT_DIR}/bin ") +endif() + +set(WAMR_COMPILER_DIR ${CMAKE_CURRENT_LIST_DIR}/../../wamr-compiler/build) +message(CHECK_START "Detecting WAMR_COMPILER at ${WAMR_COMPILER_DIR}") +find_file(WAMR_COMPILER + wamrc + PATHS "${CMAKE_CURRENT_LIST_DIR}/../../../wamr-compiler/build" + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH +) +if(WAMR_COMPILER) + message(CHECK_PASS "found") +else() + message(CHECK_FAIL "not found") +endif() +if((NOT EXISTS ${WAMR_COMPILER}) ) + message(FATAL_ERROR "Please build wamrc under the path=${WAMR_ROOT_DIR}/wamr-compiler/") +endif() + +################ wasm and aot compilation ################ +function (compile_sample SOURCE_FILE) + get_filename_component (FILE_NAME ${SOURCE_FILE} NAME_WLE) + set (WASM_MODULE ${FILE_NAME}.wasm) + add_executable (${WASM_MODULE} ${SOURCE_FILE}) + + add_custom_target( + wasm_to_aot + ALL + DEPENDS ${WAMR_COMPILER} ${WASM_MODULE} + # Use --enable-dump-call-stack to generate stack trace (addr2line) + COMMAND ${WAMR_COMPILER} --size-level=0 --enable-dump-call-stack -o wasm-apps/trap.aot wasm-apps/trap.wasm + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) +endfunction () + +set(CMAKE_BUILD_TYPE Debug) # Otherwise no debug symbols (addr2line) +compile_sample(trap.c) \ No newline at end of file diff --git a/samples/debug-tools/wasm-apps/trap.c b/samples/debug-tools/wasm-apps/trap.c new file mode 100644 index 0000000000..364c430d19 --- /dev/null +++ b/samples/debug-tools/wasm-apps/trap.c @@ -0,0 +1,27 @@ +int +c(int n) +{ + __builtin_trap(); +} + +int +b(int n) +{ + n += 3; + return c(n); +} + +int +a(int n) +{ + return b(n); +} + +int +main(int argc, char **argv) +{ + int i = 5; + a(i); + + return 0; +} diff --git a/samples/inst-context/src/main.c b/samples/inst-context/src/main.c index 0d774735e4..f5068deffc 100644 --- a/samples/inst-context/src/main.c +++ b/samples/inst-context/src/main.c @@ -128,7 +128,7 @@ main(int argc, char *argv_main[]) } wasm_function_inst_t func3 = - wasm_runtime_lookup_function(module_inst, "calculate", NULL); + wasm_runtime_lookup_function(module_inst, "calculate"); if (!func3) { printf("The wasm function calculate is not found.\n"); goto fail; diff --git a/samples/linux-perf/CMakeLists.txt b/samples/linux-perf/CMakeLists.txt new file mode 100644 index 0000000000..e9882c835f --- /dev/null +++ b/samples/linux-perf/CMakeLists.txt @@ -0,0 +1,63 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project(linux_perf_sample) + +if(NOT CMAKE_HOST_LINUX) + message(FATAL_ERROR "This sample only works on linux") +endif() + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +set(CMAKE_CXX_STANDARD 17) + +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +find_package(WASISDK REQUIRED) + +################ runtime settings ################ +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +include(CheckPIESupported) + +# AOT and JIT byd default +set(WAMR_BUILD_AOT 1) +set(WAMR_BUILD_INTERP 0) +set(WAMR_BUILD_JIT 1) +# wasm32-wasi +set(WAMR_BUILD_LIBC_BUILTIN 0) +set(WAMR_BUILD_LIBC_WASI 1) +# mvp +set(WAMR_BUILD_BULK_MEMORY 1) +set(WAMR_BUILD_REF_TYPES 1) +set(WAMR_BUILD_SIMD 1) +set(WAMR_BUILD_TAIL_CALL 1) +# trap information +set(WAMR_BUILD_DUMP_CALL_STACK 1) +# linux perf +set(WAMR_BUILD_LINUX_PERF 1) +# +#set(WAMR_BUILD_THREAD_MGR 0) + +# vmlib +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib SHARED ${WAMR_RUNTIME_LIB_SOURCE}) +target_include_directories(vmlib INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include) +target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl) + +################ host ################ +add_executable(${PROJECT_NAME} host/demo.c) +target_link_libraries(${PROJECT_NAME} vmlib) + +################ aot + wasm ################ +include(ExternalProject) +ExternalProject_Add(wasm + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wasm" + CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/wasm -B build + -DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN} + BUILD_COMMAND ${CMAKE_COMMAND} --build build + INSTALL_COMMAND ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR} +) \ No newline at end of file diff --git a/samples/linux-perf/README.md b/samples/linux-perf/README.md new file mode 100644 index 0000000000..5a8dc578fb --- /dev/null +++ b/samples/linux-perf/README.md @@ -0,0 +1,90 @@ +# linux perf sample introduction + +This is a sample to show how to use the Linux perf tool to profile the execution of a WebAssembly application. And how to use the [Flamegraph](https://www.brendangregg.com/flamegraphs.html) tool to visualize the profiling result. + +## Build and run the sample + +There are two Wasm modules and their instance will be created and run in the sample. [The first module](./wasm/fib.c) is a simple Wasm module that calculates the Fibonacci number. [The second module](./wasm/ackermann.c) is a simple Wasm module that execute the Ackermann function. The target is enable to profile the execution of both two modules separately. + +```bash +$ cmake -S . -B build +$ cmake --build build +``` + +### Profile the execution + +```bash +$ cd build +$ perf record -k mono -g --output=perf.data -- ./linux_perf_sample +``` + +Enable to use `perf report --stdio` to do a quick analysis of the profiling result. + +### Visualize the profiling result + +Need to download Flamegraph tool from [Flamegraph](https://github.com/brendangregg/FlameGraph/releases/tag/v1.0) firstly. + +```bash +$ perf script > out.perf +$ ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded +$ ./FlameGraph/flamegraph.pl out.folded > perf.svg +``` + +In this result, you'll see two modules's profiling result and all wasm functions are named as "aot_func#N" which is a little hard to distinguish. + +![perf.png](./pics/perf.png) + +### Separate profiling result + +[process_folded_data.py](../../test-tools/flame-graph-helper/process_folded_data.py) is a script can a) translate "aot_func#N" into its original function name in name sections, b) separate the profiling result of different modules. + +In this sample, we want to separate `fib` and `ackermann` profiling data from _out.folded_. In [demo](host/demo.c), we decide to name the module of `fib1.wasm` as `fib2` and the module of `ackermann1.wasm` as `ackermann2`. + +```bash +$ python process_folded_data.py --wabt_home /opt/wabt --wasm_names fib2=./fib1.wasm,ackermann2=./ackermann1.wasm out.folded +-> write into out.fib2.translated +-> write into out.ackermann2.translated +-> write into out.translated +``` + +More scenarios: + +if only using one wasm during profiling, the script can be used like this: + +```bash +$ python process_folded_data.py --wabt_home /opt/wabt --wasm --folded +``` + +if only using one wasm during profiling and specify the module name via APIs, the script can be used like this: + +```bash +$ python process_folded_data.py --wabt_home /opt/wabt --wasm_names = --folded +``` + +if only using one wasm during profiling and specify the module name, which is same with the basename of wasm file, via APIs, the script can be used like this: + +```bash +$ python process_folded_data.py --wabt_home /opt/wabt --wasm --folded +``` + +if using multiple wasm during profiling and specify module names, which are same with basename of wasm files, via APIs, the script can be used like this: + +```bash +$ python process_folded_data.py --wabt_home /opt/wabt --wasm --wasm --wasm --folded +``` + +if using multiple wasm during profiling and specify module names via APIs, the script can be used like this: + +```bash +$ python process_folded_data.py --wabt_home /opt/wabt --wasm_names =,=,= --folded +``` + +Now we have two flame-graphs for two wasm modules: + +![fib.svg](./pics/perf.fib.svg) + +![ackermann.svg](./pics/perf.ackermann.svg) + +## Reference + +- [perf_tune](../../doc/perf_tune.md) diff --git a/samples/linux-perf/cmake/FindWAMRC.cmake b/samples/linux-perf/cmake/FindWAMRC.cmake new file mode 100644 index 0000000000..586263eddd --- /dev/null +++ b/samples/linux-perf/cmake/FindWAMRC.cmake @@ -0,0 +1,14 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +include(FindPackageHandleStandardArgs) + +find_file(WAMRC_BIN + NAMES wamrc + DOC "search wamrc" + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../../../wamr-compiler/build + REQUIRED +) + +find_package_handle_standard_args(WAMRC REQUIRED_VARS WAMRC_BIN) +mark_as_advanced(WAMRC_BIN) \ No newline at end of file diff --git a/samples/linux-perf/cmake/FindWASISDK.cmake b/samples/linux-perf/cmake/FindWASISDK.cmake new file mode 100644 index 0000000000..5cdfea41e4 --- /dev/null +++ b/samples/linux-perf/cmake/FindWASISDK.cmake @@ -0,0 +1,23 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +include(FindPackageHandleStandardArgs) + +file(GLOB WASISDK_SEARCH_PATH "/opt/wasi-sdk-*") +find_path(WASISDK_HOME + NAMES share/wasi-sysroot + PATHS ${WASISDK_SEARCH_PATH} + NO_DEFAULT_PATH + REQUIRED +) + +string(REGEX MATCH [0-9]+\.[0-9]+\.*[0-9]* WASISDK_VERSION ${WASISDK_HOME}) + +find_package_handle_standard_args(WASISDK REQUIRED_VARS WASISDK_HOME VERSION_VAR WASISDK_VERSION) + +if(WASISDK_FOUND) + set(WASISDK_CC_COMMAND ${WASISDK_HOME}/bin/clang) + set(WASISDK_CXX_COMMAND ${WASISDK_HOME}/bin/clang++) + set(WASISDK_TOOLCHAIN ${WASISDK_HOME}/share/cmake/wasi-sdk.cmake) + set(WASISDK_SYSROOT ${WASISDK_HOME}/share/wasi-sysroot) +endif() diff --git a/samples/linux-perf/host/demo.c b/samples/linux-perf/host/demo.c new file mode 100644 index 0000000000..8ea446ed4c --- /dev/null +++ b/samples/linux-perf/host/demo.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include +#include + +#include "wasm_c_api.h" + +#define own + +/* return a copy of the file stem of a file path */ +static own char * +stem(const char *file_path) +{ + char *base_name = basename(file_path); + char *s = strdup(base_name); + char *dot = strchr(s, '.'); + assert(dot); + *dot = '\0'; + return s; +} + +static void +guest_i32_to_wasm_i32_array(int *args, unsigned argc, wasm_val_t *data, + unsigned datac) +{ + for (unsigned i = 0; i < argc && i < datac; i++) { + memset(&data[i], 0, sizeof(wasm_val_t)); + data[i].kind = WASM_I32; + data[i].of.i32 = args[i]; + } +} + +int +load_run_wasm_file(wasm_engine_t *engine, const char *file_path, int *args, + unsigned argc) +{ + wasm_store_t *store = wasm_store_new(engine); + // Load binary. + printf("Loading binary...\n"); + FILE *file = fopen(file_path, "rb"); + assert(file); + + int ret = fseek(file, 0L, SEEK_END); + assert(ret == 0); + + long file_size = ftell(file); + assert(file_size != -1); + + ret = fseek(file, 0L, SEEK_SET); + assert(ret == 0); + + wasm_byte_vec_t binary = { 0 }; + wasm_byte_vec_new_uninitialized(&binary, file_size); + + size_t nread = fread(binary.data, file_size, 1, file); + fclose(file); + + // Compile. + printf("Compiling module...\n"); + + // Use its file name as the module name + char *file_name = stem(file_path); + assert(file_name); + + LoadArgs load_args = { 0 }; + load_args.name = file_name; + own wasm_module_t *module = wasm_module_new_ex(store, &binary, &load_args); + wasm_byte_vec_delete(&binary); + assert(module); + + // Use export type to find the function index to call later + wasm_exporttype_vec_t export_types = { 0 }; + wasm_module_exports(module, &export_types); + int func_to_call = -1; + for (unsigned i = 0; i < export_types.num_elems; i++) { + const wasm_name_t *name = wasm_exporttype_name(export_types.data[i]); + if (strncmp(name->data, "run", 3) == 0) { + func_to_call = i; + break; + } + } + assert(func_to_call != -1); + + // Instantiate. + printf("Instantiating module...\n"); + wasm_extern_vec_t imports = WASM_EMPTY_VEC; + own wasm_instance_t *instance = wasm_instance_new_with_args( + store, module, &imports, NULL, 16 * 1024 * 1024, 1 * 1024 * 1024); + assert(instance); + + // Extract export. + printf("Extracting export...\n"); + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + assert(exports.size); + + assert(wasm_extern_kind(exports.data[func_to_call]) == WASM_EXTERN_FUNC); + const wasm_func_t *run_func = + wasm_extern_as_func(exports.data[func_to_call]); + assert(run_func); + + wasm_module_delete(module); + wasm_instance_delete(instance); + + // Call. + printf("Calling export...\n"); + wasm_val_t as[4] = { 0 }; + guest_i32_to_wasm_i32_array(args, argc, as, 4); + + wasm_val_vec_t params = WASM_ARRAY_VEC(as); + wasm_val_t rs[1] = { WASM_I32_VAL(0) }; + wasm_val_vec_t results = WASM_ARRAY_VEC(rs); + wasm_trap_t *trap = wasm_func_call(run_func, ¶ms, &results); + assert(!trap); + + wasm_extern_vec_delete(&exports); + free(file_name); + wasm_store_delete(store); + + { + nread = nread; + ret = ret; + trap = trap; + } + return 0; +} + +void * +load_run_fib_wasm(void *arg) +{ + wasm_engine_t *engine = (wasm_engine_t *)arg; + int args[] = { 40 }; + load_run_wasm_file(engine, "./fib1.wasm", args, 1); + return NULL; +} + +void * +load_run_fib_aot(void *arg) +{ + wasm_engine_t *engine = (wasm_engine_t *)arg; + int args[] = { 40 }; + load_run_wasm_file(engine, "./fib2.aot", args, 1); + return NULL; +} + +void * +load_run_ackermann_wasm(void *arg) +{ + wasm_engine_t *engine = (wasm_engine_t *)arg; + int args[] = { 3, 12 }; + load_run_wasm_file(engine, "./ackermann1.wasm", args, 2); + return NULL; +} + +void * +load_run_ackermann_aot(void *arg) +{ + wasm_engine_t *engine = (wasm_engine_t *)arg; + int args[] = { 3, 12 }; + load_run_wasm_file(engine, "./ackermann2.aot", args, 2); + return NULL; +} + +int +main(int argc, const char *argv[]) +{ + // Initialize. + printf("Initializing...\n"); + wasm_config_t *config = wasm_config_new(); + wasm_config_set_linux_perf_opt(config, true); + wasm_engine_t *engine = wasm_engine_new_with_config(config); + + pthread_t tid[4] = { 0 }; + /* FIXME: uncomment when it is able to run two modules with llvm-jit */ + // pthread_create(&tid[0], NULL, load_run_fib_wasm, (void *)engine); + // pthread_create(&tid[2], NULL, load_run_ackermann_wasm, (void *)engine); + + pthread_create(&tid[1], NULL, load_run_fib_aot, (void *)engine); + pthread_create(&tid[3], NULL, load_run_ackermann_aot, (void *)engine); + + for (unsigned i = 0; i < sizeof(tid) / sizeof(tid[0]); i++) + pthread_join(tid[i], NULL); + + // Shut down. + printf("Shutting down...\n"); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; +} diff --git a/samples/linux-perf/pics/perf.ackermann.svg b/samples/linux-perf/pics/perf.ackermann.svg new file mode 100644 index 0000000000..c2e1d87472 --- /dev/null +++ b/samples/linux-perf/pics/perf.ackermann.svg @@ -0,0 +1,1349 @@ + + + + + + + + + + + + + + +Flame Graph + +Reset Zoom +Search +ic + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +load_run_wasm_file (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +invoke_ii_i (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +load_run_ackermann_aot (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] run (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +wasm_runtime_call_wasm (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +all (11,485,868,643 samples, 100%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +aot_call_function (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +linux_perf_samp (11,485,868,643 samples, 100.00%) +linux_perf_samp + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +wasm_func_call (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +invoke_native_with_hw_bound_check (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +start_thread (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (11,484,299,081 samples, 99.99%) +[Wasm] [ackermann2] ackermann + + +[Wasm] [ackermann2] ackermann (1,569,562 samples, 0.01%) + + + + diff --git a/samples/linux-perf/pics/perf.fib.svg b/samples/linux-perf/pics/perf.fib.svg new file mode 100644 index 0000000000..a1db059a7a --- /dev/null +++ b/samples/linux-perf/pics/perf.fib.svg @@ -0,0 +1,605 @@ + + + + + + + + + + + + + + +Flame Graph + +Reset Zoom +Search +ic + + + +[Wasm] [fib2] fibonacci (1,321,095,222 samples, 93.80%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (382,407,564 samples, 27.15%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (15,340,273 samples, 1.09%) + + + +[Wasm] [fib2] fibonacci (1,359,552,763 samples, 96.53%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,408,481,525 samples, 100.00%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (27,274,310 samples, 1.94%) +[.. + + +[Wasm] [fib2] fibonacci (62,450,767 samples, 4.43%) +[Wasm.. + + +[Wasm] [fib2] fibonacci (1,408,481,525 samples, 100.00%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,388,674,508 samples, 98.59%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,170,751,868 samples, 83.12%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,408,481,525 samples, 100.00%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (120,820,158 samples, 8.58%) +[Wasm] [fib2.. + + +invoke_i_i (1,408,481,525 samples, 100.00%) +invoke_i_i + + +[Wasm] [fib2] fibonacci (1,375,872,224 samples, 97.68%) +[Wasm] [fib2] fibonacci + + +load_run_wasm_file (1,408,481,525 samples, 100.00%) +load_run_wasm_file + + +load_run_fib_aot (1,408,481,525 samples, 100.00%) +load_run_fib_aot + + +[Wasm] [fib2] run (1,408,481,525 samples, 100.00%) +[Wasm] [fib2] run + + +[Wasm] [fib2] fibonacci (42,420,273 samples, 3.01%) +[Wa.. + + +[Wasm] [fib2] fibonacci (1,266,323,684 samples, 89.91%) +[Wasm] [fib2] fibonacci + + +linux_perf_samp (1,408,481,525 samples, 100.00%) +linux_perf_samp + + +[Wasm] [fib2] fibonacci (280,259,464 samples, 19.90%) +[Wasm] [fib2] fibonacci + + +start_thread (1,408,481,525 samples, 100.00%) +start_thread + + +[Wasm] [fib2] fibonacci (2,334,521 samples, 0.17%) + + + +[Wasm] [fib2] fibonacci (666,394,609 samples, 47.31%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (943,121,736 samples, 66.96%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,169,581 samples, 0.08%) + + + +[Wasm] [fib2] fibonacci (1,169,581 samples, 0.08%) + + + +[Wasm] [fib2] fibonacci (194,755,877 samples, 13.83%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,406,148,966 samples, 99.83%) +[Wasm] [fib2] fibonacci + + +all (1,408,481,525 samples, 100%) + + + +wasm_func_call (1,408,481,525 samples, 100.00%) +wasm_func_call + + +[Wasm] [fib2] fibonacci (5,943,602 samples, 0.42%) + + + +[Wasm] [fib2] fibonacci (1,408,481,525 samples, 100.00%) +[Wasm] [fib2] fibonacci + + +wasm_runtime_call_wasm (1,408,481,525 samples, 100.00%) +wasm_runtime_call_wasm + + +[Wasm] [fib2] fibonacci (1,401,486,191 samples, 99.50%) +[Wasm] [fib2] fibonacci + + +aot_call_function (1,408,481,525 samples, 100.00%) +aot_call_function + + +[Wasm] [fib2] fibonacci (531,941,563 samples, 37.77%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,406,148,966 samples, 99.83%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,061,055,435 samples, 75.33%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,408,481,525 samples, 100.00%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (1,403,816,880 samples, 99.67%) +[Wasm] [fib2] fibonacci + + +[Wasm] [fib2] fibonacci (800,646,766 samples, 56.84%) +[Wasm] [fib2] fibonacci + + +invoke_native_with_hw_bound_check (1,408,481,525 samples, 100.00%) +invoke_native_with_hw_bound_check + + + diff --git a/samples/linux-perf/pics/perf.png b/samples/linux-perf/pics/perf.png new file mode 100755 index 0000000000..fc4c0930fc Binary files /dev/null and b/samples/linux-perf/pics/perf.png differ diff --git a/samples/linux-perf/wasm/CMakeLists.txt b/samples/linux-perf/wasm/CMakeLists.txt new file mode 100644 index 0000000000..8d36e28dfb --- /dev/null +++ b/samples/linux-perf/wasm/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project(linux_perf_sample_wasm) + +include(CMakePrintHelpers) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake) +find_package(WAMRC REQUIRED) + +################ wasm ################ +add_executable(fib_wasm fib.c) +set_target_properties(fib_wasm PROPERTIES SUFFIX .wasm) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fib_wasm.wasm DESTINATION . RENAME fib1.wasm) + +add_executable(ackermann_wasm ackermann.c) +set_target_properties(ackermann_wasm PROPERTIES SUFFIX .wasm) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ackermann_wasm.wasm DESTINATION . RENAME ackermann1.wasm) + + +################ aot ################ +add_custom_target(fib_aot + ALL + COMMAND ${WAMRC_BIN} --enable-linux-perf -o fib2.aot fib_wasm.wasm + DEPENDS fib_wasm + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fib2.aot DESTINATION .) + +add_custom_target(ackermann_aot + ALL + COMMAND ${WAMRC_BIN} --enable-linux-perf -o ackermann2.aot ackermann_wasm.wasm + DEPENDS ackermann_wasm + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ackermann2.aot DESTINATION .) diff --git a/samples/linux-perf/wasm/ackermann.c b/samples/linux-perf/wasm/ackermann.c new file mode 100644 index 0000000000..d6eb4346ff --- /dev/null +++ b/samples/linux-perf/wasm/ackermann.c @@ -0,0 +1,38 @@ +#include + +// Ackermann function +unsigned long +ackermann(unsigned long m, unsigned long n) +{ + if (m == 0) { + return n + 1; + } + else if (n == 0) { + return ackermann(m - 1, 1); + } + else { + return ackermann(m - 1, ackermann(m, n - 1)); + } +} + +__attribute__((export_name("run"))) int +run(int m, int n) +{ + int result = ackermann(m, n); + printf("ackermann(%d, %d)=%d\n", m, n, result); + return result; +} + +int +main() +{ + unsigned long m, n, result; + + // Example usage: + m = 3; + n = 2; + result = ackermann(m, n); + printf("Ackermann(%lu, %lu) = %lu\n", m, n, result); + + return 0; +} diff --git a/samples/linux-perf/wasm/fib.c b/samples/linux-perf/wasm/fib.c new file mode 100644 index 0000000000..cb928f65d0 --- /dev/null +++ b/samples/linux-perf/wasm/fib.c @@ -0,0 +1,32 @@ +#include +#include + +int +fibonacci(int n) +{ + if (n <= 0) + return 0; + + if (n == 1) + return 1; + + return fibonacci(n - 1) + fibonacci(n - 2); +} + +__attribute__((export_name("run"))) int +run(int n) +{ + int result = fibonacci(n); + printf("fibonacci(%d)=%d\n", n, result); + return result; +} + +int +main(int argc, char **argv) +{ + int n = atoi(argv[1]); + + printf("fibonacci(%d)=%d\n", n, fibonacci(n)); + + return 0; +} diff --git a/samples/native-lib/test_hello2.c b/samples/native-lib/test_hello2.c index 5dae79ca48..53ea663a72 100644 --- a/samples/native-lib/test_hello2.c +++ b/samples/native-lib/test_hello2.c @@ -30,12 +30,14 @@ test_hello2_wrapper(wasm_exec_env_t exec_env, uint32_t nameaddr, wasm_runtime_free(p); wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env); - if (!wasm_runtime_validate_app_str_addr(inst, nameaddr) - || !wasm_runtime_validate_app_addr(inst, resultaddr, resultlen)) { + if (!wasm_runtime_validate_app_str_addr(inst, (uint64_t)nameaddr) + || !wasm_runtime_validate_app_addr(inst, (uint64_t)resultaddr, + (uint64_t)resultlen)) { return -1; } - const char *name = wasm_runtime_addr_app_to_native(inst, nameaddr); - char *result = wasm_runtime_addr_app_to_native(inst, resultaddr); + const char *name = + wasm_runtime_addr_app_to_native(inst, (uint64_t)nameaddr); + char *result = wasm_runtime_addr_app_to_native(inst, (uint64_t)resultaddr); return snprintf(result, resultlen, "Hello, %s. This is %s! Your wasm_module_inst_t is %p.\n", name, __func__, inst); diff --git a/samples/ref-types/src/hello.c b/samples/ref-types/src/hello.c index 0ee1aee88e..8a6f968c3a 100644 --- a/samples/ref-types/src/hello.c +++ b/samples/ref-types/src/hello.c @@ -234,19 +234,19 @@ main(int argc, char *argv[]) /* lookup function instance */ if (!(wasm_cmp_externref_ptr = wasm_runtime_lookup_function( - wasm_module_inst, "cmp-externref", NULL))) { + wasm_module_inst, "cmp-externref"))) { printf("%s\n", "lookup function cmp-externref failed"); goto fail; } if (!(wasm_get_externref_ptr = wasm_runtime_lookup_function( - wasm_module_inst, "get-externref", NULL))) { + wasm_module_inst, "get-externref"))) { printf("%s\n", "lookup function get-externref failed"); goto fail; } if (!(wasm_set_externref_ptr = wasm_runtime_lookup_function( - wasm_module_inst, "set-externref", NULL))) { + wasm_module_inst, "set-externref"))) { printf("%s\n", "lookup function set-externref failed"); goto fail; } diff --git a/samples/shared-module/src/main.c b/samples/shared-module/src/main.c index ebea0c6bfd..7efbc4d0b9 100644 --- a/samples/shared-module/src/main.c +++ b/samples/shared-module/src/main.c @@ -104,15 +104,15 @@ main(int argc, char *argv_main[]) goto fail; } - func_test_data_drop[i] = wasm_runtime_lookup_function( - module_inst[i], name_test_data_drop, NULL); + func_test_data_drop[i] = + wasm_runtime_lookup_function(module_inst[i], name_test_data_drop); if (!func_test_data_drop[i]) { printf("The wasm function %s is not found.\n", name_test_data_drop); goto fail; } - func_test_elem_drop[i] = wasm_runtime_lookup_function( - module_inst[i], name_test_elem_drop, NULL); + func_test_elem_drop[i] = + wasm_runtime_lookup_function(module_inst[i], name_test_elem_drop); if (!func_test_elem_drop[i]) { printf("The wasm function %s is not found.\n", name_test_elem_drop); goto fail; diff --git a/samples/spawn-thread/src/main.c b/samples/spawn-thread/src/main.c index 9501ae4c03..ecdf679a2b 100644 --- a/samples/spawn-thread/src/main.c +++ b/samples/spawn-thread/src/main.c @@ -29,7 +29,7 @@ thread(void *arg) return NULL; } - func = wasm_runtime_lookup_function(module_inst, "sum", NULL); + func = wasm_runtime_lookup_function(module_inst, "sum"); if (!func) { printf("failed to lookup function sum"); wasm_runtime_destroy_thread_env(); @@ -57,7 +57,7 @@ wamr_thread_cb(wasm_exec_env_t exec_env, void *arg) wasm_function_inst_t func; uint32 argv[2]; - func = wasm_runtime_lookup_function(module_inst, "sum", NULL); + func = wasm_runtime_lookup_function(module_inst, "sum"); if (!func) { printf("failed to lookup function sum"); return NULL; @@ -133,7 +133,7 @@ main(int argc, char *argv[]) goto fail4; } - func = wasm_runtime_lookup_function(wasm_module_inst, "sum", NULL); + func = wasm_runtime_lookup_function(wasm_module_inst, "sum"); if (!func) { printf("failed to lookup function sum"); goto fail5; diff --git a/samples/terminate/src/main.c b/samples/terminate/src/main.c index 4885b0b11b..fb0842a2b5 100644 --- a/samples/terminate/src/main.c +++ b/samples/terminate/src/main.c @@ -39,7 +39,7 @@ runner_with_spawn_exec_env(void *vp) wasm_function_inst_t func; bool ok = wasm_runtime_init_thread_env(); assert(ok); - func = wasm_runtime_lookup_function(inst, "block_forever", NULL); + func = wasm_runtime_lookup_function(inst, "block_forever"); assert(func != NULL); wasm_runtime_call_wasm(env, func, 0, NULL); wasm_runtime_destroy_spawned_exec_env(env); diff --git a/samples/wasm-c-api/src/hello.c b/samples/wasm-c-api/src/hello.c index 966e141d71..6650f3485d 100644 --- a/samples/wasm-c-api/src/hello.c +++ b/samples/wasm-c-api/src/hello.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -81,6 +82,8 @@ int main(int argc, const char* argv[]) { wasm_byte_vec_delete(&binary); + assert(wasm_module_set_name(module, "hello")); + // Create external print functions. printf("Creating callback...\n"); own wasm_functype_t* hello_type = wasm_functype_new_0_0(); @@ -117,6 +120,12 @@ int main(int argc, const char* argv[]) { return 1; } + { + const char* name = wasm_module_get_name(module); + assert(strncmp(name, "hello", 5) == 0); + printf("> removing module %s \n", name); + } + wasm_module_delete(module); wasm_instance_delete(instance); diff --git a/test-tools/addr2line/addr2line.py b/test-tools/addr2line/addr2line.py index 8ef3566e8d..594f8e19f8 100644 --- a/test-tools/addr2line/addr2line.py +++ b/test-tools/addr2line/addr2line.py @@ -12,9 +12,7 @@ import sys """ -it is a tool to transfer the address, which is from a call-stack dump generated by iwasm, to line info for a wasm file. - -> in order to generate the call-stack dump, you can use the following command: `$ cmake -DWAMR_BUILD_DUMP_CALL_STACK=1 ...` +This is a tool to convert addresses, which are from a call-stack dump generated by iwasm, into line info for a wasm file. When a wasm file is compiled with debug info, it is possible to transfer the address to line info. @@ -28,24 +26,62 @@ ``` - store the call-stack dump into a file, e.g. call_stack.txt -- run the following command to transfer the address to line info: +- run the following command to convert the address into line info: ``` $ cd test-tools/addr2line - $ python3 addr2line.py --wasi-sdk --wasm-file call_stack.txt + $ python3 addr2line.py --wasi-sdk --wabt --wasm-file call_stack.txt ``` -- the script will use *llvm-dwarfdump* to lookup the line info for each address in the call-stack dump. -- the output will be: + The script will use *wasm-objdump* in wabt to transform address, then use *llvm-dwarfdump* to lookup the line info for each address + in the call-stack dump. +- if addresses are not available in the stack trace (i.e. iwasm <= 1.3.2) or iwasm is used in fast interpreter mode, + run the following command to convert the function index into line info (passing the `--no-addr` option): ``` - #00: 0x0a04 - $f18 - #01: 0x08e4 - $f11 (FILE:quicksort.c LINE: 176 COLUMN: 11 FUNC:Quick) - #02: 0x096f - $f12 (FILE:quicksort.c LINE: 182 COLUMN: 3 FUNC:main) - #03: 0x01aa - _start + $ python3 addr2line.py --wasi-sdk --wabt --wasm-file call_stack.txt --no-addr ``` - + The script will use *wasm-objdump* in wabt to get the function names corresponding to function indexes, then use *llvm-dwarfdump* to lookup the line info for each + function index in the call-stack dump. """ -def get_line_info(dwarf_dump: Path, wasm_file: Path, offset: int) -> str: +def get_code_section_start(wasm_objdump: Path, wasm_file: Path) -> int: + """ + Find the start offset of Code section in a wasm file. + + if the code section header likes: + Code start=0x0000017c end=0x00004382 (size=0x00004206) count: 47 + + the start offset is 0x0000017c + """ + cmd = f"{wasm_objdump} -h {wasm_file}" + p = subprocess.run( + shlex.split(cmd), + check=True, + capture_output=True, + text=True, + universal_newlines=True, + ) + outputs = p.stdout.split(os.linesep) + + # if there is no .debug section, return -1 + for line in outputs: + line = line.strip() + if ".debug_info" in line: + break + else: + print(f"No .debug_info section found {wasm_file}") + return -1 + + for line in outputs: + line = line.strip() + if "Code" in line: + return int(line.split()[1].split("=")[1], 16) + + return -1 + + +def get_line_info_from_function_addr( + dwarf_dump: Path, wasm_file: Path, offset: int +) -> tuple[str, str, str, str]: """ Find the location info of a given offset in a wasm file. """ @@ -59,29 +95,72 @@ def get_line_info(dwarf_dump: Path, wasm_file: Path, offset: int) -> str: ) outputs = p.stdout.split(os.linesep) - capture_name = False + function_name, function_file = "", "unknown" + function_line, function_column = "?", "?" + for line in outputs: line = line.strip() - if "DW_TAG_subprogram" in line: - capture_name = True - continue + if "DW_AT_name" in line: + function_name = get_dwarf_tag_value("DW_AT_name", line) - if "DW_AT_name" in line and capture_name: - PATTERN = r"DW_AT_name\s+\(\"(\S+)\"\)" - m = re.match(PATTERN, line) - assert m is not None + if "DW_AT_decl_file" in line: + function_file = get_dwarf_tag_value("DW_AT_decl_file", line) - function_name = m.groups()[0] + if "Line info" in line: + _, function_line, function_column = parse_line_info(line) - if line.startswith("Line info"): - location = line - return (function_name, location) + return (function_name, function_file, function_line, function_column) - return () +def get_dwarf_tag_value(tag: str, line: str) -> str: + # Try extracting value as string + STR_PATTERN = rf"{tag}\s+\(\"(.*)\"\)" + m = re.match(STR_PATTERN, line) + if m: + return m.groups()[0] -def parse_line_info(line_info: str) -> (): + # Try extracting value as integer + INT_PATTERN = rf"{tag}\s+\((\d+)\)" + m = re.match(INT_PATTERN, line) + return m.groups()[0] + + +def get_line_info_from_function_name( + dwarf_dump: Path, wasm_file: Path, function_name: str +) -> tuple[str, str, str]: + """ + Find the location info of a given function in a wasm file. + """ + cmd = f"{dwarf_dump} --name={function_name} {wasm_file}" + p = subprocess.run( + shlex.split(cmd), + check=False, + capture_output=True, + text=True, + universal_newlines=True, + ) + outputs = p.stdout.split(os.linesep) + + function_name, function_file = "", "unknown" + function_line = "?" + + for line in outputs: + line = line.strip() + + if "DW_AT_name" in line: + function_name = get_dwarf_tag_value("DW_AT_name", line) + + if "DW_AT_decl_file" in line: + function_file = get_dwarf_tag_value("DW_AT_decl_file", line) + + if "DW_AT_decl_line" in line: + function_line = get_dwarf_tag_value("DW_AT_decl_line", line) + + return (function_name, function_file, function_line) + + +def parse_line_info(line_info: str) -> tuple[str, str, str]: """ line_info -> [file, line, column] """ @@ -93,51 +172,152 @@ def parse_line_info(line_info: str) -> (): return (file, int(line), int(column)) -def parse_call_stack_line(line: str) -> (): +def parse_call_stack_line(line: str) -> tuple[str, str, str]: """ + New format (WAMR > 1.3.2): #00: 0x0a04 - $f18 => (00, 0x0a04, $f18) + Old format: + #00 $f18 => (00, _, $f18) + Text format (-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1 -DWAMR_BUILD_CUSTOM_NAME_SECTION=1): + #02: 0x0200 - a => (02, 0x0200, a) + _start (always): + #05: 0x011f - _start => (05, 0x011f, _start) """ + + # New format and Text format and _start PATTERN = r"#([0-9]+): 0x([0-9a-f]+) - (\S+)" m = re.match(PATTERN, line) - return m.groups() if m else None + if m is not None: + return m.groups() + + # Old format + PATTERN = r"#([0-9]+) (\S+)" + m = re.match(PATTERN, line) + if m is not None: + return (m.groups()[0], None, m.groups()[1]) + + return None + + +def parse_module_functions(wasm_objdump: Path, wasm_file: Path) -> dict[str, str]: + function_index_to_name = {} + + cmd = f"{wasm_objdump} -x {wasm_file} --section=function" + p = subprocess.run( + shlex.split(cmd), + check=True, + capture_output=True, + text=True, + universal_newlines=True, + ) + outputs = p.stdout.split(os.linesep) + + for line in outputs: + if not f"func[" in line: + continue + + PATTERN = r".*func\[([0-9]+)\].*<(.*)>" + m = re.match(PATTERN, line) + assert m is not None + + index = m.groups()[0] + name = m.groups()[1] + function_index_to_name[index] = name + + return function_index_to_name + + +def demangle(cxxfilt: Path, function_name: str) -> str: + cmd = f"{cxxfilt} -n {function_name}" + p = subprocess.run( + shlex.split(cmd), + check=True, + capture_output=True, + text=True, + universal_newlines=True, + ) + return p.stdout.strip() def main(): parser = argparse.ArgumentParser(description="addr2line for wasm") parser.add_argument("--wasi-sdk", type=Path, help="path to wasi-sdk") + parser.add_argument("--wabt", type=Path, help="path to wabt") parser.add_argument("--wasm-file", type=Path, help="path to wasm file") parser.add_argument("call_stack_file", type=Path, help="path to a call stack file") + parser.add_argument( + "--no-addr", + action="store_true", + help="use call stack without addresses or from fast interpreter mode", + ) args = parser.parse_args() + wasm_objdump = args.wabt.joinpath("bin/wasm-objdump") + assert wasm_objdump.exists() + llvm_dwarf_dump = args.wasi_sdk.joinpath("bin/llvm-dwarfdump") assert llvm_dwarf_dump.exists() + llvm_cxxfilt = args.wasi_sdk.joinpath("bin/llvm-cxxfilt") + assert llvm_cxxfilt.exists() + + code_section_start = get_code_section_start(wasm_objdump, args.wasm_file) + if code_section_start == -1: + return -1 + + function_index_to_name = parse_module_functions(wasm_objdump, args.wasm_file) + assert args.call_stack_file.exists() with open(args.call_stack_file, "rt", encoding="ascii") as f: - for line in f: + for i, line in enumerate(f): line = line.strip() - if not line: continue splitted = parse_call_stack_line(line) if splitted is None: - print(line) - continue - - _, offset, _ = splitted - - offset = int(offset, 16) - line_info = get_line_info(llvm_dwarf_dump, args.wasm_file, offset) - if not line_info: - print(line) + print(f"{line}") continue - function_name, line_info = line_info - src_file, src_line, src_column = parse_line_info(line_info) - print( - f"{line} (FILE:{src_file} LINE:{src_line:5} COLUMN:{src_column:3} FUNC:{function_name})" - ) + _, offset, index = splitted + if args.no_addr: + if not index.startswith("$f"): # E.g. _start or Text format + print(f"{i}: {index}") + continue + index = index[2:] + + if index not in function_index_to_name: + print(f"{i}: {line}") + continue + + line_info = get_line_info_from_function_name( + llvm_dwarf_dump, args.wasm_file, function_index_to_name[index] + ) + + _, function_file, function_line = line_info + function_name = demangle(llvm_cxxfilt, function_index_to_name[index]) + print(f"{i}: {function_name}") + print(f"\tat {function_file}:{function_line}") + else: + offset = int(offset, 16) + offset = offset - code_section_start + function_name, function_file, function_line, function_column = ( + get_line_info_from_function_addr( + llvm_dwarf_dump, args.wasm_file, offset + ) + ) + + # if can't parse function_name, use name section or + if function_name == "": + if index.startswith("$f"): + function_name = function_index_to_name.get(index[2:], index) + else: + function_name = index + + function_name = demangle(llvm_cxxfilt, function_name) + + print(f"{i}: {function_name}") + print(f"\tat {function_file}:{function_line}:{function_column}") return 0 diff --git a/test-tools/flame-graph-helper/.gitignore b/test-tools/flame-graph-helper/.gitignore new file mode 100644 index 0000000000..b5ddc69ff8 --- /dev/null +++ b/test-tools/flame-graph-helper/.gitignore @@ -0,0 +1,2 @@ +*.* +!*.py \ No newline at end of file diff --git a/test-tools/flame-graph-helper/process_folded_data.py b/test-tools/flame-graph-helper/process_folded_data.py new file mode 100644 index 0000000000..e4650fe254 --- /dev/null +++ b/test-tools/flame-graph-helper/process_folded_data.py @@ -0,0 +1,325 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +""" +It is used to process *out.folded* file generated by [FlameGraph](https://github.com/brendangregg/FlameGraph). + +- translate jitted function names, which are in a form like `aot_func#N` or `[module name]#aot_func#N`, into corresponding names in a name section in .wasm +- divide the translated functions into different modules if the module name is specified in the symbol + +Usage: + +After +``` bash +# collect profiling data in perf.data + +$ perf script -i perf.data > out.perf + +$ ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded +``` + +Use this script to translate the function names in out.folded + +``` +$ python translate_wasm_function_name.py --wabt_home --folded out.folded <.wasm> +# out.folded -> out.folded.translated +``` + +""" + +import argparse +import os +from pathlib import Path +import re +import shlex +import subprocess +from typing import Dict, List + + +# parse arguments like "foo=bar,fiz=biz" into a dictatory {foo:bar,fiz=biz} +class ParseKVArgs(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + setattr(namespace, self.dest, dict()) + for value in values.split(","): + k, v = value.split("=") + getattr(namespace, self.dest)[k] = v + + +def calculate_import_function_count( + wasm_objdump_bin: Path, module_names: Dict[str, Path] +) -> Dict[str, int]: + """ + for every wasm file in , calculate the number of functions in the import section. + + using " -j Import -x " + """ + + assert wasm_objdump_bin.exists() + + import_function_counts = {} + for module_name, wasm_path in module_names.items(): + assert wasm_path.exists() + command = f"{wasm_objdump_bin} -j Import -x {wasm_path}" + p = subprocess.run( + shlex.split(command), + capture_output=True, + check=False, + text=True, + universal_newlines=True, + ) + + if p.stderr: + print("No content in import section") + import_function_counts[module_name] = 0 + continue + + import_function_count = 0 + for line in p.stdout.split(os.linesep): + line = line.strip() + + if not line: + continue + + if not " func" in line: + continue + + m = re.search(r"^-\s+func", line) + assert m + + import_function_count += 1 + + # print(f"! there are {import_function_count} import function in {module_name}") + import_function_counts[module_name] = import_function_count + + return import_function_counts + + +def collect_name_section_content( + wasm_objdump_bin: Path, module_names: Dict[str, Path] +) -> Dict[str, Dict[int, str]]: + """ + for every wasm file in , get the content of name section. + + execute "wasm_objdump_bin -j name -x wasm_file" + """ + assert wasm_objdump_bin.exists() + + name_sections = {} + for module_name, wasm_path in module_names.items(): + assert wasm_path.exists() + command = f"{wasm_objdump_bin} -j name -x {wasm_path}" + p = subprocess.run( + shlex.split(command), + capture_output=True, + check=False, + text=True, + universal_newlines=True, + ) + + if p.stderr: + print("No content in name section") + name_sections[module_name] = {} + continue + + name_section = {} + for line in p.stdout.split(os.linesep): + line = line.strip() + + if not line: + continue + + if not " func" in line: + continue + + # - func[N] <__imported_wasi_snapshot_preview1_fd_close> + m = re.match(r"- func\[(\d+)\] <(.+)>", line) + assert m + + func_index, func_name = m.groups() + name_section.update({int(func_index): func_name}) + + name_sections[module_name] = name_section + + return name_sections + + +def is_stack_check_mode(folded: Path) -> bool: + """ + check if there is a function name looks like "aot_func_internal#N", it means that WAMR adds a stack check function before the original function. + """ + with open(folded, "rt", encoding="utf-8") as f: + for line in f: + line = line.strip() + if "aot_func_internal" in line: + return True + return False + + +def replace_function_name( + import_function_counts: Dict[str, int], + name_sections: Dict[str, Dict[int, str]], + folded_in: Path, + module_names: Dict[str, Path], +) -> None: + """ + read content in . every line contains symbols which are separated by ";". + + Usually, all jitted functions are in the form of "aot_func#N". N is its function index. Use the index to find the corresponding function name in the name section. + + if there is a function name looks like "aot_func_internal#N", it means that WAMR adds a stack check function before the original function. + In this case, "aot_func#N" should be translated with "_precheck" as a suffix and "aot_func_internal#N" should be treated as the original one + """ + + assert folded_in.exists(), f"{folded_in} doesn't exist" + + stack_check_mode = is_stack_check_mode(folded_in) + + # every wasm has a translated out.folded, like out..folded.translated + folded_out_files = {} + for module_name in module_names.keys(): + wasm_folded_out_path = folded_in.with_suffix(f".{module_name}.translated") + print(f"-> write into {wasm_folded_out_path}") + folded_out_files[module_name] = wasm_folded_out_path.open( + "wt", encoding="utf-8" + ) + # Plus a default translated out.folded + default_folded_out_path = folded_in.with_suffix(".translated") + print(f"-> write into {default_folded_out_path}") + default_folded_out = default_folded_out_path.open("wt", encoding="utf-8") + + with folded_in.open("rt", encoding="utf-8") as f_in: + for line in f_in: + line = line.strip() + + m = re.match(r"(.*) (\d+)", line) + assert m + syms, samples = m.groups() + + new_line = [] + last_function_module_name = "" + for sym in syms.split(";"): + if not "aot_func" in sym: + new_line.append(sym) + continue + + # [module_name]#aot_func#N or aot_func#N + splitted = sym.split("#") + module_name = "" if splitted[0] == "aot_func" else splitted[0] + # remove [ and ] + module_name = module_name[1:-1] + + if len(module_name) == 0 and len(module_names) > 1: + raise RuntimeError( + f"❌ {sym} doesn't have a module name, but there are multiple wasm files" + ) + + if not module_name in module_names: + raise RuntimeError( + f"❌ can't find corresponds wasm file for {module_name}" + ) + + last_function_module_name = module_name + + func_idx = int(splitted[-1]) + # adjust index + func_idx = func_idx + import_function_counts[module_name] + + # print(f"🔍 {module_name} {splitted[1]} {func_idx}") + + if func_idx in name_sections[module_name]: + if len(module_name) > 0: + wasm_func_name = f"[Wasm] [{module_name}] {name_sections[module_name][func_idx]}" + else: + wasm_func_name = ( + f"[Wasm] {name_sections[module_name][func_idx]}" + ) + else: + if len(module_name) > 0: + wasm_func_name = f"[Wasm] [{module_name}] func[{func_idx}]" + else: + wasm_func_name = f"[Wasm] func[{func_idx}]" + + if stack_check_mode: + # aot_func_internal -> xxx + # aot_func --> xxx_precheck + if "aot_func" == splitted[1]: + wasm_func_name += "_precheck" + + new_line.append(wasm_func_name) + + line = ";".join(new_line) + line += f" {samples}" + + # always write into the default output + default_folded_out.write(line + os.linesep) + # based on the module name of last function, write into the corresponding output + if len(last_function_module_name) > 0: + folded_out_files[last_function_module_name].write(line + os.linesep) + + default_folded_out.close() + for f in folded_out_files.values(): + f.close() + + +def main(wabt_home: str, folded: str, module_names: Dict[str, Path]) -> None: + wabt_home = Path(wabt_home) + assert wabt_home.exists() + + folded = Path(folded) + assert folded.exists() + + wasm_objdump_bin = wabt_home.joinpath("bin", "wasm-objdump") + import_function_counts = calculate_import_function_count( + wasm_objdump_bin, module_names + ) + + name_sections = collect_name_section_content(wasm_objdump_bin, module_names) + + replace_function_name(import_function_counts, name_sections, folded, module_names) + + +if __name__ == "__main__": + argparse = argparse.ArgumentParser() + argparse.add_argument( + "--wabt_home", required=True, help="wabt home, like /opt/wabt-1.0.33" + ) + argparse.add_argument( + "--wasm", + action="append", + default=[], + help="wasm files for profiling before. like --wasm apple.wasm --wasm banana.wasm", + ) + argparse.add_argument( + "--wasm_names", + action=ParseKVArgs, + default={}, + metavar="module_name=wasm_file, ...", + help="multiple wasm files and their module names, like a=apple.wasm,b=banana.wasm,c=cake.wasm", + ) + argparse.add_argument( + "folded_file", + help="a out.folded generated by flamegraph/stackcollapse-perf.pl", + ) + + args = argparse.parse_args() + + if not args.wasm and not args.wasm_names: + print("Please specify wasm files with either --wasm or --wasm_names") + exit(1) + + # - only one wasm file. And there is no [module name] in out.folded + # - multiple wasm files. via `--wasm X --wasm Y --wasm Z`. And there is [module name] in out.folded. use the basename of wasm as the module name + # - multiple wasm files. via `--wasm_names X=x,Y=y,Z=z`. And there is [module name] in out.folded. use the specified module name + module_names = {} + if args.wasm_names: + for name, wasm_path in args.wasm_names.items(): + module_names[name] = Path(wasm_path) + else: + # use the basename of wasm as the module name + for wasm in args.wasm: + wasm_path = Path(wasm) + module_names[wasm_path.stem] = wasm_path + + main(args.wabt_home, args.folded_file, module_names) diff --git a/test-tools/trans-jitted-func-name/trans_wasm_func_name.py b/test-tools/trans-jitted-func-name/trans_wasm_func_name.py deleted file mode 100644 index 1380cd52a8..0000000000 --- a/test-tools/trans-jitted-func-name/trans_wasm_func_name.py +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -""" -It is used to translate jitted functions' names(in out.folded) to coorespond name in name section in .wasm - -Usage: - -After -``` -$ perf script -i perf.data > out.perf - -# fold call stacks -$ ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded -``` - -Add a step: -``` -# translate jitted functions' names -$ python translate_wasm_function_name.py --wabt_home --folded out.folded <.wasm> -# out.folded -> out.folded.translated -$ ls out.folded.translated -``` - -Then -``` -# generate flamegraph -$ ./FlameGraph/flamegraph.pl out.folded.translated > perf.wasm.svg -``` - -""" - -import argparse -import os -from pathlib import Path -import re -import shlex -import subprocess - - -def preflight_check(wabt_home: Path) -> Path: - """ - if wasm-objdump exists in wabt_home - """ - wasm_objdump_bin = wabt_home.joinpath("bin", "wasm-objdump") - if not wasm_objdump_bin.exists(): - raise RuntimeError(f"wasm-objdump not found in {wabt_home}") - - return wasm_objdump_bin - - -def collect_import_section_content(wasm_objdump_bin: Path, wasm_file: Path) -> dict: - """ - execute "wasm_objdump_bin -j Import -x " and return a dict like {function: X, global: Y, memory: Z, table: N} - """ - assert wasm_objdump_bin.exists() - assert wasm_file.exists() - - command = f"{wasm_objdump_bin} -j Import -x {wasm_file}" - p = subprocess.run( - shlex.split(command), - capture_output=True, - check=False, - text=True, - universal_newlines=True, - ) - - if p.stderr: - return {} - - import_section = {} - for line in p.stdout.split(os.linesep): - line = line.strip() - - if not line: - continue - - if line.startswith(" - func"): - import_section.update("function", import_section.get("function", 0) + 1) - else: - pass - - return import_section - - -def collect_name_section_content(wasm_objdump_bin: Path, wasm_file: Path) -> dict: - """ - execute "wasm_objdump_bin -j name -x wasm_file" and store the output in a list - """ - assert wasm_objdump_bin.exists() - assert wasm_file.exists() - - command = f"{wasm_objdump_bin} -j name -x {wasm_file}" - p = subprocess.run( - shlex.split(command), - capture_output=True, - check=False, - text=True, - universal_newlines=True, - ) - - if p.stderr: - raise RuntimeError(f"not found name section in {wasm_file}") - - name_section = {} - for line in p.stdout.split(os.linesep): - line = line.strip() - - if not line: - continue - - # - func[0] <__imported_wasi_snapshot_preview1_fd_close> - if line.startswith("- func"): - m = re.match(r"- func\[(\d+)\] <(.+)>", line) - assert m - - func_index, func_name = m.groups() - name_section.update({func_index: func_name}) - - assert name_section - return name_section - - -def replace_function_name( - import_section: dict, name_section: dict, folded_in: str, folded_out: str -) -> None: - """ - read content in . each line will be like: - - quiche::BalsaFrame::ProcessHeaders;non-virtual thunk to Envoy::Http::Http1::BalsaParser::MessageDone;Envoy::Http::Http1::ConnectionImpl::onMessageComplete;Envoy::Http::Http1::ConnectionImpl::onMessageCompleteImpl;Envoy::Http::Http1::ServerConnectionImpl::onMessageCompleteBase;Envoy::Http::ConnectionManagerImpl::ActiveStream::decodeHeaders;Envoy::Http::FilterManager::decodeHeaders;virtual thunk to Envoy::Extensions::Common::Wasm::Context::decodeHeaders;proxy_wasm::ContextBase::onRequestHeaders;proxy_wasm::wamr::Wamr::getModuleFunctionImpl;wasm_func_call;wasm_runtime_call_wasm;wasm_call_function;call_wasm_with_hw_bound_check;wasm_interp_call_wasm;llvm_jit_call_func_bytecode;wasm_runtime_invoke_native;push_args_end;aot_func_internal#3302;aot_func_internal#3308;asm_sysvec_apic_timer_interrupt;sysvec_apic_timer_interrupt;__sysvec_apic_timer_interrupt;hrtimer_interrupt;__hrtimer_run_queues;__remove_hrtimer;rb_next 1110899 - - symbol names are spearated by ";" - - if there is a symbol named like "aot_func#XXX" or "aot_func_internal#XXX", it will be replaced with the function name in name section by index - """ - folded_in = Path(folded_in) - assert folded_in.exists() - folded_out = Path(folded_out) - - import_function_count = import_section.get("function", 0) - with folded_in.open("rt", encoding="utf-8") as f_in, folded_out.open( - "wt", encoding="utf-8" - ) as f_out: - precheck_mode = False - for line in f_in: - line = line.strip() - if "aot_func_internal" in line: - precheck_mode = True - - f_in.seek(0) - for line in f_in: - new_line = [] - line = line.strip() - - m = re.match(r"(.*) (\d+)", line) - syms, samples = m.groups() - for sym in syms.split(";"): - m = re.match(r"aot_func(_internal)?#(\d+)", sym) - if not m: - new_line.append(sym) - continue - - func_idx = m.groups()[-1] - if func_idx in name_section: - wasm_func_name = f"[Wasm] {name_section[func_idx]}" - else: - wasm_func_name = ( - f"[Wasm] function[{func_idx + import_function_count}]" - ) - - if precheck_mode: - # aot_func_internal -> xxx - # aot_func --> xxx_precheck - wasm_func_name += "_precheck" if not m.groups()[0] else "" - else: - # aot_func --> xxx - pass - - new_line.append(wasm_func_name) - - line = ";".join(new_line) - line += f" {samples}" - f_out.write(line + os.linesep) - - print(f"⚙️ {folded_in} -> {folded_out}") - - -def main(wabt_home: str, wasm_file: str, folded: str) -> None: - wabt_home = Path(wabt_home) - wasm_file = Path(wasm_file) - - wasm_objdump_bin = preflight_check(wabt_home) - import_section = collect_import_section_content(wasm_objdump_bin, wasm_file) - name_section = collect_name_section_content(wasm_objdump_bin, wasm_file) - - replace_function_name(import_section, name_section, folded, folded + ".translated") - - -if __name__ == "__main__": - argparse = argparse.ArgumentParser() - argparse.add_argument( - "--folded", help="stackcollapse-perf.pl generated, like out.folded" - ) - argparse.add_argument("wasm_file", help="wasm file") - argparse.add_argument("--wabt_home", help="wabt home, like /opt/wabt-1.0.33") - - args = argparse.parse_args() - main(args.wabt_home, args.wasm_file, args.folded) diff --git a/tests/benchmarks/jetstream/build.sh b/tests/benchmarks/jetstream/build.sh index ca8401cdab..019b4073df 100755 --- a/tests/benchmarks/jetstream/build.sh +++ b/tests/benchmarks/jetstream/build.sh @@ -7,11 +7,11 @@ source /opt/emsdk/emsdk_env.sh PLATFORM=$(uname -s | tr A-Z a-z) +WORK_DIR=$PWD OUT_DIR=$PWD/out WAMRC_CMD=$PWD/../../../wamr-compiler/build/wamrc +JETSTREAM_DIR=$PWD/perf-automation/benchmarks/JetStream2/wasm -mkdir -p jetstream -mkdir -p tsf-src mkdir -p ${OUT_DIR} if [[ $1 != "--no-simd" ]];then @@ -22,20 +22,16 @@ else WASM_SIMD_FLAGS="" fi -cd jetstream - -echo "Download source files .." -wget -N https://browserbench.org/JetStream/wasm/gcc-loops.cpp -wget -N https://browserbench.org/JetStream/wasm/quicksort.c -wget -N https://browserbench.org/JetStream/wasm/HashSet.cpp -wget -N https://browserbench.org/JetStream/simple/float-mm.c - -if [[ $? != 0 ]]; then - exit +if [ ! -d perf-automation ]; then + git clone https://github.com/mozilla/perf-automation.git + echo "Patch source files .." + cd perf-automation + patch -p1 -N < ../jetstream.patch fi -echo "Patch source files .." -patch -p1 -N < ../jetstream.patch +cd ${JETSTREAM_DIR} + +# Build gcc-loops echo "Build gcc-loops with g++ .." g++ -O3 ${NATIVE_SIMD_FLAGS} -o ${OUT_DIR}/gcc-loops_native gcc-loops.cpp @@ -56,6 +52,8 @@ if [[ ${PLATFORM} == "linux" ]]; then ${WAMRC_CMD} --enable-segue -o ${OUT_DIR}/gcc-loops_segue.aot ${OUT_DIR}/gcc-loops.wasm fi +# Build quicksort + echo "Build quicksort with gcc .." gcc -O3 ${NATIVE_SIMD_FLAGS} -o ${OUT_DIR}/quicksort_native quicksort.c @@ -74,6 +72,8 @@ if [[ ${PLATFORM} == "linux" ]]; then ${WAMRC_CMD} --enable-segue -o ${OUT_DIR}/quicksort_segue.aot ${OUT_DIR}/quicksort.wasm fi +# Build HashSet + echo "Build HashSet with g++ .." g++ -O3 ${NATIVE_SIMD_FLAGS} -o ${OUT_DIR}/HashSet_native HashSet.cpp \ -lstdc++ @@ -93,6 +93,10 @@ if [[ ${PLATFORM} == "linux" ]]; then ${WAMRC_CMD} --enable-segue -o ${OUT_DIR}/HashSet_segue.aot ${OUT_DIR}/HashSet.wasm fi +# Build float-mm + +cd ${JETSTREAM_DIR}/../simple + echo "Build float-mm with gcc .." gcc -O3 ${NATIVE_SIMD_FLAGS} -o ${OUT_DIR}/float-mm_native float-mm.c @@ -111,7 +115,9 @@ if [[ ${PLATFORM} == "linux" ]]; then ${WAMRC_CMD} --enable-segue -o ${OUT_DIR}/float-mm_segue.aot ${OUT_DIR}/float-mm.wasm fi -cd ../tsf-src +# Build tsf + +cd ${JETSTREAM_DIR}/TSF tsf_srcs="tsf_asprintf.c tsf_buffer.c tsf_error.c tsf_reflect.c tsf_st.c \ tsf_type.c tsf_io.c tsf_native.c tsf_generator.c tsf_st_typetable.c \ @@ -127,28 +133,6 @@ tsf_srcs="tsf_asprintf.c tsf_buffer.c tsf_error.c tsf_reflect.c tsf_st.c \ tsf_fsdb.c tsf_fsdb_protocol.c tsf_define_helpers.c tsf_ir.c \ tsf_ir_different.c tsf_ir_speed.c" -tsf_files="${tsf_srcs} config.h gpc_worklist.h \ - tsf_config_stub.h tsf.h tsf_internal.h tsf_region.h tsf_types.h \ - gpc.h tsf_atomics.h tsf_define_helpers.h tsf_indent.h tsf_inttypes.h \ - tsf_serial_protocol.h tsf_util.h gpc_int_common.h tsf_build_defines.h \ - tsf_format.h tsf_internal_config.h tsf_ir_different.h tsf_sha1.h \ - tsf_zip_abstract.h gpc_internal.h tsf_config.h tsf_fsdb_protocol.h \ - tsf_internal_config_stub.h tsf_ir.h tsf_st.h \ - gpc_instruction_dispatch.gen gpc_instruction_stack_effects.gen \ - gpc_instruction_to_string.gen gpc_instruction_size.gen \ - gpc_instruction_static_size.gen gpc_interpreter.gen" - -echo "Download tsf source files .." -for t in ${tsf_files} -do - wget -N "https://browserbench.org/JetStream/wasm/TSF/${t}" - if [[ $? != 0 ]]; then - exit - fi -done - -patch -p1 -N < ../tsf.patch - echo "Build tsf with gcc .." gcc \ -o ${OUT_DIR}/tsf_native -O3 ${NATIVE_SIMD_FLAGS} \ diff --git a/tests/benchmarks/jetstream/jetstream.patch b/tests/benchmarks/jetstream/jetstream.patch index bc680d98a1..8799fb6c5c 100644 --- a/tests/benchmarks/jetstream/jetstream.patch +++ b/tests/benchmarks/jetstream/jetstream.patch @@ -1,8 +1,9 @@ -diff -urN jetstream-org/HashSet.cpp jetstream/HashSet.cpp ---- jetstream-org/HashSet.cpp 2020-10-30 04:12:42.000000000 +0800 -+++ jetstream/HashSet.cpp 2022-01-24 17:11:08.619831711 +0800 +diff --git a/benchmarks/JetStream2/wasm/HashSet.cpp b/benchmarks/JetStream2/wasm/HashSet.cpp +index eca979b0..d1bf4d3d 100644 +--- a/benchmarks/JetStream2/wasm/HashSet.cpp ++++ b/benchmarks/JetStream2/wasm/HashSet.cpp @@ -22,8 +22,10 @@ - + #include #include +#include @@ -10,9 +11,9 @@ diff -urN jetstream-org/HashSet.cpp jetstream/HashSet.cpp #include +#include #include - + // Compile with: xcrun clang++ -o HashSet HashSet.cpp -O2 -W -framework Foundation -licucore -std=c++11 -fvisibility=hidden -DNDEBUG=1 -@@ -76,7 +78,7 @@ +@@ -76,7 +78,7 @@ template inline ToType bitwise_cast(FromType from) { typename std::remove_const::type to { }; @@ -20,4 +21,43 @@ diff -urN jetstream-org/HashSet.cpp jetstream/HashSet.cpp + memcpy(&to, &from, sizeof(to)); return to; } - + +diff --git a/benchmarks/JetStream2/wasm/TSF/gpc_code_gen_util.c b/benchmarks/JetStream2/wasm/TSF/gpc_code_gen_util.c +index 56220fa7..7e3a365b 100644 +--- a/benchmarks/JetStream2/wasm/TSF/gpc_code_gen_util.c ++++ b/benchmarks/JetStream2/wasm/TSF/gpc_code_gen_util.c +@@ -34,6 +34,8 @@ + #include + #include + ++int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); ++ + /* code generation debugging */ + + /* NOTE: It is now the case that the count may be incremented multiple times, +diff --git a/benchmarks/JetStream2/wasm/TSF/tsf_internal.h b/benchmarks/JetStream2/wasm/TSF/tsf_internal.h +index 225a248b..ae39d3d3 100644 +--- a/benchmarks/JetStream2/wasm/TSF/tsf_internal.h ++++ b/benchmarks/JetStream2/wasm/TSF/tsf_internal.h +@@ -429,6 +429,7 @@ struct tsf_fsdb { + #endif + tsf_fsdb_connection_t *connection; + #endif ++ uint32_t __padding; + } remote; + } u; + tsf_limits_t *limits; +diff --git a/benchmarks/JetStream2/wasm/TSF/tsf_ir_speed.c b/benchmarks/JetStream2/wasm/TSF/tsf_ir_speed.c +index dd75c43e..79435c42 100644 +--- a/benchmarks/JetStream2/wasm/TSF/tsf_ir_speed.c ++++ b/benchmarks/JetStream2/wasm/TSF/tsf_ir_speed.c +@@ -63,6 +63,9 @@ static void writeTest(const char *filename, + Program_t *program; + unsigned elementIndex; + ++ if (!(programIndex % 100)) ++ printf("##programIndex: %u\n", programIndex); ++ + CS(program = tsf_region_create(sizeof(Program_t))); + + program->globals.len = numDecls + numDefns; diff --git a/tests/benchmarks/jetstream/tsf.patch b/tests/benchmarks/jetstream/tsf.patch deleted file mode 100644 index 98355b08cf..0000000000 --- a/tests/benchmarks/jetstream/tsf.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff -urN tsf-src-org/gpc_code_gen_util.c tsf-src/gpc_code_gen_util.c ---- tsf-src-org/gpc_code_gen_util.c 2023-09-21 11:12:40.211166472 +0800 -+++ tsf-src/gpc_code_gen_util.c 2023-09-21 11:09:13.643170967 +0800 -@@ -34,6 +34,8 @@ - #include - #include - -+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); -+ - /* code generation debugging */ - - /* NOTE: It is now the case that the count may be incremented multiple times, -diff -urN tsf-src-org/tsf_internal.h tsf-src/tsf_internal.h ---- tsf-src-org/tsf_internal.h 2023-09-21 11:11:50.843167546 +0800 -+++ tsf-src/tsf_internal.h 2023-09-21 11:06:53.031174027 +0800 -@@ -429,6 +429,7 @@ - #endif - tsf_fsdb_connection_t *connection; - #endif -+ uint32_t __padding; - } remote; - } u; - tsf_limits_t *limits; -diff -urN tsf-src-org/tsf_ir_speed.c tsf-src/tsf_ir_speed.c ---- tsf-src-org/tsf_ir_speed.c 2023-09-21 11:12:15.699167005 +0800 -+++ tsf-src/tsf_ir_speed.c 2023-09-21 11:06:53.031174027 +0800 -@@ -63,6 +63,9 @@ - Program_t *program; - unsigned elementIndex; - -+ if (!(programIndex % 100)) -+ printf("##programIndex: %u\n", programIndex); -+ - CS(program = tsf_region_create(sizeof(Program_t))); - - program->globals.len = numDecls + numDefns; diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 8027abde0a..98f5c1e63d 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -14,7 +14,7 @@ """ The script itself has to be put under the same directory with the "spec". -To run a single non-GC case with interpreter mode: +To run a single non-GC and non-memory64 case with interpreter mode: cd workspace python3 runtest.py --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \ spec/test/core/xxx.wast @@ -22,7 +22,7 @@ cd workspace python3 runtest.py --aot --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \ --aot-compiler wamrc spec/test/core/xxx.wast -To run a single GC case: +To run a single GC case or single memory64 case: cd workspace python3 runtest.py --wast2wasm spec/interpreter/wasm --interpreter iwasm \ --aot-compiler wamrc --gc spec/test/core/xxx.wast @@ -78,6 +78,7 @@ def ignore_the_case( multi_thread_flag=False, simd_flag=False, gc_flag=False, + memory64_flag=False, xip_flag=False, eh_flag=False, qemu_flag=False, @@ -162,6 +163,7 @@ def test_case( clean_up_flag=True, verbose_flag=True, gc_flag=False, + memory64_flag=False, qemu_flag=False, qemu_firmware="", log="", @@ -169,7 +171,7 @@ def test_case( ): CMD = [sys.executable, "runtest.py"] CMD.append("--wast2wasm") - CMD.append(WAST2WASM_CMD if not gc_flag else SPEC_INTERPRETER_CMD) + CMD.append(WAST2WASM_CMD if not gc_flag and not memory64_flag else SPEC_INTERPRETER_CMD) CMD.append("--interpreter") if sgx_flag: CMD.append(IWASM_SGX_CMD) @@ -217,6 +219,9 @@ def test_case( if gc_flag: CMD.append("--gc") + if memory64_flag: + CMD.append("--memory64") + if log != "": CMD.append("--log-dir") CMD.append(log) @@ -283,6 +288,7 @@ def test_suite( clean_up_flag=True, verbose_flag=True, gc_flag=False, + memory64_flag=False, parl_flag=False, qemu_flag=False, qemu_firmware="", @@ -325,6 +331,7 @@ def test_suite( multi_thread_flag, simd_flag, gc_flag, + memory64_flag, xip_flag, eh_flag, qemu_flag, @@ -357,6 +364,7 @@ def test_suite( clean_up_flag, verbose_flag, gc_flag, + memory64_flag, qemu_flag, qemu_firmware, log, @@ -382,6 +390,7 @@ def test_suite( else: print(f"----- Run the whole spec test suite -----") for case_path in case_list: + print(case_path) try: test_case( str(case_path), @@ -396,6 +405,7 @@ def test_suite( clean_up_flag, verbose_flag, gc_flag, + memory64_flag, qemu_flag, qemu_firmware, log, @@ -521,6 +531,13 @@ def main(): dest="gc_flag", help="Running with GC feature", ) + parser.add_argument( + "--memory64", + action="store_true", + default=False, + dest="memory64_flag", + help="Running with memory64 feature", + ) parser.add_argument( "cases", metavar="path_to__case", @@ -563,6 +580,7 @@ def main(): options.clean_up_flag, options.verbose_flag, options.gc_flag, + options.memory64_flag, options.parl_flag, options.qemu_flag, options.qemu_firmware, @@ -589,6 +607,7 @@ def main(): options.clean_up_flag, options.verbose_flag, options.gc_flag, + options.memory64_flag, options.qemu_flag, options.qemu_firmware, options.log, diff --git a/tests/wamr-test-suites/spec-test-script/memory64.patch b/tests/wamr-test-suites/spec-test-script/memory64.patch new file mode 100644 index 0000000000..739a1df60d --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/memory64.patch @@ -0,0 +1,28 @@ +diff --git a/test/core/memory.wast b/test/core/memory.wast +index 1dd5b84..497b69f 100644 +--- a/test/core/memory.wast ++++ b/test/core/memory.wast +@@ -76,17 +76,17 @@ + "memory size must be at most 65536 pages (4GiB)" + ) + +-(assert_invalid ++(assert_malformed + (module quote "(memory 0x1_0000_0000)") +- "memory size must be at most 65536 pages (4GiB)" ++ "i32 constant out of range" + ) +-(assert_invalid ++(assert_malformed + (module quote "(memory 0x1_0000_0000 0x1_0000_0000)") +- "memory size must be at most 65536 pages (4GiB)" ++ "i32 constant out of range" + ) +-(assert_invalid ++(assert_malformed + (module quote "(memory 0 0x1_0000_0000)") +- "memory size must be at most 65536 pages (4GiB)" ++ "i32 constant out of range" + ) + + (module diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 344e4fd440..13229d977f 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -313,6 +313,9 @@ def assert_prompt(runner, prompts, timeout, is_need_execute_result): parser.add_argument('--gc', default=False, action='store_true', help='Test with GC') +parser.add_argument('--memory64', default=False, action='store_true', + help='Test with Memory64') + parser.add_argument('--qemu', default=False, action='store_true', help="Enable QEMU") @@ -1071,7 +1074,7 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): log("Compiling WASM to '%s'" % wasm_tempfile) # default arguments - if opts.gc: + if opts.gc or opts.memory64: cmd = [opts.wast2wasm, "-u", "-d", wast_tempfile, "-o", wasm_tempfile] elif opts.eh: cmd = [opts.wast2wasm, "--enable-thread", "--no-check", "--enable-exceptions", "--enable-tail-call", wast_tempfile, "-o", wasm_tempfile ] @@ -1116,6 +1119,9 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = ' cmd.append("--enable-gc") cmd.append("--enable-tail-call") + if opts.memory64: + cmd.append("--enable-memory64") + if output == 'object': cmd.append("--format=object") elif output == 'ir': diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 933583816a..0c56acac47 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -23,6 +23,7 @@ function help() echo "-p enable multi thread feature" echo "-S enable SIMD feature" echo "-G enable GC feature" + echo "-W enable memory64 feature" echo "-X enable XIP feature" echo "-e enable exception handling" echo "-x test SGX" @@ -50,6 +51,7 @@ ENABLE_MULTI_THREAD=0 COLLECT_CODE_COVERAGE=0 ENABLE_SIMD=0 ENABLE_GC=0 +ENABLE_MEMORY64=0 ENABLE_XIP=0 ENABLE_EH=0 ENABLE_DEBUG_VERSION=0 @@ -72,7 +74,7 @@ WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2" TARGET_LIST=("AARCH64" "AARCH64_VFP" "ARMV7" "ARMV7_VFP" "THUMBV7" "THUMBV7_VFP" \ "RISCV32" "RISCV32_ILP32F" "RISCV32_ILP32D" "RISCV64" "RISCV64_LP64F" "RISCV64_LP64D") -while getopts ":s:cabgvt:m:MCpSXexwPGQF:j:T:" opt +while getopts ":s:cabgvt:m:MCpSXexwWPGQF:j:T:" opt do OPT_PARSED="TRUE" case $opt in @@ -131,6 +133,10 @@ do echo "enable multi module feature" ENABLE_MULTI_MODULE=1 ;; + W) + echo "enable wasm64(memory64) feature" + ENABLE_MEMORY64=1 + ;; C) echo "enable code coverage" COLLECT_CODE_COVERAGE=1 @@ -478,6 +484,29 @@ function spec_test() popd fi + # update memory64 cases + if [[ ${ENABLE_MEMORY64} == 1 ]]; then + echo "checkout spec for memory64 proposal" + + popd + rm -fr spec + # check spec test cases for memory64 + git clone -b main --single-branch https://github.com/WebAssembly/memory64.git spec + pushd spec + + git restore . && git clean -ffd . + # Reset to commit: "Merge remote-tracking branch 'upstream/main' into merge2" + git reset --hard 48e69f394869c55b7bbe14ac963c09f4605490b6 + git checkout 044d0d2e77bdcbe891f7e0b9dd2ac01d56435f0b -- test/core/elem.wast + git apply ../../spec-test-script/ignore_cases.patch + git apply ../../spec-test-script/memory64.patch + + echo "compile the reference intepreter" + pushd interpreter + make + popd + fi + popd echo $(pwd) @@ -488,7 +517,7 @@ function spec_test() local ARGS_FOR_SPEC_TEST="" - # multi-module only enable in interp mode + # multi-module only enable in interp mode and aot mode if [[ 1 == ${ENABLE_MULTI_MODULE} ]]; then if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' ]]; then ARGS_FOR_SPEC_TEST+="-M " @@ -537,6 +566,13 @@ function spec_test() ARGS_FOR_SPEC_TEST+="--gc " fi + # wasm64(memory64) is only enabled in interp and aot mode + if [[ 1 == ${ENABLE_MEMORY64} ]]; then + if [[ $1 == 'classic-interp' || $1 == 'aot' ]]; then + ARGS_FOR_SPEC_TEST+="--memory64 " + fi + fi + if [[ ${ENABLE_QEMU} == 1 ]]; then ARGS_FOR_SPEC_TEST+="--qemu " ARGS_FOR_SPEC_TEST+="--qemu-firmware ${QEMU_FIRMWARE} " @@ -833,6 +869,12 @@ function trigger() EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MULTI_MODULE=0" fi + if [[ ${ENABLE_MEMORY64} == 1 ]];then + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MEMORY64=1" + else + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MEMORY64=0" + fi + if [[ ${ENABLE_MULTI_THREAD} == 1 ]];then EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_PTHREAD=1" fi diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 901ec5effc..c976145631 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -472,7 +472,8 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--enable-checkpoint")) { option.enable_aux_stack_frame = true; option.enable_checkpoint = true; - } else if (!strcmp(argv[0], "--enable-loop-checkpoint")) { + } + else if (!strcmp(argv[0], "--enable-loop-checkpoint")) { option.enable_aux_stack_frame = true; option.enable_checkpoint = true; option.enable_loop_checkpoint = true;