diff --git a/.github/workflows/Crate-publishing.yml b/.github/workflows/Crate-publishing.yml index 229cf49c0c..e07af532d4 100644 --- a/.github/workflows/Crate-publishing.yml +++ b/.github/workflows/Crate-publishing.yml @@ -1,5 +1,9 @@ name: Crate 📦 Distribution +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: push: paths-ignore: @@ -47,12 +51,6 @@ jobs: run: | choco install ninja - - name: "🛠️ macOS build dependencies" - if: contains(matrix.config.os, 'macOS') - shell: bash - run: | - brew install ninja - - name: "🚧 Cargo test" if: "!startsWith(github.ref, 'refs/tags')" run: | @@ -60,6 +58,7 @@ jobs: - name: Publish crates to Crates.io if: startsWith(github.ref, 'refs/tags') && !startsWith(github.ref, 'refs/tags/v') && contains(matrix.config.os, 'ubuntu') - uses: katyo/publish-crates@v2 - with: - registry-token: ${{ secrets.cratesio_token }} + env: + TOKEN: ${{ secrets.cratesio_token }} + run: | + cargo login $TOKEN && cargo publish -p unicorn-engine-sys && cd bindings/rust/unicorn-engine && cargo publish -p unicorn-engine diff --git a/.github/workflows/Nuget-publishing.yml b/.github/workflows/Nuget-publishing.yml index 820a7a0563..681978a410 100644 --- a/.github/workflows/Nuget-publishing.yml +++ b/.github/workflows/Nuget-publishing.yml @@ -1,5 +1,10 @@ name: Nuget 📦 Distribution +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + + on: push: paths-ignore: @@ -159,7 +164,6 @@ jobs: if: contains(matrix.config.name, 'macos-x64') shell: bash run: | - brew install ninja ninja --version cmake --version mkdir build diff --git a/.github/workflows/build-uc2.yml b/.github/workflows/build-uc2.yml index d2dff10560..adf86d38a6 100644 --- a/.github/workflows/build-uc2.yml +++ b/.github/workflows/build-uc2.yml @@ -1,5 +1,9 @@ name: Build UC2 +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: workflow_dispatch: inputs: @@ -164,7 +168,7 @@ jobs: cmake --build . --config ${{ env.BUILD_TYPE }} cmake --install . --strip --config ${{ env.BUILD_TYPE }} ctest -VV -C ${{ env.BUILD_TYPE }} - mv Debug instdir + mv ${{ env.BUILD_TYPE }} instdir - name: '🛠️ Win MSVC 32 setup' if: contains(matrix.config.name, 'MSVC 32') @@ -191,7 +195,7 @@ jobs: cmake --build . --config ${{ env.BUILD_TYPE }} cmake --install . --strip --config ${{ env.BUILD_TYPE }} ctest -VV -C ${{ env.BUILD_TYPE }} - mv Debug instdir + mv ${{ env.BUILD_TYPE }} instdir - name: '🚧 Win MINGW build' if: contains(matrix.config.mingw, 'MINGW') @@ -294,7 +298,6 @@ jobs: if: contains(matrix.config.name, 'macos') shell: bash run: | - brew install ninja ninja --version cmake --version mkdir build @@ -314,7 +317,6 @@ jobs: if: contains(matrix.config.name, 'android') shell: bash run: | - brew install ninja mkdir build mkdir instdir cmake . -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ diff --git a/.github/workflows/build-wheels-publish.yml b/.github/workflows/build-wheels-publish.yml index c68bad7479..b331f38494 100644 --- a/.github/workflows/build-wheels-publish.yml +++ b/.github/workflows/build-wheels-publish.yml @@ -1,5 +1,9 @@ name: Build and publish wheels with cibuildwheel +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: workflow_dispatch: inputs: @@ -11,14 +15,6 @@ on: options: - '0' - '1' - fullMode: - description: 'Full Mode' - required: false - default: '' - type: choice - options: - - '0' - - '1' push: paths-ignore: - ".gitignore" @@ -38,7 +34,7 @@ env: jobs: # job to be executed for every push - testing purpose - build_wheels_python38_only: + build_and_test_wheels: name: Building on ${{ matrix.os }} - ${{ matrix.arch }} - ${{ matrix.cibw_build }} runs-on: ${{ matrix.os }} strategy: @@ -47,21 +43,21 @@ jobs: include: # NOTE: Doing this to parallelize and speed up workflow # i686 - manylinux - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp38-manylinux*', cibw_skip: '' } + - { os: ubuntu-latest, arch: i686, cibw_build: 'cp*-manylinux*', cibw_skip: 'cp36*' } # i686 - musllinux - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp38-musllinux*', cibw_skip: '' } + - { os: ubuntu-latest, arch: i686, cibw_build: 'cp*-musllinux*', cibw_skip: 'cp36*' } # x86_64 - manylinux - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp38-manylinux*', cibw_skip: '' } + - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp*-manylinux*', cibw_skip: 'cp36*' } # x86_64 - musllinux - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp38-musllinux*', cibw_skip: '' } + - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp*-musllinux*', cibw_skip: 'cp36*' } # aarch64 - manylinux - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp38-manylinux*', cibw_skip: '' } + - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp*-manylinux*', cibw_skip: 'cp36*' } # aarch64 - musllinux - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp38-musllinux*', cibw_skip: '' } - - { os: macos-13, arch: x86_64, cibw_build: 'cp38*', cibw_skip: '' } - - { os: macos-latest, arch: arm64, cibw_build: 'cp38*', cibw_skip: '' } - - { os: windows-2022, arch: AMD64, cibw_build: 'cp38*', cibw_skip: '' } - - { os: windows-2022, arch: x86, cibw_build: 'cp38*', cibw_skip: '' } + - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp*-musllinux*', cibw_skip: 'cp36*' } + - { os: macos-13, arch: x86_64, cibw_build: 'cp*', cibw_skip: 'cp36*' } + - { os: macos-14, arch: arm64, cibw_build: 'cp*', cibw_skip: 'cp36* cp37*' } + - { os: windows-2022, arch: AMD64, cibw_build: 'cp*', cibw_skip: 'cp36*' } + - { os: windows-2022, arch: x86, cibw_build: 'cp*', cibw_skip: 'cp36*' } steps: - uses: actions/checkout@v4 @@ -113,7 +109,7 @@ jobs: uses: docker/setup-qemu-action@v3 - name: '🚧 cibuildwheel run' - uses: pypa/cibuildwheel@v2.22.0 + uses: pypa/cibuildwheel@v2.23.3 env: CIBW_BUILD_FRONTEND: build CIBW_BUILD: ${{ matrix.cibw_build }} @@ -136,10 +132,10 @@ jobs: shell: bash run: | python3 -m pip install -U pip wheel - python3 -m wheel tags --python-tag='py2' --abi-tag=none wheelhouse/*cp38*.whl + python3 -m wheel tags --python-tag='py2' --abi-tag=none wheelhouse/*cp37*.whl - - uses: LizardByte/setup-python-action@v2024.919.163656 - if: (runner.os == 'Linux' && (matrix.arch == 'x86_64' || matrix.arch == 'aarch64') && matrix.cibw_build == 'cp38-manylinux*') || (runner.os == 'macOS' && matrix.arch == 'arm64') || (runner.os == 'Windows' && matrix.arch == 'AMD64') + - uses: LizardByte/actions/actions/setup_python@v2025.715.25226 + if: (runner.os == 'Linux' && (matrix.arch == 'x86_64' || matrix.arch == 'aarch64') && matrix.cibw_build == 'cp*-manylinux*') || (runner.os == 'macOS' && matrix.arch == 'arm64') || (runner.os == 'Windows' && matrix.arch == 'AMD64') with: python-version: 2.7 @@ -153,135 +149,12 @@ jobs: # NOTE: no python2.7 support for macos-13: https://github.com/LizardByte/setup-python-action/issues/2 - name: 'Python 2.7 tests - Non-Windows' - if: (runner.os == 'Linux' && (matrix.arch == 'x86_64' || matrix.arch == 'aarch64') && matrix.cibw_build == 'cp38-manylinux*') || (runner.os == 'macOS' && matrix.arch == 'arm64') + if: (runner.os == 'Linux' && (matrix.arch == 'x86_64' || matrix.arch == 'aarch64') && matrix.cibw_build == 'cp*-manylinux*') || (runner.os == 'macOS' && matrix.arch == 'arm64') run: | python2 -m pip install capstone==4.0.2 wheelhouse/*py2*.whl python2 -m unittest discover tests/regress "*.py" - # https://github.com/unicorn-engine/unicorn/issues/2033 - # Skip macos arm64 wheels during release stage - - uses: actions/upload-artifact@v4 - if: ${{!( startsWith(github.ref, 'refs/tags') && !startsWith(github.ref, 'refs/tags/v') && contains(matrix.os, 'macos') && contains(matrix.arch, 'arm64') )}} - with: - name: ${{ env.ARTIFACT_NAME }} - path: ./wheelhouse/*.whl - - # Job to be executed to build all wheels for all platforms/architectures/python versions only for tag release - build_wheels_all_versions: - name: Building on ${{ matrix.os }} - ${{ matrix.arch }} - ${{ matrix.cibw_build }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - # NOTE: Doing this to parallelize and speed up workflow - # i686 - manylinux - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp37-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp39-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp310-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp311-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp312-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp313-manylinux*', cibw_skip: '' } - # i686 - musllinux - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp37-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp39-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp310-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp311-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp312-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: i686, cibw_build: 'cp313-musllinux*', cibw_skip: '' } - # x86_64 - manylinux - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp37-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp39-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp310-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp311-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp312-manylinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp313-manylinux*', cibw_skip: '' } - # x86_64 - musllinux - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp37-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp39-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp310-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp311-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp312-musllinux*', cibw_skip: '' } - - { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp313-musllinux*', cibw_skip: '' } - # aarch64 - manylinux - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp37-manylinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp39-manylinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp310-manylinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp311-manylinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp312-manylinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp313-manylinux*', cibw_skip: '' } - # aarch64 - musllinux - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp37-musllinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp39-musllinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp310-musllinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp311-musllinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp312-musllinux*', cibw_skip: '' } - - { os: ubuntu-24.04-arm, arch: aarch64, cibw_build: 'cp313-musllinux*', cibw_skip: '' } - - { os: macos-13, arch: x86_64, cibw_build: 'cp*', cibw_skip: '*36* *38*' } - - { os: macos-latest, arch: arm64, cibw_build: 'cp*', cibw_skip: '*36* *37* *38*' } - - { os: windows-2022, arch: AMD64, cibw_build: 'cp*', cibw_skip: '*36* *38*' } - - { os: windows-2022, arch: x86, cibw_build: 'cp*', cibw_skip: '*36* *38*' } - if: ${{ inputs.fullMode == 1 || (startsWith(github.ref, 'refs/tags') && !startsWith(github.ref, 'refs/tags/v')) || contains(github.event.head_commit.message, 'CI(full)') }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - # https://github.com/actions/upload-artifact/issues/22 - - name: Prepare a unique name for Artifacts - shell: bash - run: | - # replace not-allowed chars with dash - name="cibw-wheels-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.cibw_build }}" - name=$(echo -n "$name" | sed -e 's/[ \t:\/\\"<>|*?]/-/g' -e 's/--*/-/g' | sed -e 's/\-$//') - echo "ARTIFACT_NAME=$name" >> $GITHUB_ENV - - - name: "Increase pagefile to avoid OOM" - if: runner.os == 'Windows' - uses: al-cheb/configure-pagefile-action@v1.4 - with: - minimum-size: 8GB - disk-root: "C:" - - - name: '🛠️ Add msbuild to PATH' - if: runner.os == 'Windows' - uses: microsoft/setup-msbuild@v2 - with: - vs-version: '17' - - - name: '🛠️ Win MSVC 32 dev cmd setup' - if: runner.os == 'Windows' && matrix.arch == 'x86' - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x86 - - - name: '🛠️ Win MSVC 64 dev cmd setup' - if: runner.os == 'Windows' && matrix.arch == 'AMD64' - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x64 - - - name: '🛠️ Set up QEMU' - if: runner.os == 'Linux' && matrix.arch == 'i686' - uses: docker/setup-qemu-action@v3 - - - name: '🚧 cibuildwheel run' - uses: pypa/cibuildwheel@v2.22.0 - env: - CIBW_BUILD_FRONTEND: build - CIBW_BUILD: ${{ matrix.cibw_build }} - CIBW_SKIP: ${{ matrix.cibw_skip }} - CIBW_ARCHS: ${{ matrix.arch }} - CIBW_ENVIRONMENT: DEBUG=${{ env.UNICORN_DEBUG }} GENERATORS='Visual Studio 17 2022' - CIBW_ENVIRONMENT_PASS_LINUX: DEBUG - CIBW_TEST_EXTRAS: test - CIBW_TEST_COMMAND: 'python -m unittest discover -v {project}/tests/regress "*.py"' - with: - package-dir: bindings/python - output-dir: wheelhouse - - uses: actions/upload-artifact@v4 - if: ${{!( startsWith(github.ref, 'refs/tags') && !startsWith(github.ref, 'refs/tags/v') && contains(matrix.os, 'macos') && contains(matrix.arch, 'arm64') )}} with: name: ${{ env.ARTIFACT_NAME }} path: ./wheelhouse/*.whl @@ -307,7 +180,7 @@ jobs: path: bindings/python/dist/*.tar.gz publish: - needs: [ build_wheels_python38_only, build_wheels_all_versions, make_sdist ] + needs: [ build_and_test_wheels, make_sdist ] environment: pypi permissions: id-token: write diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index 83bee63e86..412700cbc0 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -1,6 +1,10 @@ on: workflow_dispatch: - + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + name: Upload Prerelease Assets jobs: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b99ce2f3ea..8ed0870633 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,10 @@ on: workflow_dispatch: - + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + name: Upload Release Assets jobs: diff --git a/.github/workflows/zigbuild.yml b/.github/workflows/zigbuild.yml index ae39dd730e..6b39211da1 100644 --- a/.github/workflows/zigbuild.yml +++ b/.github/workflows/zigbuild.yml @@ -1,5 +1,9 @@ name: Zig Build +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: push: paths-ignore: diff --git a/.gitignore b/.gitignore index 001321b5cd..d62eca0468 100644 --- a/.gitignore +++ b/.gitignore @@ -91,7 +91,6 @@ cmocka/ zig-cache/ zig-out/ .cache -bindings/rust/sys/src/bindings.rs ################## ## PyCharm Project diff --git a/CMakeLists.txt b/CMakeLists.txt index c725ac591d..033db0965d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # CMake setup for Unicorn 2. # By Huitao Chen & Nguyen Anh Quynh, 2019-2020 -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.5...3.20) # Only required for MSVC, but we can't know the compiler at this point because we haven't # called enable_language() or project(), and if we did that it would lock in the old @@ -71,7 +71,7 @@ set(CMAKE_C_STANDARD 11) set(UNICORN_VERSION_MAJOR 2) set(UNICORN_VERSION_MINOR 1) -set(UNICORN_VERSION_PATCH 3) +set(UNICORN_VERSION_PATCH 4) include(cmake/bundle_static.cmake) @@ -169,17 +169,18 @@ else() execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine OUTPUT_VARIABLE UC_COMPILER_VERSION) - string(FIND "${UC_COMPILER_VERSION}" "i686" UC_RET) - if(${UC_RET} GREATER_EQUAL "0") + if(UC_COMPILER_VERSION MATCHES "^i686.*") set(UNICORN_TARGET_ARCH "i386") set(UNICORN_CFLAGS -m32 -static-libgcc) # Workaround for github action bugs set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - else() + elseif(UC_COMPILER_VERSION MATCHES "^x86_64.*") set(UNICORN_TARGET_ARCH "i386") set(UNICORN_CFLAGS -m64 -mcx16) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m64") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m64") + elseif(UC_COMPILER_VERSION MATCHES "^aarch64.*") + set(UNICORN_TARGET_ARCH "aarch64") endif() elseif(ANDROID_ABI) string(FIND "${ANDROID_ABI}" "arm64" UC_RET) diff --git a/Cargo.toml b/Cargo.toml index 81fa746ef0..5729ac742a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,17 @@ [workspace] -default-members = ["bindings/rust"] -members = ["bindings/rust", "bindings/rust/sys"] +members = ["bindings/rust/unicorn-engine"] resolver = "2" [workspace.package] rust-version = "1.85.0" -version = "2.1.3" -authors = ["Ziqiao Kong", "Lukas Seidel", "Amaan Qureshi "] +version = "2.1.5" +authors = ["Ziqiao Kong ", "Lukas Seidel", "Amaan Qureshi "] keywords = ["unicorn", "cpu", "emulator", "bindings"] categories = ["api-bindings", "emulators", "no-std", "virtualization"] documentation = "https://github.com/unicorn-engine/unicorn/wiki" edition = "2024" license = "GPL-2.0" -readme = "README.md" +readme = "./bindings/rust/sys/README.md" repository = "https://github.com/unicorn-engine/unicorn" description = "Rust bindings for the Unicorn emulator with utility functions" @@ -29,3 +28,78 @@ use_self = "allow" pedantic = { level = "warn", priority = -1 } nursery = { level = "warn", priority = -1 } cargo = { level = "warn", priority = -1 } + +# Root package +[package] +name = "unicorn-engine-sys" +version.workspace = true +authors.workspace = true +keywords.workspace = true +categories = [ + "api-bindings", + "emulators", + "external-ffi-bindings", + "no-std", + "virtualization", +] +documentation.workspace = true +edition.workspace = true +license.workspace = true +readme = "README.md" +repository.workspace = true +description.workspace = true +links = "unicorn" +# Cargo package --list +exclude = [ + "/docs", + "/bindings/dotnet", + "/bindings/go", + "/bindings/haskell", + "/bindings/java", + "/bindings/pascal", + "/bindings/python", + "/bindings/ruby", + "/bindings/vb6", + "/bindings/zig", + "/samples", + "/tests", +] + +[lib] +path = "bindings/rust/sys/src/lib.rs" + +[lints] +workspace = true + +[build-dependencies] +bindgen = "0.71.1" +cc = { version = "1.2.17" } +cmake = { version = "0.1.54" } +heck = "0.5.0" +pkg-config = { version = "0.3.32" } + +[features] +default = ["arch_all"] +dynamic_linkage = [] +arch_all = [ + "arch_x86", + "arch_arm", + "arch_aarch64", + "arch_riscv", + "arch_mips", + "arch_sparc", + "arch_m68k", + "arch_ppc", + "arch_s390x", + "arch_tricore", +] +arch_x86 = [] +arch_arm = [] +arch_aarch64 = ["arch_arm"] +arch_riscv = [] +arch_mips = [] +arch_sparc = [] +arch_m68k = [] +arch_ppc = [] +arch_s390x = [] +arch_tricore = [] diff --git a/ChangeLog b/ChangeLog index 58874c39d4..f7cd0ae1ed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,71 @@ This file details the changelog of Unicorn Engine. +------------------------------- +[Version 2.1.4]: September 9th, 2025 + +Hello everyone. It has been a while since last release and we are releasing Unicorn 2.1.4. Though it is a patch release, there are some highlights worth mentioning. + +The very first thing is that, Unicorn (finally!) offers consistent PC guarantee in all cases. Well, it might sound weird that why it was not. Generally QEMU is not designed to keep PC synced in all cases for performance and Unicorn once put necessary hacks but those hacks were too hard to maintain. Now we have architecture agnostic mechanism to offer the PC guarantee. + +In addition, we offer a standalone unicorn Rust crate `unicorn-engine-sys` to allows users to build their own bindings since v2.1.4. There are also lots of bindings improvements contained in this release. + +We also fix the building and distribution issues for macos ARM and distribute wheels again. Our friend @patryk4815 from pwndbg helps sort this out. Kudos to him! + +For 2.2.0, personally I wish I could work it out before the end of this year, by merging lots of pending big PRs but my time budget is relatively limited recently. Please aware that 2.2.0 would probably bump QEMU version to 5.1.0 or even higher so semantics could be changed. Any help is highly welcome and please contact @wtdcode if you are keen. + +Lastly, I would like to express my deep gratitude to all contributors that help make this release happen, specifically @Evian-Zhang for Rust improvements and unicornafl integration, @Antelox for consistent contributions on our workflows, @amaanq for various huge work, reviews and Rust bindings split, @PhilippTakacs for PR reviews and fix. Again, thanks for every contributor! + +Below goes the auto generated release notes. Starting from this tag, the release note will switch to a short passage plus Github generated contents because this makes it easier to follow big changes. + +## What's Changed +* bindings/zig: Fix sample_riscv_zig partial writes and logging by @fervagar in https://github.com/unicorn-engine/unicorn/pull/2133 +* Fix physical address truncation on 32-bit systems with addressing extensions by @ExhoAR22 in https://github.com/unicorn-engine/unicorn/pull/2139 +* refactor(lib): mark pointers as const where possible by @amaanq in https://github.com/unicorn-engine/unicorn/pull/2140 +* bindings: ruby: fix unexpected uc_query result pointer type by @anthraxx in https://github.com/unicorn-engine/unicorn/pull/1962 +* bindings: ruby: fix version identifier to 2.1.3 by @anthraxx in https://github.com/unicorn-engine/unicorn/pull/2142 +* feat(arm): add an `ESR` register by @amaanq in https://github.com/unicorn-engine/unicorn/pull/2155 +* fix(rust): watch all source and header files by @amaanq in https://github.com/unicorn-engine/unicorn/pull/2159 +* feat(rust): improve ARM CP register ergonomics by @amaanq in https://github.com/unicorn-engine/unicorn/pull/2160 +* fix(m68k): correct SR register read by @amaanq in https://github.com/unicorn-engine/unicorn/pull/2161 +* fix(python): catch `BaseException` in wrappers instead of `Exception` by @amaanq in https://github.com/unicorn-engine/unicorn/pull/2163 +* Remove the size limit for memory read and write (revamped) by @rliebig in https://github.com/unicorn-engine/unicorn/pull/2144 +* Loongarch port by @wtdcode in https://github.com/unicorn-engine/unicorn/pull/2164 +* S390x registers by @wtdcode in https://github.com/unicorn-engine/unicorn/pull/2167 +* Add from_handle_with_data method by @Evian-Zhang in https://github.com/unicorn-engine/unicorn/pull/2169 +* Make Unicorn struct clone-able by @Evian-Zhang in https://github.com/unicorn-engine/unicorn/pull/2170 +* Add Display and Error impl for uc_error for Rust bindings by @Evian-Zhang in https://github.com/unicorn-engine/unicorn/pull/2171 +* Add edge generated callback by @Evian-Zhang in https://github.com/unicorn-engine/unicorn/pull/2176 +* Correctly restore skip_sync_pc_on_exit by @Evian-Zhang in https://github.com/unicorn-engine/unicorn/pull/2181 +* Added CFG check and standalone flag for .NET binding by @AdvDebug in https://github.com/unicorn-engine/unicorn/pull/2182 +* qemu/configure: make strings command can be redefined by ${STRINGS} by @clan in https://github.com/unicorn-engine/unicorn/pull/2186 +* fix x86 pc by @wtdcode in https://github.com/unicorn-engine/unicorn/pull/2187 +* Patch from Saferewrite by @wtdcode in https://github.com/unicorn-engine/unicorn/pull/2188 +* fix incorrect ret of trampoline `closure` in `alloc_code_gen_buffer` by @HyperSine in https://github.com/unicorn-engine/unicorn/pull/2197 +* reset invalid_error before ram_block_add by @PhilippTakacs in https://github.com/unicorn-engine/unicorn/pull/2189 +* add uc_mem_read_virtual by @PhilippTakacs in https://github.com/unicorn-engine/unicorn/pull/2121 +* Minor fixes for vmem apis by @wtdcode in https://github.com/unicorn-engine/unicorn/pull/2199 +* glib_compat/glib_compact: Clear the buffer in g_hash_table_resize by @MarsDoge in https://github.com/unicorn-engine/unicorn/pull/2219 +* Enable install for rust bindings by @wtdcode in https://github.com/unicorn-engine/unicorn/pull/2224 +* Remove ninja installation from macos runners by @scribam in https://github.com/unicorn-engine/unicorn/pull/2225 +* Fix `read_sprr_perm` for Apple real CPUs and GitHub Actions; enable Apple ARM64 wheel builds on PyPI. Fixes #2033. by @patryk4815 in https://github.com/unicorn-engine/unicorn/pull/2227 +* Bump cmake minimum required version to 3.10 by @scribam in https://github.com/unicorn-engine/unicorn/pull/2226 +* Add support for clangarm64 by @scribam in https://github.com/unicorn-engine/unicorn/pull/2228 +* Revert "glib_compat/glib_compact: Clear the buffer in g_hash_table_resize" by @wtdcode in https://github.com/unicorn-engine/unicorn/pull/2220 +* Python bindings: Use ABI3 wheels by @Antelox in https://github.com/unicorn-engine/unicorn/pull/2223 +* concurrent control by @wtdcode in https://github.com/unicorn-engine/unicorn/pull/2235 + +## New Contributors +* @fervagar made their first contribution in https://github.com/unicorn-engine/unicorn/pull/2133 +* @ExhoAR22 made their first contribution in https://github.com/unicorn-engine/unicorn/pull/2139 +* @anthraxx made their first contribution in https://github.com/unicorn-engine/unicorn/pull/1962 +* @rliebig made their first contribution in https://github.com/unicorn-engine/unicorn/pull/2144 +* @AdvDebug made their first contribution in https://github.com/unicorn-engine/unicorn/pull/2182 +* @HyperSine made their first contribution in https://github.com/unicorn-engine/unicorn/pull/2197 +* @MarsDoge made their first contribution in https://github.com/unicorn-engine/unicorn/pull/2219 +* @patryk4815 made their first contribution in https://github.com/unicorn-engine/unicorn/pull/2227 + +**Full Changelog**: https://github.com/unicorn-engine/unicorn/compare/v2.1.3...v2.1.4 + ------------------------------- [Version 2.1.3]: March 7th, 2025 diff --git a/README.md b/README.md index 293d05db01..3544750592 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ Contact [Contact us](http://www.unicorn-engine.org/contact/) via mailing list, email or twitter for any questions. +Join [our group](https://t.me/+lnNl0fPpyCYzZmVh) for instant feedback. + Contribute ---------- @@ -55,5 +57,4 @@ We also maintain a list of more challenged problems in [milestones](https://gith Please send pull request to our [dev branch](https://github.com/unicorn-engine/unicorn/tree/dev). -[CREDITS.TXT](CREDITS.TXT) records important contributors of our project. - +[CREDITS.TXT](CREDITS.TXT) records important contributors of our project. \ No newline at end of file diff --git a/bindings/dotnet/UnicornEngine/Const/Common.fs b/bindings/dotnet/UnicornEngine/Const/Common.fs index addce7b7c6..4de99f01a4 100644 --- a/bindings/dotnet/UnicornEngine/Const/Common.fs +++ b/bindings/dotnet/UnicornEngine/Const/Common.fs @@ -8,11 +8,11 @@ open System module Common = let UC_API_MAJOR = 2 let UC_API_MINOR = 1 - let UC_API_PATCH = 3 + let UC_API_PATCH = 4 let UC_API_EXTRA = 255 let UC_VERSION_MAJOR = 2 let UC_VERSION_MINOR = 1 - let UC_VERSION_PATCH = 3 + let UC_VERSION_PATCH = 4 let UC_VERSION_EXTRA = 255 let UC_SECOND_SCALE = 1000000 let UC_MILISECOND_SCALE = 1000 @@ -79,6 +79,12 @@ module Common = let UC_ERR_RESOURCE = 20 let UC_ERR_EXCEPTION = 21 let UC_ERR_OVERFLOW = 22 + + let UC_PROT_NONE = 0 + let UC_PROT_READ = 1 + let UC_PROT_WRITE = 2 + let UC_PROT_EXEC = 4 + let UC_PROT_ALL = 7 let UC_MEM_READ = 16 let UC_MEM_WRITE = 17 let UC_MEM_FETCH = 18 @@ -146,12 +152,6 @@ module Common = let UC_CTL_TLB_TYPE = 12 let UC_CTL_TCG_BUFFER_SIZE = 13 let UC_CTL_CONTEXT_MODE = 14 - - let UC_PROT_NONE = 0 - let UC_PROT_READ = 1 - let UC_PROT_WRITE = 2 - let UC_PROT_EXEC = 4 - let UC_PROT_ALL = 7 let UC_CTL_CONTEXT_CPU = 1 let UC_CTL_CONTEXT_MEMORY = 2 diff --git a/bindings/dotnet/UnicornEngine/Const/Sparc.fs b/bindings/dotnet/UnicornEngine/Const/Sparc.fs index 8350af5c14..89a55b0ef2 100644 --- a/bindings/dotnet/UnicornEngine/Const/Sparc.fs +++ b/bindings/dotnet/UnicornEngine/Const/Sparc.fs @@ -136,7 +136,8 @@ module Sparc = let UC_SPARC_REG_Y = 86 let UC_SPARC_REG_XCC = 87 let UC_SPARC_REG_PC = 88 - let UC_SPARC_REG_ENDING = 89 + let UC_SPARC_REG_PSR = 89 + let UC_SPARC_REG_ENDING = 90 let UC_SPARC_REG_O6 = 84 let UC_SPARC_REG_I6 = 67 diff --git a/bindings/dotnet/UnicornEngine/UnicornEngine.fsproj b/bindings/dotnet/UnicornEngine/UnicornEngine.fsproj index 6ada4d0518..0c02ef3bfd 100644 --- a/bindings/dotnet/UnicornEngine/UnicornEngine.fsproj +++ b/bindings/dotnet/UnicornEngine/UnicornEngine.fsproj @@ -6,7 +6,7 @@ Copyright © Antonio Parata 2016 https://github.com/unicorn-engine/unicorn .NET bindings for unicorn - 2.1.3 + 2.1.4 0c21f1c1-2725-4a46-9022-1905f85822a5 true true diff --git a/bindings/dotnet/UnicornSamples/UnicornSamples.csproj b/bindings/dotnet/UnicornSamples/UnicornSamples.csproj index facc1e97f1..28d85c86c0 100644 --- a/bindings/dotnet/UnicornSamples/UnicornSamples.csproj +++ b/bindings/dotnet/UnicornSamples/UnicornSamples.csproj @@ -6,7 +6,7 @@ UnicornSamples Copyright © Antonio Parata 2016 https://github.com/unicorn-engine/unicorn - 2.1.3 + 2.1.4 {B80B5987-1E24-4309-8BF9-C4F91270F21C} true diff --git a/bindings/go/unicorn/sparc_const.go b/bindings/go/unicorn/sparc_const.go index e836c8c515..0e0d917219 100644 --- a/bindings/go/unicorn/sparc_const.go +++ b/bindings/go/unicorn/sparc_const.go @@ -131,7 +131,8 @@ const ( SPARC_REG_Y = 86 SPARC_REG_XCC = 87 SPARC_REG_PC = 88 - SPARC_REG_ENDING = 89 + SPARC_REG_PSR = 89 + SPARC_REG_ENDING = 90 SPARC_REG_O6 = 84 SPARC_REG_I6 = 67 ) \ No newline at end of file diff --git a/bindings/go/unicorn/uc.c b/bindings/go/unicorn/uc.c index 1f88c182e2..3ee067a001 100644 --- a/bindings/go/unicorn/uc.c +++ b/bindings/go/unicorn/uc.c @@ -24,6 +24,82 @@ uc_err uc_reg_write_batch_helper(uc_engine *handle, int *regs, uint64_t *val_in, return ret; } +uc_err uc_ctl_get_mode_helper(uc_engine *handle, int *mode) { + return uc_ctl(handle, UC_CTL_READ(UC_CTL_UC_MODE, 1), (mode)); +} + +uc_err uc_ctl_get_page_size_helper(uc_engine *handle, uint32_t *ptr) { + return uc_ctl(handle, UC_CTL_READ(UC_CTL_UC_PAGE_SIZE, 1), (ptr)); +} + +uc_err uc_ctl_set_page_size_helper(uc_engine *handle, uint32_t page_size) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_UC_PAGE_SIZE, 1), (page_size)); +} + +uc_err uc_ctl_get_arch_helper(uc_engine *handle, int *arch) { + return uc_ctl(handle, UC_CTL_READ(UC_CTL_UC_ARCH, 1), (arch)); +} + +uc_err uc_ctl_get_timeout_helper(uc_engine *handle, uint64_t *ptr) { + return uc_ctl(handle, UC_CTL_READ(UC_CTL_UC_TIMEOUT, 1), (ptr)); +} + +uc_err uc_ctl_exits_enable_helper(uc_engine *handle) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_UC_USE_EXITS, 1), 1); +} + +uc_err uc_ctl_exits_disable_helper(uc_engine *handle) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_UC_USE_EXITS, 1), 0); +} + +uc_err uc_ctl_get_exits_cnt_helper(uc_engine *handle, size_t *ptr) { + return uc_ctl(handle, UC_CTL_READ(UC_CTL_UC_EXITS_CNT, 1), (ptr)); +} + +uc_err uc_ctl_get_exits_helper(uc_engine *handle, uint64_t *exits, size_t len) { + return uc_ctl(handle, UC_CTL_READ(UC_CTL_UC_EXITS, 2), (exits), (len)); +} + +uc_err uc_ctl_set_exits_helper(uc_engine *handle, uint64_t *exits, size_t len) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_UC_EXITS, 2), (exits), (len)); +} + +uc_err uc_ctl_get_cpu_model_helper(uc_engine *handle, int *model) { + return uc_ctl(handle, UC_CTL_READ(UC_CTL_CPU_MODEL, 1), (model)); +} + uc_err uc_ctl_set_cpu_model_helper(uc_engine *handle, int model) { - return uc_ctl_set_cpu_model(handle, model); + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_CPU_MODEL, 1), (model)); +} + +uc_err uc_ctl_remove_cache_helper(uc_engine *handle, uint64_t address, uint64_t end) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_TB_REMOVE_CACHE, 2), (address), (end)); +} + +uc_err uc_ctl_request_cache_helper(uc_engine *handle, uint64_t address, uc_tb *tb) { + return uc_ctl(handle, UC_CTL_READ_WRITE(UC_CTL_TB_REQUEST_CACHE, 2), (address), (tb)); +} + +uc_err uc_ctl_flush_tb_helper(uc_engine *handle) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_TB_FLUSH, 0)); +} + +uc_err uc_ctl_flush_tlb_helper(uc_engine *handle) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_TLB_FLUSH, 0)); +} + +uc_err uc_ctl_tlb_mode_helper(uc_engine *handle, int mode) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_TLB_TYPE, 1), (mode)); +} + +uc_err uc_ctl_get_tcg_buffer_size_helper(uc_engine *handle, uint32_t *size) { + return uc_ctl(handle, UC_CTL_READ(UC_CTL_TCG_BUFFER_SIZE, 1), (size)); +} + +uc_err uc_ctl_set_tcg_buffer_size_helper(uc_engine *handle, uint32_t size) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_TCG_BUFFER_SIZE, 1), (size)); +} + +uc_err uc_ctl_context_mode_helper(uc_engine *handle, int mode) { + return uc_ctl(handle, UC_CTL_WRITE(UC_CTL_CONTEXT_MODE, 1), (mode)); } diff --git a/bindings/go/unicorn/uc.h b/bindings/go/unicorn/uc.h index f9bbfcf174..f1fbc918b4 100644 --- a/bindings/go/unicorn/uc.h +++ b/bindings/go/unicorn/uc.h @@ -1,3 +1,22 @@ uc_err uc_reg_read_batch_helper(uc_engine *handle, int *regs, uint64_t *val_out, int count); uc_err uc_reg_write_batch_helper(uc_engine *handle, int *regs, uint64_t *val_in, int count); +uc_err uc_ctl_get_mode_helper(uc_engine *handle, int *mode); +uc_err uc_ctl_get_page_size_helper(uc_engine *handle, uint32_t *ptr); +uc_err uc_ctl_set_page_size_helper(uc_engine *handle, uint32_t page_size); +uc_err uc_ctl_get_arch_helper(uc_engine *handle, int *arch); +uc_err uc_ctl_get_timeout_helper(uc_engine *handle, uint64_t *ptr); +uc_err uc_ctl_exits_enable_helper(uc_engine *handle); +uc_err uc_ctl_exits_disable_helper(uc_engine *handle); +uc_err uc_ctl_get_exits_cnt_helper(uc_engine *handle, size_t *ptr); +uc_err uc_ctl_get_exits_helper(uc_engine *handle, uint64_t *exits, size_t len); +uc_err uc_ctl_set_exits_helper(uc_engine *handle, uint64_t *exits, size_t len); +uc_err uc_ctl_get_cpu_model_helper(uc_engine *handle, int *model); uc_err uc_ctl_set_cpu_model_helper(uc_engine *handle, int model); +uc_err uc_ctl_remove_cache_helper(uc_engine *handle, uint64_t address, uint64_t end); +uc_err uc_ctl_request_cache_helper(uc_engine *handle, uint64_t address, uc_tb *tb); +uc_err uc_ctl_flush_tb_helper(uc_engine *handle); +uc_err uc_ctl_flush_tlb_helper(uc_engine *handle); +uc_err uc_ctl_tlb_mode_helper(uc_engine *handle, int mode); +uc_err uc_ctl_get_tcg_buffer_size_helper(uc_engine *handle, uint32_t *size); +uc_err uc_ctl_set_tcg_buffer_size_helper(uc_engine *handle, uint32_t size); +uc_err uc_ctl_context_mode_helper(uc_engine *handle, int mode); diff --git a/bindings/go/unicorn/unicorn.go b/bindings/go/unicorn/unicorn.go index c1e5793cfc..dc30cd2911 100644 --- a/bindings/go/unicorn/unicorn.go +++ b/bindings/go/unicorn/unicorn.go @@ -59,7 +59,27 @@ type Unicorn interface { Handle() *C.uc_engine RegWriteX86Msr(reg uint64, val uint64) error RegReadX86Msr(reg uint64) (uint64, error) + + GetMode() (int, error) + GetPageSize() (uint32, error) + SetPageSize(pageSize uint32) error + GetArch() (int, error) + GetTimeout() (uint64, error) + ExitsEnable() error + ExitsDisable() error + GetExitsCnt() (uint32, error) + GetExits() ([]uint64, error) + SetExits(exits []uint64) error + GetCPUModel() (int, error) SetCPUModel(model int) error + RemoveCache(address, end uint64) error + RequestCache(address uint64) (UcTb, error) + FlushTB() error + FlushTLB() error + TLBMode(mode int) error + GetTCGBufferSize() (uint32, error) + SetTCGBufferSize(size uint32) error + ContextMode(mode int) error } type uc struct { @@ -72,6 +92,12 @@ type UcOptions struct { Timeout, Count uint64 } +type UcTb struct { + Pc uint64 + Icount uint16 + Size uint16 +} + func Version() (int, int) { var major, minor C.uint C.uc_version(&major, &minor) @@ -107,7 +133,13 @@ func (u *uc) Close() (err error) { } func (u *uc) StartWithOptions(begin, until uint64, options *UcOptions) error { - ucerr := C.uc_emu_start(u.handle, C.uint64_t(begin), C.uint64_t(until), C.uint64_t(options.Timeout), C.size_t(options.Count)) + ucerr := C.uc_emu_start( + u.handle, + C.uint64_t(begin), + C.uint64_t(until), + C.uint64_t(options.Timeout), + C.size_t(options.Count), + ) return errReturn(ucerr) } @@ -187,14 +219,18 @@ func (u *uc) MemWrite(addr uint64, data []byte) error { if len(data) == 0 { return nil } - return errReturn(C.uc_mem_write(u.handle, C.uint64_t(addr), unsafe.Pointer(&data[0]), C.uint64_t(len(data)))) + return errReturn( + C.uc_mem_write(u.handle, C.uint64_t(addr), unsafe.Pointer(&data[0]), C.uint64_t(len(data))), + ) } func (u *uc) MemReadInto(dst []byte, addr uint64) error { if len(dst) == 0 { return nil } - return errReturn(C.uc_mem_read(u.handle, C.uint64_t(addr), unsafe.Pointer(&dst[0]), C.uint64_t(len(dst)))) + return errReturn( + C.uc_mem_read(u.handle, C.uint64_t(addr), unsafe.Pointer(&dst[0]), C.uint64_t(len(dst))), + ) } func (u *uc) MemRead(addr, size uint64) ([]byte, error) { @@ -211,11 +247,15 @@ func (u *uc) MemMap(addr, size uint64) error { } func (u *uc) MemMapPtr(addr, size uint64, prot int, ptr unsafe.Pointer) error { - return errReturn(C.uc_mem_map_ptr(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot), ptr)) + return errReturn( + C.uc_mem_map_ptr(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot), ptr), + ) } func (u *uc) MemProtect(addr, size uint64, prot int) error { - return errReturn(C.uc_mem_protect(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot))) + return errReturn( + C.uc_mem_protect(u.handle, C.uint64_t(addr), C.uint64_t(size), C.uint32_t(prot)), + ) } func (u *uc) MemUnmap(addr, size uint64) error { @@ -232,7 +272,130 @@ func (u *uc) Handle() *C.uc_engine { return u.handle } +func (u *uc) GetMode() (int, error) { + var mode C.int + ucerr := C.uc_ctl_get_mode_helper(u.handle, &mode) + return int(mode), errReturn(ucerr) +} + +func (u *uc) GetPageSize() (uint32, error) { + var ptr C.uint32_t + ucerr := C.uc_ctl_get_page_size_helper(u.handle, &ptr) + return uint32(ptr), errReturn(ucerr) +} + +func (u *uc) SetPageSize(pageSize uint32) error { + ucerr := C.uc_ctl_set_page_size_helper(u.handle, C.uint32_t(pageSize)) + return errReturn(ucerr) +} + +func (u *uc) GetArch() (int, error) { + var arch C.int + ucerr := C.uc_ctl_get_arch_helper(u.handle, &arch) + return int(arch), errReturn(ucerr) +} + +func (u *uc) GetTimeout() (uint64, error) { + var timeout C.uint64_t + ucerr := C.uc_ctl_get_timeout_helper(u.handle, &timeout) + return uint64(timeout), errReturn(ucerr) +} + +func (u *uc) ExitsEnable() error { + return errReturn(C.uc_ctl_exits_enable_helper(u.handle)) +} + +func (u *uc) ExitsDisable() error { + return errReturn(C.uc_ctl_exits_disable_helper(u.handle)) +} + +func (u *uc) GetExitsCnt() (uint32, error) { + var count C.size_t + ucerr := C.uc_ctl_get_timeout_helper(u.handle, &count) + return uint32(count), errReturn(ucerr) +} + +func (u *uc) GetExits() ([]uint64, error) { + count, err := u.GetExitsCnt() + if err != nil { + return nil, err + } + exits := make([]C.uint64_t, count) + ucerr := C.uc_ctl_get_exits_helper(u.handle, &exits[0], C.size_t(count)) + + res := make([]uint64, count) + for i := 0; i < int(count); i++ { + res[i] = uint64(exits[i]) + } + return res, errReturn(ucerr) +} + +func (u *uc) SetExits(exits []uint64) error { + cExits := make([]C.uint64_t, len(exits)) + for i := 0; i < len(exits); i++ { + cExits[i] = C.uint64_t(exits[i]) + } + ucerr := C.uc_ctl_set_exits_helper(u.handle, &cExits[0], C.size_t(len(exits))) + return errReturn(ucerr) +} + +func (u *uc) GetCPUModel() (int, error) { + var model C.int + ucerr := C.uc_ctl_get_cpu_model_helper(u.handle, &model) + return int(model), errReturn(ucerr) +} + func (u *uc) SetCPUModel(model int) error { ucerr := C.uc_ctl_set_cpu_model_helper(u.handle, C.int(model)) return errReturn(ucerr) } + +func (u *uc) RemoveCache(address, end uint64) error { + ucerr := C.uc_ctl_remove_cache_helper(u.handle, C.uint64_t(address), C.uint64_t(end)) + return errReturn(ucerr) +} + +func (u *uc) RequestCache(address uint64) (UcTb, error) { + var tb C.uc_tb + ucerr := C.uc_ctl_request_cache_helper(u.handle, C.uint64_t(address), &tb) + err := errReturn(ucerr) + if err != nil { + return UcTb{}, err + } + return UcTb{ + Pc: uint64(tb.pc), + Icount: uint16(tb.icount), + Size: uint16(tb.size), + }, nil +} + +func (u *uc) FlushTB() error { + ucerr := C.uc_ctl_flush_tb_helper(u.handle) + return errReturn(ucerr) +} + +func (u *uc) FlushTLB() error { + ucerr := C.uc_ctl_flush_tlb_helper(u.handle) + return errReturn(ucerr) +} + +func (u *uc) TLBMode(mode int) error { + ucerr := C.uc_ctl_tlb_mode_helper(u.handle, C.int(mode)) + return errReturn(ucerr) +} + +func (u *uc) GetTCGBufferSize() (uint32, error) { + var size C.uint32_t + ucerr := C.uc_ctl_get_tcg_buffer_size_helper(u.handle, &size) + return uint32(size), errReturn(ucerr) +} + +func (u *uc) SetTCGBufferSize(size uint32) error { + ucerr := C.uc_ctl_set_tcg_buffer_size_helper(u.handle, C.uint32_t(size)) + return errReturn(ucerr) +} + +func (u *uc) ContextMode(mode int) error { + ucerr := C.uc_ctl_context_mode_helper(u.handle, C.int(mode)) + return errReturn(ucerr) +} diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index f005f652dd..6f7da98d43 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -3,11 +3,11 @@ package unicorn const ( API_MAJOR = 2 API_MINOR = 1 - API_PATCH = 3 + API_PATCH = 4 API_EXTRA = 255 VERSION_MAJOR = 2 VERSION_MINOR = 1 - VERSION_PATCH = 3 + VERSION_PATCH = 4 VERSION_EXTRA = 255 SECOND_SCALE = 1000000 MILISECOND_SCALE = 1000 @@ -74,6 +74,12 @@ const ( ERR_RESOURCE = 20 ERR_EXCEPTION = 21 ERR_OVERFLOW = 22 + + PROT_NONE = 0 + PROT_READ = 1 + PROT_WRITE = 2 + PROT_EXEC = 4 + PROT_ALL = 7 MEM_READ = 16 MEM_WRITE = 17 MEM_FETCH = 18 @@ -141,12 +147,6 @@ const ( CTL_TLB_TYPE = 12 CTL_TCG_BUFFER_SIZE = 13 CTL_CONTEXT_MODE = 14 - - PROT_NONE = 0 - PROT_READ = 1 - PROT_WRITE = 2 - PROT_EXEC = 4 - PROT_ALL = 7 CTL_CONTEXT_CPU = 1 CTL_CONTEXT_MEMORY = 2 ) \ No newline at end of file diff --git a/bindings/java/pom.xml b/bindings/java/pom.xml index eb580fa5e3..778fd07881 100644 --- a/bindings/java/pom.xml +++ b/bindings/java/pom.xml @@ -6,7 +6,7 @@ org.unicorn-engine unicorn - 2.1.3 + 2.1.4 unicorn https://www.unicorn-engine.org diff --git a/bindings/java/src/main/java/unicorn/SparcConst.java b/bindings/java/src/main/java/unicorn/SparcConst.java index 5a40764244..c04921128f 100644 --- a/bindings/java/src/main/java/unicorn/SparcConst.java +++ b/bindings/java/src/main/java/unicorn/SparcConst.java @@ -133,7 +133,8 @@ public interface SparcConst { public static final int UC_SPARC_REG_Y = 86; public static final int UC_SPARC_REG_XCC = 87; public static final int UC_SPARC_REG_PC = 88; - public static final int UC_SPARC_REG_ENDING = 89; + public static final int UC_SPARC_REG_PSR = 89; + public static final int UC_SPARC_REG_ENDING = 90; public static final int UC_SPARC_REG_O6 = 84; public static final int UC_SPARC_REG_I6 = 67; diff --git a/bindings/java/src/main/java/unicorn/UnicornConst.java b/bindings/java/src/main/java/unicorn/UnicornConst.java index 2fca78c336..b562494e61 100644 --- a/bindings/java/src/main/java/unicorn/UnicornConst.java +++ b/bindings/java/src/main/java/unicorn/UnicornConst.java @@ -5,11 +5,11 @@ public interface UnicornConst { public static final int UC_API_MAJOR = 2; public static final int UC_API_MINOR = 1; - public static final int UC_API_PATCH = 3; + public static final int UC_API_PATCH = 4; public static final int UC_API_EXTRA = 255; public static final int UC_VERSION_MAJOR = 2; public static final int UC_VERSION_MINOR = 1; - public static final int UC_VERSION_PATCH = 3; + public static final int UC_VERSION_PATCH = 4; public static final int UC_VERSION_EXTRA = 255; public static final int UC_SECOND_SCALE = 1000000; public static final int UC_MILISECOND_SCALE = 1000; @@ -76,6 +76,12 @@ public interface UnicornConst { public static final int UC_ERR_RESOURCE = 20; public static final int UC_ERR_EXCEPTION = 21; public static final int UC_ERR_OVERFLOW = 22; + + public static final int UC_PROT_NONE = 0; + public static final int UC_PROT_READ = 1; + public static final int UC_PROT_WRITE = 2; + public static final int UC_PROT_EXEC = 4; + public static final int UC_PROT_ALL = 7; public static final int UC_MEM_READ = 16; public static final int UC_MEM_WRITE = 17; public static final int UC_MEM_FETCH = 18; @@ -143,12 +149,6 @@ public interface UnicornConst { public static final int UC_CTL_TLB_TYPE = 12; public static final int UC_CTL_TCG_BUFFER_SIZE = 13; public static final int UC_CTL_CONTEXT_MODE = 14; - - public static final int UC_PROT_NONE = 0; - public static final int UC_PROT_READ = 1; - public static final int UC_PROT_WRITE = 2; - public static final int UC_PROT_EXEC = 4; - public static final int UC_PROT_ALL = 7; public static final int UC_CTL_CONTEXT_CPU = 1; public static final int UC_CTL_CONTEXT_MEMORY = 2; diff --git a/bindings/pascal/unicorn/SparcConst.pas b/bindings/pascal/unicorn/SparcConst.pas index 1f0abb3e01..6bcae37b7f 100644 --- a/bindings/pascal/unicorn/SparcConst.pas +++ b/bindings/pascal/unicorn/SparcConst.pas @@ -134,7 +134,8 @@ interface UC_SPARC_REG_Y = 86; UC_SPARC_REG_XCC = 87; UC_SPARC_REG_PC = 88; - UC_SPARC_REG_ENDING = 89; + UC_SPARC_REG_PSR = 89; + UC_SPARC_REG_ENDING = 90; UC_SPARC_REG_O6 = 84; UC_SPARC_REG_I6 = 67; diff --git a/bindings/pascal/unicorn/UnicornConst.pas b/bindings/pascal/unicorn/UnicornConst.pas index 0716ec3e4e..07e781c42c 100644 --- a/bindings/pascal/unicorn/UnicornConst.pas +++ b/bindings/pascal/unicorn/UnicornConst.pas @@ -6,11 +6,11 @@ interface const UC_API_MAJOR = 2; UC_API_MINOR = 1; - UC_API_PATCH = 3; + UC_API_PATCH = 4; UC_API_EXTRA = 255; UC_VERSION_MAJOR = 2; UC_VERSION_MINOR = 1; - UC_VERSION_PATCH = 3; + UC_VERSION_PATCH = 4; UC_VERSION_EXTRA = 255; UC_SECOND_SCALE = 1000000; UC_MILISECOND_SCALE = 1000; @@ -77,6 +77,12 @@ interface UC_ERR_RESOURCE = 20; UC_ERR_EXCEPTION = 21; UC_ERR_OVERFLOW = 22; + + UC_PROT_NONE = 0; + UC_PROT_READ = 1; + UC_PROT_WRITE = 2; + UC_PROT_EXEC = 4; + UC_PROT_ALL = 7; UC_MEM_READ = 16; UC_MEM_WRITE = 17; UC_MEM_FETCH = 18; @@ -144,12 +150,6 @@ interface UC_CTL_TLB_TYPE = 12; UC_CTL_TCG_BUFFER_SIZE = 13; UC_CTL_CONTEXT_MODE = 14; - - UC_PROT_NONE = 0; - UC_PROT_READ = 1; - UC_PROT_WRITE = 2; - UC_PROT_EXEC = 4; - UC_PROT_ALL = 7; UC_CTL_CONTEXT_CPU = 1; UC_CTL_CONTEXT_MEMORY = 2; diff --git a/bindings/python/Makefile b/bindings/python/Makefile index 363d646f80..f301494a25 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -66,7 +66,7 @@ sdist3_win: python3 setup.py sdist register upload clean: - rm -rf src/ dist/ build/ MANIFEST + rm -rf src/ dist/ build/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll rm -rf unicorn/lib unicorn/include diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index ee5c81a250..679f1cb1f3 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=64", "build", "wheel", "setuptools-scm"] +requires = ["setuptools>=64", "build", "setuptools-scm"] build-backend = "setuptools.build_meta" [project] diff --git a/bindings/python/setup.py b/bindings/python/setup.py index 12d152ff0c..52cbbff38a 100755 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -148,5 +148,6 @@ def run(self): setup( cmdclass={'build_py': CustomBuild, 'sdist': CustomSDist}, - has_ext_modules=lambda: True, # It's not a Pure Python wheel + has_ext_modules=lambda: True, # It's not a Pure Python wheel, + options={"bdist_wheel": {"py_limited_api": "cp37"}}, # to have ABI3 tagged wheel ) diff --git a/bindings/python/unicorn/sparc_const.py b/bindings/python/unicorn/sparc_const.py index 77b8c004c7..f05651b647 100644 --- a/bindings/python/unicorn/sparc_const.py +++ b/bindings/python/unicorn/sparc_const.py @@ -129,6 +129,7 @@ UC_SPARC_REG_Y = 86 UC_SPARC_REG_XCC = 87 UC_SPARC_REG_PC = 88 -UC_SPARC_REG_ENDING = 89 +UC_SPARC_REG_PSR = 89 +UC_SPARC_REG_ENDING = 90 UC_SPARC_REG_O6 = 84 UC_SPARC_REG_I6 = 67 diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 8fab22415b..82476d20a8 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -1,11 +1,11 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py] UC_API_MAJOR = 2 UC_API_MINOR = 1 -UC_API_PATCH = 3 +UC_API_PATCH = 4 UC_API_EXTRA = 255 UC_VERSION_MAJOR = 2 UC_VERSION_MINOR = 1 -UC_VERSION_PATCH = 3 +UC_VERSION_PATCH = 4 UC_VERSION_EXTRA = 255 UC_SECOND_SCALE = 1000000 UC_MILISECOND_SCALE = 1000 @@ -72,6 +72,12 @@ UC_ERR_RESOURCE = 20 UC_ERR_EXCEPTION = 21 UC_ERR_OVERFLOW = 22 + +UC_PROT_NONE = 0 +UC_PROT_READ = 1 +UC_PROT_WRITE = 2 +UC_PROT_EXEC = 4 +UC_PROT_ALL = 7 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 @@ -139,11 +145,5 @@ UC_CTL_TLB_TYPE = 12 UC_CTL_TCG_BUFFER_SIZE = 13 UC_CTL_CONTEXT_MODE = 14 - -UC_PROT_NONE = 0 -UC_PROT_READ = 1 -UC_PROT_WRITE = 2 -UC_PROT_EXEC = 4 -UC_PROT_ALL = 7 UC_CTL_CONTEXT_CPU = 1 UC_CTL_CONTEXT_MEMORY = 2 diff --git a/bindings/ruby/Makefile b/bindings/ruby/Makefile index bd21b57c71..93bb23bc28 100644 --- a/bindings/ruby/Makefile +++ b/bindings/ruby/Makefile @@ -5,7 +5,7 @@ # Use bundle install && rake to install gem and test install: gen_const cd unicorn_gem && rake build - cd unicorn_gem && gem install --local pkg/unicorn-engine-2.1.3.gem + cd unicorn_gem && gem install --local pkg/unicorn-engine-2.1.4.gem gen_const: cd .. && python3 const_generator.py ruby diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb index ccdeebb720..3f5f23e51f 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb @@ -131,7 +131,8 @@ module UnicornEngine UC_SPARC_REG_Y = 86 UC_SPARC_REG_XCC = 87 UC_SPARC_REG_PC = 88 - UC_SPARC_REG_ENDING = 89 + UC_SPARC_REG_PSR = 89 + UC_SPARC_REG_ENDING = 90 UC_SPARC_REG_O6 = 84 UC_SPARC_REG_I6 = 67 end \ No newline at end of file diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb index c573a6f7c0..d190233c06 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb @@ -3,11 +3,11 @@ module UnicornEngine UC_API_MAJOR = 2 UC_API_MINOR = 1 - UC_API_PATCH = 3 + UC_API_PATCH = 4 UC_API_EXTRA = 255 UC_VERSION_MAJOR = 2 UC_VERSION_MINOR = 1 - UC_VERSION_PATCH = 3 + UC_VERSION_PATCH = 4 UC_VERSION_EXTRA = 255 UC_SECOND_SCALE = 1000000 UC_MILISECOND_SCALE = 1000 @@ -74,6 +74,12 @@ module UnicornEngine UC_ERR_RESOURCE = 20 UC_ERR_EXCEPTION = 21 UC_ERR_OVERFLOW = 22 + + UC_PROT_NONE = 0 + UC_PROT_READ = 1 + UC_PROT_WRITE = 2 + UC_PROT_EXEC = 4 + UC_PROT_ALL = 7 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 @@ -141,12 +147,6 @@ module UnicornEngine UC_CTL_TLB_TYPE = 12 UC_CTL_TCG_BUFFER_SIZE = 13 UC_CTL_CONTEXT_MODE = 14 - - UC_PROT_NONE = 0 - UC_PROT_READ = 1 - UC_PROT_WRITE = 2 - UC_PROT_EXEC = 4 - UC_PROT_ALL = 7 UC_CTL_CONTEXT_CPU = 1 UC_CTL_CONTEXT_MEMORY = 2 end \ No newline at end of file diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/version.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/version.rb index df28ba5708..94851999f4 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/version.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/version.rb @@ -1,3 +1,3 @@ module Unicorn - VERSION = "2.1.3" + VERSION = "2.1.4" end diff --git a/bindings/rust/sys/Cargo.toml b/bindings/rust/sys/Cargo.toml deleted file mode 100644 index ad8c5f4499..0000000000 --- a/bindings/rust/sys/Cargo.toml +++ /dev/null @@ -1,55 +0,0 @@ -[package] -name = "unicorn-engine-sys" -version.workspace = true -authors.workspace = true -keywords.workspace = true -categories = [ - "api-bindings", - "emulators", - "external-ffi-bindings", - "no-std", - "virtualization", -] -documentation.workspace = true -edition.workspace = true -license.workspace = true -readme = "README.md" -repository.workspace = true -description.workspace = true -links = "unicorn" - -[lints] -workspace = true - -[build-dependencies] -bindgen = "0.71.1" -cc = { version = "1.2.17" } -cmake = { version = "0.1.54" } -heck = "0.5.0" -pkg-config = { version = "0.3.32" } - -[features] -default = ["arch_all"] -dynamic_linkage = [] -arch_all = [ - "arch_x86", - "arch_arm", - "arch_aarch64", - "arch_riscv", - "arch_mips", - "arch_sparc", - "arch_m68k", - "arch_ppc", - "arch_s390x", - "arch_tricore", -] -arch_x86 = [] -arch_arm = [] -arch_aarch64 = ["arch_arm"] -arch_riscv = [] -arch_mips = [] -arch_sparc = [] -arch_m68k = [] -arch_ppc = [] -arch_s390x = [] -arch_tricore = [] diff --git a/bindings/rust/sys/README.md b/bindings/rust/sys/README.md index ca03938ca6..39ee38eb28 100644 --- a/bindings/rust/sys/README.md +++ b/bindings/rust/sys/README.md @@ -57,5 +57,5 @@ Add this to your `Cargo.toml`: ``` [dependencies] -unicorn-engine-sys = "2.2.0" +unicorn-engine-sys = "2.1.4" ``` diff --git a/bindings/rust/sys/src/bindings.rs b/bindings/rust/sys/src/bindings.rs new file mode 100644 index 0000000000..44ae78fcab --- /dev/null +++ b/bindings/rust/sys/src/bindings.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/bindings/rust/COPYING b/bindings/rust/unicorn-engine/COPYING similarity index 100% rename from bindings/rust/COPYING rename to bindings/rust/unicorn-engine/COPYING diff --git a/bindings/rust/Cargo.toml b/bindings/rust/unicorn-engine/Cargo.toml similarity index 92% rename from bindings/rust/Cargo.toml rename to bindings/rust/unicorn-engine/Cargo.toml index 139b41efde..e497e34943 100644 --- a/bindings/rust/Cargo.toml +++ b/bindings/rust/unicorn-engine/Cargo.toml @@ -15,7 +15,7 @@ description.workspace = true workspace = true [dependencies] -unicorn-engine-sys = { version = "2.1.3", path = "sys", features = [], default-features = false } +unicorn-engine-sys = { version = "2.1.5", path = "../../../", features = [], default-features = false } [build-dependencies] bindgen = "0.71.1" diff --git a/bindings/rust/README.md b/bindings/rust/unicorn-engine/README.md similarity index 100% rename from bindings/rust/README.md rename to bindings/rust/unicorn-engine/README.md diff --git a/bindings/rust/src/ffi.rs b/bindings/rust/unicorn-engine/src/ffi.rs similarity index 100% rename from bindings/rust/src/ffi.rs rename to bindings/rust/unicorn-engine/src/ffi.rs diff --git a/bindings/rust/src/hook.rs b/bindings/rust/unicorn-engine/src/hook.rs similarity index 100% rename from bindings/rust/src/hook.rs rename to bindings/rust/unicorn-engine/src/hook.rs diff --git a/bindings/rust/src/lib.rs b/bindings/rust/unicorn-engine/src/lib.rs similarity index 100% rename from bindings/rust/src/lib.rs rename to bindings/rust/unicorn-engine/src/lib.rs diff --git a/bindings/rust/src/tests/arm.rs b/bindings/rust/unicorn-engine/src/tests/arm.rs similarity index 100% rename from bindings/rust/src/tests/arm.rs rename to bindings/rust/unicorn-engine/src/tests/arm.rs diff --git a/bindings/rust/src/tests/arm64.rs b/bindings/rust/unicorn-engine/src/tests/arm64.rs similarity index 100% rename from bindings/rust/src/tests/arm64.rs rename to bindings/rust/unicorn-engine/src/tests/arm64.rs diff --git a/bindings/rust/src/tests/ctl.rs b/bindings/rust/unicorn-engine/src/tests/ctl.rs similarity index 100% rename from bindings/rust/src/tests/ctl.rs rename to bindings/rust/unicorn-engine/src/tests/ctl.rs diff --git a/bindings/rust/src/tests/m68k.rs b/bindings/rust/unicorn-engine/src/tests/m68k.rs similarity index 100% rename from bindings/rust/src/tests/m68k.rs rename to bindings/rust/unicorn-engine/src/tests/m68k.rs diff --git a/bindings/rust/src/tests/mem.rs b/bindings/rust/unicorn-engine/src/tests/mem.rs similarity index 100% rename from bindings/rust/src/tests/mem.rs rename to bindings/rust/unicorn-engine/src/tests/mem.rs diff --git a/bindings/rust/src/tests/mips.rs b/bindings/rust/unicorn-engine/src/tests/mips.rs similarity index 100% rename from bindings/rust/src/tests/mips.rs rename to bindings/rust/unicorn-engine/src/tests/mips.rs diff --git a/bindings/rust/src/tests/mod.rs b/bindings/rust/unicorn-engine/src/tests/mod.rs similarity index 100% rename from bindings/rust/src/tests/mod.rs rename to bindings/rust/unicorn-engine/src/tests/mod.rs diff --git a/bindings/rust/src/tests/ppc.rs b/bindings/rust/unicorn-engine/src/tests/ppc.rs similarity index 100% rename from bindings/rust/src/tests/ppc.rs rename to bindings/rust/unicorn-engine/src/tests/ppc.rs diff --git a/bindings/rust/src/tests/riscv.rs b/bindings/rust/unicorn-engine/src/tests/riscv.rs similarity index 100% rename from bindings/rust/src/tests/riscv.rs rename to bindings/rust/unicorn-engine/src/tests/riscv.rs diff --git a/bindings/rust/src/tests/s390x.rs b/bindings/rust/unicorn-engine/src/tests/s390x.rs similarity index 100% rename from bindings/rust/src/tests/s390x.rs rename to bindings/rust/unicorn-engine/src/tests/s390x.rs diff --git a/bindings/rust/src/unicorn_const.rs b/bindings/rust/unicorn-engine/src/unicorn_const.rs similarity index 100% rename from bindings/rust/src/unicorn_const.rs rename to bindings/rust/unicorn-engine/src/unicorn_const.rs diff --git a/bindings/zig/unicorn/sparc_const.zig b/bindings/zig/unicorn/sparc_const.zig index f745e84fa8..2bab21d2c2 100644 --- a/bindings/zig/unicorn/sparc_const.zig +++ b/bindings/zig/unicorn/sparc_const.zig @@ -131,7 +131,8 @@ pub const sparcConst = enum(c_int) { SPARC_REG_Y = 86, SPARC_REG_XCC = 87, SPARC_REG_PC = 88, - SPARC_REG_ENDING = 89, + SPARC_REG_PSR = 89, + SPARC_REG_ENDING = 90, SPARC_REG_O6 = 84, SPARC_REG_I6 = 67, diff --git a/bindings/zig/unicorn/unicorn_const.zig b/bindings/zig/unicorn/unicorn_const.zig index 7991ff9783..7a24f55d41 100644 --- a/bindings/zig/unicorn/unicorn_const.zig +++ b/bindings/zig/unicorn/unicorn_const.zig @@ -3,11 +3,11 @@ pub const unicornConst = enum(c_int) { API_MAJOR = 2, API_MINOR = 1, - API_PATCH = 3, + API_PATCH = 4, API_EXTRA = 255, VERSION_MAJOR = 2, VERSION_MINOR = 1, - VERSION_PATCH = 3, + VERSION_PATCH = 4, VERSION_EXTRA = 255, SECOND_SCALE = 1000000, MILISECOND_SCALE = 1000, @@ -74,6 +74,12 @@ pub const unicornConst = enum(c_int) { ERR_RESOURCE = 20, ERR_EXCEPTION = 21, ERR_OVERFLOW = 22, + + PROT_NONE = 0, + PROT_READ = 1, + PROT_WRITE = 2, + PROT_EXEC = 4, + PROT_ALL = 7, MEM_READ = 16, MEM_WRITE = 17, MEM_FETCH = 18, @@ -141,12 +147,6 @@ pub const unicornConst = enum(c_int) { CTL_TLB_TYPE = 12, CTL_TCG_BUFFER_SIZE = 13, CTL_CONTEXT_MODE = 14, - - PROT_NONE = 0, - PROT_READ = 1, - PROT_WRITE = 2, - PROT_EXEC = 4, - PROT_ALL = 7, CTL_CONTEXT_CPU = 1, CTL_CONTEXT_MEMORY = 2, diff --git a/bindings/rust/sys/build.rs b/build.rs similarity index 94% rename from bindings/rust/sys/build.rs rename to build.rs index 45ffbddd12..f2c03d3a66 100644 --- a/bindings/rust/sys/build.rs +++ b/build.rs @@ -50,13 +50,7 @@ fn get_tool_paths_msvc(compiler: &cc::Tool) -> Option<(PathBuf, PathBuf)> { fn build_with_cmake() { let current_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - let uc_dir = current_dir - .parent() - .unwrap() - .parent() - .unwrap() - .parent() - .unwrap(); + let uc_dir = current_dir; let compiler = cc::Build::new().get_compiler(); // Initialize configuration @@ -125,20 +119,20 @@ fn build_with_cmake() { config.define("UNICORN_LOGGING", "ON"); } - // need to clear build target and append "build" to the path because - // unicorn's CMakeLists.txt doesn't properly support 'install', so we use - // the build artifacts from the build directory, which cmake crate sets - // to "/build/" let dst = config .define("UNICORN_BUILD_TESTS", "OFF") - .define("UNICORN_INSTALL", "OFF") + .define("UNICORN_INSTALL", "ON") .define("UNICORN_ARCH", archs) - .no_build_target(true) .build(); println!( "cargo:rustc-link-search=native={}", - dst.join("build").display() + dst.join("lib").display() + ); + // rhel + println!( + "cargo:rustc-link-search=native={}", + dst.join("lib64").display() ); // Lazymio(@wtdcode): Dynamic link may break. See: https://github.com/rust-lang/cargo/issues/5077 @@ -329,10 +323,7 @@ impl ParseCallbacks for Renamer { } fn generate_bindings() { - const HEADER_PATH: &str = concat!( - env!("CARGO_MANIFEST_DIR"), - "/../../../include/unicorn/unicorn.h" - ); + const HEADER_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/include/unicorn/unicorn.h"); let bitflag_enums = [ "uc_hook_type", @@ -359,9 +350,9 @@ fn generate_bindings() { .generate() .expect("Failed to generate bindings"); - let bindings_rs = "src/bindings.rs"; + let bindings_rs = PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("bindings.rs"); bindings - .write_to_file(bindings_rs) + .write_to_file(&bindings_rs) .unwrap_or_else(|_| panic!("Failed to write bindings into path: {bindings_rs:?}")); } diff --git a/build.zig.zon b/build.zig.zon index ce9de9d143..5d7852e0e3 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = .unicorn, - .version = "2.1.3", + .version = "2.1.4", .minimum_zig_version = "0.14.0-dev.3445+6c3cbb0c8", .fingerprint = 0x58fbd83f3bf465b6, .paths = .{""}, diff --git a/docs/FAQ.md b/docs/FAQ.md index 6964f6aeb9..ccac896392 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -9,6 +9,9 @@ Optimize your program with less instrumentation, e.g. by using `UC_HOOK_BLOCK` i ## Why do I get a wrong PC after emulation stops? +
+ For version < 2.1.4 + Updating PC is a very large overhead (10x slower in the worst case, see FAQ above) for emulation so the PC sync guarantee is explained below in several cases: - A `UC_HOOK_CODE` hook is installed. In this case, the PC is sync-ed _everywhere_ within the effective range of the hook. However, on some architectures, the PC might by sync-ed all the time if the hook is installed in any range. Note using `count` in `uc_emu_start` implies installing a `UC_HOOK_CODE` hook. @@ -33,10 +36,19 @@ mov x0, #1 mov x1, #2 ldr x0, [x1] <--- exception here and PC sync-ed here ``` + +
+ +
+ For version >= 2.1.4 + +We should always have valid PC all the time. Please report an issue for your case. + +
## I get an “Unhandled CPU Exception”, why? -Unicorn is a pure CPU emulator and usually it’s due to no handler registered for instructions like `syscall` and `SVC`. If you expect system emulation, you probably would like [qiling framework](https://github.com/qilingframework/qiling). +Unicorn is a pure CPU emulator and usually it’s due to no handler registered for instructions like `syscall` and `SVC`. If you expect syscall and userland emulation, you probably would like [qiling framework](https://github.com/qilingframework/qiling). ## I would like to instrument a specific instruction but get a `UC_ERR_HOOK`, why? diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index f7af979f5a..b4ffc6bc75 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -72,7 +72,7 @@ typedef size_t uc_hook; // Unicorn API version #define UC_API_MAJOR 2 #define UC_API_MINOR 1 -#define UC_API_PATCH 3 +#define UC_API_PATCH 4 // Release candidate version, 255 means the official release. #define UC_API_EXTRA 255 diff --git a/qemu/configure b/qemu/configure index af3781c34e..cfd344f759 100755 --- a/qemu/configure +++ b/qemu/configure @@ -2152,39 +2152,13 @@ fi if [ "$darwin" = "yes" ] ; then cat > $TMPC << EOF #include -int main() { pthread_jit_write_protect_np(0); return 0;} +int main() { pthread_jit_write_protect_supported_np(); return 0;} EOF if ! compile_prog ""; then have_pthread_jit_protect='no' else have_pthread_jit_protect='yes' fi - - if test "$have_pthread_jit_protect" = "yes" ; then - cat > $TMPC << EOF -#include "stdint.h" -int main() { - uint64_t v; - - __asm__ __volatile__("isb sy\n" - "mrs %0, S3_6_c15_c1_5\n" - : "=r"(v)::"memory"); - // In Apple Hypervisor virtualized environment (EL1), this value is not accessbile - // but pthread_jit_write_protect_np essentially is a no-op. - return 0; -} -EOF - if ! compile_prog ""; then - have_sprr_mrs='no' - else - $TMPE - if [ $? -eq 0 ]; then - have_sprr_mrs='yes' - else - have_sprr_mrs='no' - fi - fi - fi fi ########################################## @@ -2565,10 +2539,6 @@ if test "$have_pthread_jit_protect" = "yes" ; then echo "HAVE_PTHREAD_JIT_PROTECT=y" >> $config_host_mak fi -if test "$have_sprr_mrs" = "yes" ; then - echo "HAVE_SPRR_MRS=y" >> $config_host_mak -fi - # Hold two types of flag: # CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on # a thread we have a handle to diff --git a/qemu/include/tcg/tcg-apple-jit.h b/qemu/include/tcg/tcg-apple-jit.h index f471403a9e..4ace2c7be9 100644 --- a/qemu/include/tcg/tcg-apple-jit.h +++ b/qemu/include/tcg/tcg-apple-jit.h @@ -30,12 +30,13 @@ #include "stdbool.h" #include "qemu/compiler.h" +#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && (defined(__arm__) || defined(__aarch64__)) + // Returns the S3_6_c15_c1_5 register's value -// Taken from +// Taken from // https://stackoverflow.com/questions/70019553/lldb-how-to-read-the-permissions-of-a-memory-region-for-a-thread // https://blog.svenpeter.dev/posts/m1_sprr_gxf/ // On Github Action (Virtualized environment), this shall always returns 0 -#if defined(HAVE_SPRR_MRS) static inline uint64_t read_sprr_perm(void) { uint64_t v; @@ -44,17 +45,12 @@ static inline uint64_t read_sprr_perm(void) : "=r"(v)::"memory"); return v; } -#else -static inline uint64_t read_sprr_perm(void) -{ - return 0; -} -#endif - -#if defined(__APPLE__) && defined(HAVE_SPRR_MRS) && defined(HAVE_PTHREAD_JIT_PROTECT) && (defined(__arm__) || defined(__aarch64__)) QEMU_UNUSED_FUNC static inline uint8_t thread_mask() { + if (!pthread_jit_write_protect_supported_np()) { + return 0; + } uint64_t v = read_sprr_perm(); if (v == 0) { @@ -75,6 +71,9 @@ QEMU_UNUSED_FUNC static inline bool thread_executable() } static inline void assert_executable(bool executable) { + if (!pthread_jit_write_protect_supported_np()) { + return; + } uint64_t v = read_sprr_perm(); if (!v) { diff --git a/qemu/util/guest-random.c b/qemu/util/guest-random.c index 7c1fe7be4f..328da3f84e 100644 --- a/qemu/util/guest-random.c +++ b/qemu/util/guest-random.c @@ -15,14 +15,17 @@ #include "qemu/guest-random.h" #include "crypto/random.h" //#include "sysemu/replay.h" - +#include +#include +#include #ifndef _MSC_VER static __thread GRand *thread_rand; +#else +static bool initialized = false; #endif static bool deterministic = true; - static int glib_random_bytes(void *buf, size_t len) { #ifndef _MSC_VER @@ -43,6 +46,26 @@ static int glib_random_bytes(void *buf, size_t len) x = g_rand_int(rand); __builtin_memcpy(buf + i, &x, i - len); } +#else + uint32_t x; + size_t i; + + if (!initialized) { + if (deterministic) { + srand(0); + } else { + srand(time(NULL)); + } + + for (i = 0; i + 4 <= len; i += 4) { + x = rand(); + memcpy(((uint8_t*)buf) + i, &x, 4); + } + if (i < len) { + x = rand(); + memcpy(((uint8_t*)buf) + i, &x, i - len); + } + } #endif return 0; } diff --git a/tests/regress/translator_buffer.py b/tests/regress/translator_buffer.py index abeff0ee58..6b323681c2 100755 --- a/tests/regress/translator_buffer.py +++ b/tests/regress/translator_buffer.py @@ -18,6 +18,7 @@ def __page_aligned(address): self.mu = Uc(UC_ARCH_X86, UC_MODE_64) self.mu.ctl_set_tlb_mode(UC_TLB_VIRTUAL) + self.mu.ctl_set_tcg_buffer_size(1 * 1024 * 1024) # 1MB regress.logger.debug("mapping code : %#x", __page_aligned(code)) regress.logger.debug("mapping stack : %#x", __page_aligned(stack)) @@ -82,8 +83,8 @@ def runTest(self): sp_base = 0x000f88001b800000 # was: 0xffff88001b800000 mg_base = 0x000f880026f02000 # was: 0xffff880026f02000 - ips = range(0x9000, 0xf000, 8) - sps = range(0x0000, 0x6000, 8) + ips = range(0x9000, 0xf000, 16) # was: ..., 8 + sps = range(0x0000, 0x6000, 16) # was: ..., 8 for i, (ip, sp) in enumerate(zip(ips, sps)): self.init_unicorn(ip_base + ip, sp_base + sp, mg_base + i * 8)