- Improved the GitHub python binding workflow: (#2072)

- Added fullMode input in workflow_dispatch
    - Take decision whether to build either in debug or release mode and if to build for all python versions according to the commit message patterns
    - Set proper artifact names
    - Removed not needed steps
    - Compacted some steps in order to leverage more the matrix feature
    - Bumped cibuildwheel action to 2.22.0
    - Run actual regress tests in place of sample scripts
- Specify optional test install in pyproject.toml with proper requirements
- Derive package version from git tags
- Add GENERATORS env var support in setup.py to specify cmake generator and minor refactoring
- Minor cleanup/refactoring for the regress test suite
- Marked some regress tests with skipIf to skip them in case of old python versions
- Marked some failing regress tests to be checked with skipIf
This commit is contained in:
@Antelox
2024-12-29 15:24:48 +01:00
committed by GitHub
parent 07e8162cca
commit 9cfd5cfac3
85 changed files with 543 additions and 838 deletions

View File

@@ -1,4 +1,4 @@
name: Build wheels with cibuildwheel
name: Build and publish wheels with cibuildwheel
on:
workflow_dispatch:
@@ -11,6 +11,14 @@ on:
options:
- '0'
- '1'
fullMode:
description: 'Full Mode'
required: false
default: ''
type: choice
options:
- '0'
- '1'
push:
paths-ignore:
- ".gitignore"
@@ -26,12 +34,12 @@ on:
env:
# Enable DEBUG flag either according to the tag release or manual override
UNICORN_DEBUG: ${{ inputs.debugMode != '' && inputs.debugMode || startsWith(github.ref, 'refs/tags') && '0' || '1' }}
UNICORN_DEBUG: ${{ inputs.debugMode != '' && inputs.debugMode || startsWith(github.ref, 'refs/tags') && '0' || contains(github.event.head_commit.message, 'CI(release)') && '0' || '1' }}
jobs:
# job to be executed for every push - testing purpose
build_wheels_python38_only:
name: Building on ${{ matrix.os }} - ${{ matrix.arch }} ${{ matrix.cibw_build }}
name: Building on ${{ matrix.os }} - ${{ matrix.arch }} - ${{ matrix.cibw_build }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@@ -39,24 +47,35 @@ jobs:
include:
# NOTE: aarch64 builds are super slow due to QEMU emulation. Making this to parallelize and speed up workflow
# i686 - manylinux
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp38-manylinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp38-manylinux*', cibw_skip: '' }
# i686 - musllinux
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp38-musllinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp38-musllinux*', cibw_skip: '' }
# x86_64 - manylinux
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp38-manylinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp38-manylinux*', cibw_skip: '' }
# x86_64 - musllinux
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp38-musllinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp38-musllinux*', cibw_skip: '' }
# aarch64 - manylinux
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp38-manylinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp38-manylinux*', cibw_skip: '' }
# aarch64 - musllinux
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp38-musllinux' }
- { os: macos-13, arch: x86_64, cibw_build: '' }
- { os: macos-latest, arch: arm64, cibw_build: '' }
- { os: windows-2019, arch: AMD64, cibw_build: '' }
- { os: windows-2019, arch: x86, cibw_build: '' }
- { os: ubuntu-latest, 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-2019, arch: AMD64, cibw_build: 'cp38*', cibw_skip: '' }
- { os: windows-2019, arch: x86, cibw_build: 'cp38*', cibw_skip: '' }
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: '🛠️ Add msbuild to PATH'
if: runner.os == 'Windows'
@@ -64,17 +83,6 @@ jobs:
with:
vs-version: '16.5'
- name: '🛠️ Win build dependencies'
if: runner.os == 'Windows'
shell: bash
run: |
choco install ninja
- name: '🛠️ macOS dependencies'
if: runner.os == 'macOS'
run: |
brew install ninja
# https://cibuildwheel.pypa.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64
- uses: actions/setup-python@v5
if: runner.os == 'macOS' && runner.arch == 'ARM64'
@@ -94,60 +102,20 @@ jobs:
arch: x64
- name: '🛠️ Set up QEMU'
if: runner.os == 'Linux'
if: runner.os == 'Linux' && matrix.arch != 'x86_64'
uses: docker/setup-qemu-action@v3
- name: '🚧 cibuildwheel run - Linux'
if: matrix.os == 'ubuntu-latest'
uses: pypa/cibuildwheel@v2.21.3
- name: '🚧 cibuildwheel run'
uses: pypa/cibuildwheel@v2.22.0
env:
CIBW_BUILD_FRONTEND: build
CIBW_BUILD: ${{ matrix.cibw_build }}*
CIBW_BUILD: ${{ matrix.cibw_build }}
CIBW_SKIP: ${{ matrix.cibw_skip }}
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_ENVIRONMENT: DEBUG=${{ env.UNICORN_DEBUG }}
CIBW_ENVIRONMENT_PASS_LINUX: DEBUG
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
with:
package-dir: bindings/python
output-dir: wheelhouse
- name: '🚧 cibuildwheel run - Windows'
if: matrix.os == 'windows-2019'
uses: pypa/cibuildwheel@v2.21.3
env:
CIBW_BUILD_FRONTEND: build
CIBW_BUILD: 'cp38*'
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_ENVIRONMENT: DEBUG=${{ env.UNICORN_DEBUG }}
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
with:
package-dir: bindings/python
output-dir: wheelhouse
- name: '🚧 cibuildwheel run - MacOS x86_84'
if: matrix.os == 'macos-13'
uses: pypa/cibuildwheel@v2.21.3
env:
CIBW_BUILD_FRONTEND: build
CIBW_BUILD: 'cp38*'
CIBW_ENVIRONMENT: SYSTEM_VERSION_COMPAT=0 DEBUG=${{ env.UNICORN_DEBUG }}
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
with:
package-dir: bindings/python
output-dir: wheelhouse
- name: '🚧 cibuildwheel run - MacOS arm64'
if: matrix.os == 'macos-latest'
uses: pypa/cibuildwheel@v2.21.3
env:
CIBW_BUILD_FRONTEND: build
CIBW_BUILD: 'cp38*'
CIBW_ENVIRONMENT: DEBUG=${{ env.UNICORN_DEBUG }}
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
CIBW_TEST_EXTRAS: test
CIBW_TEST_COMMAND: 'python -m unittest discover -v {project}/tests/regress "*.py"'
# https://github.com/pypa/cibuildwheel/pull/1169
CIBW_TEST_SKIP: "cp38-macosx_*:arm64"
with:
@@ -155,49 +123,42 @@ jobs:
output-dir: wheelhouse
# we re-tag cp38 wheel (just an old one) with py2 tag. Hacky but it works...
- name: '🚧 Python 2.7 wheels re-tagging - Windows'
if: matrix.os == 'windows-2019'
run: |
python -m pip install -U pip wheel && Get-ChildItem -Path wheelhouse/ -Filter *cp38*.whl | Foreach-Object {
python -m wheel tags --python-tag='py2' --abi-tag=none $_.FullName
break
}
- name: '🚧 Python 2.7 wheels re-tagging - Non-Windows'
if: matrix.os != 'windows-2019'
- name: '🚧 Python 2.7 wheels re-tagging'
env:
PIP_BREAK_SYSTEM_PACKAGES: 1
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 pip install -U pip wheel
python3 -m wheel tags --python-tag='py2' --abi-tag=none wheelhouse/*cp38*.whl
- uses: LizardByte/setup-python-action@master
if: (matrix.os == 'ubuntu-latest' && matrix.arch == 'x86_64' && matrix.cibw_build == 'cp38-manylinux') || matrix.os == 'macos-latest' || (matrix.os == 'windows-2019' && matrix.arch == 'AMD64')
- uses: LizardByte/setup-python-action@v2024.919.163656
if: (matrix.os == 'ubuntu-latest' && matrix.arch == 'x86_64' && matrix.cibw_build == 'cp38-manylinux*') || matrix.os == 'macos-latest' || (matrix.os == 'windows-2019' && matrix.arch == 'AMD64')
with:
python-version: 2.7
# we install and test python2.7 wheels only on native arch
- name: 'Python 2.7 tests - Windows'
if: matrix.os == 'windows-2019' && matrix.arch == 'AMD64'
shell: bash
run: |
C:\Python27\python.exe -m pip install -U pip pytest && Get-ChildItem -Path wheelhouse/ -Filter *py2*.whl | Foreach-Object {
C:\Python27\python.exe -m pip install $_.FullName
C:\Python27\python.exe -m pytest bindings/python/tests
break
}
C:/Python27/python.exe -m pip install capstone==4.0.2 wheelhouse/*py2*.whl
C:/Python27/python.exe -m unittest discover tests/regress "*.py"
# we install and test python2.7 wheels only on native arch
# 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: (matrix.os == 'ubuntu-latest' && matrix.arch == 'x86_64' && matrix.cibw_build == 'cp38-manylinux') || matrix.os == 'macos-latest'
run: python2 -m pip install wheelhouse/*py2*.whl && python2 -m pip install -U pip pytest && python2 -m pytest bindings/python/tests
if: (matrix.os == 'ubuntu-latest' && matrix.arch == 'x86_64' && matrix.cibw_build == 'cp38-manylinux*') || matrix.os == 'macos-latest'
run: |
python2 -m pip install capstone==4.0.2 wheelhouse/*py2*.whl
python2 -m unittest discover tests/regress "*.py"
- uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}-py38
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 }}
name: Building on ${{ matrix.os }} - ${{ matrix.arch }} - ${{ matrix.cibw_build }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@@ -205,54 +166,65 @@ jobs:
include:
# NOTE: aarch64 builds are super slow due to QEMU emulation. Making this to parallelize and speed up workflow
# i686 - manylinux
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp37-manylinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp39-manylinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp310-manylinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp311-manylinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp312-manylinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp313-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' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp39-musllinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp310-musllinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp311-musllinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp312-musllinux' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp313-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' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp39-manylinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp310-manylinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp311-manylinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp312-manylinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp313-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' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp39-musllinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp310-musllinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp311-musllinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp312-musllinux' }
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp313-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-latest, arch: aarch64, cibw_build: 'cp37-manylinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp39-manylinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp310-manylinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp311-manylinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp312-manylinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp313-manylinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp37-manylinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp39-manylinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp310-manylinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp311-manylinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp312-manylinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp313-manylinux*', cibw_skip: '' }
# aarch64 - musllinux
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp37-musllinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp39-musllinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp310-musllinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp311-musllinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp312-musllinux' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp313-musllinux' }
- { os: macos-13, arch: x86_64, cibw_build: '' }
- { os: macos-latest, arch: arm64, cibw_build: '' }
- { os: windows-2019, arch: AMD64, cibw_build: '' }
- { os: windows-2019, arch: x86, cibw_build: '' }
if: startsWith(github.ref, 'refs/tags')
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp37-musllinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp39-musllinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp310-musllinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp311-musllinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: aarch64, cibw_build: 'cp312-musllinux*', cibw_skip: '' }
- { os: ubuntu-latest, 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-2019, arch: AMD64, cibw_build: 'cp*', cibw_skip: '*36* *38*' }
- { os: windows-2019, arch: x86, cibw_build: 'cp*', cibw_skip: '*36* *38*' }
if: ${{ inputs.fullMode == 1 || startsWith(github.ref, 'refs/tags') || 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: '🛠️ Add msbuild to PATH'
if: runner.os == 'Windows'
@@ -260,17 +232,6 @@ jobs:
with:
vs-version: '16.5'
- name: '🛠️ Win build dependencies'
if: runner.os == 'Windows'
shell: bash
run: |
choco install ninja
- name: '🛠️ macOS dependencies'
if: runner.os == 'macOS'
run: |
brew install ninja
- name: '🛠️ Win MSVC 32 dev cmd setup'
if: runner.os == 'Windows' && matrix.arch == 'x86'
uses: ilammy/msvc-dev-cmd@v1
@@ -284,70 +245,27 @@ jobs:
arch: x64
- name: '🛠️ Set up QEMU'
if: runner.os == 'Linux'
if: runner.os == 'Linux' && matrix.arch != 'x86_64'
uses: docker/setup-qemu-action@v3
- name: '🚧 cibuildwheel run - Linux'
if: matrix.os == 'ubuntu-latest'
uses: pypa/cibuildwheel@v2.21.3
- name: '🚧 cibuildwheel run'
uses: pypa/cibuildwheel@v2.22.0
env:
CIBW_BUILD_FRONTEND: build
CIBW_BUILD: ${{ matrix.cibw_build }}*
CIBW_BUILD: ${{ matrix.cibw_build }}
CIBW_SKIP: ${{ matrix.cibw_skip }}
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_ENVIRONMENT: DEBUG=${{ env.UNICORN_DEBUG }}
CIBW_ENVIRONMENT_PASS_LINUX: DEBUG
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
with:
package-dir: bindings/python
output-dir: wheelhouse
- name: '🚧 cibuildwheel run - Windows'
if: matrix.os == 'windows-2019'
uses: pypa/cibuildwheel@v2.21.3
env:
CIBW_BUILD_FRONTEND: build
CIBW_SKIP: '*36* *38*'
CIBW_BUILD: 'cp*'
CIBW_ENVIRONMENT: DEBUG=${{ env.UNICORN_DEBUG }}
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
with:
package-dir: bindings/python
output-dir: wheelhouse
- name: '🚧 cibuildwheel run - MacOS x86_84'
if: matrix.os == 'macos-13'
uses: pypa/cibuildwheel@v2.21.3
env:
CIBW_BUILD_FRONTEND: build
CIBW_SKIP: '*36* *38*'
CIBW_BUILD: 'cp*'
CIBW_ENVIRONMENT: DEBUG=${{ env.UNICORN_DEBUG }}
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
with:
package-dir: bindings/python
output-dir: wheelhouse
- name: '🚧 cibuildwheel run - MacOS arm64'
if: matrix.os == 'macos-latest'
uses: pypa/cibuildwheel@v2.21.3
env:
CIBW_BUILD_FRONTEND: build
CIBW_SKIP: '*36* *37* *38*'
CIBW_BUILD: 'cp*'
CIBW_ENVIRONMENT: DEBUG=${{ env.UNICORN_DEBUG }}
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
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
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}-all
name: ${{ env.ARTIFACT_NAME }}
path: ./wheelhouse/*.whl
make_sdist:
@@ -356,8 +274,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Optional, use if you use setuptools_scm
submodules: true # Optional, use if you have submodules
fetch-depth: 0
- name: Build SDist
run: |

View File

@@ -1,10 +1,10 @@
[build-system]
requires = ["setuptools", "build", "wheel"]
requires = ["setuptools", "build", "wheel", "versioningit"]
build-backend = "setuptools.build_meta"
[project]
name = "unicorn"
version = "2.1.1"
dynamic = ["version"]
requires-python = ">= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*, != 3.4.*, != 3.5.*, != 3.6.*"
authors = [
{ name = "Nguyen Anh Quynh", email = "quynh@gmail.com" },
@@ -33,9 +33,11 @@ Changelog = "https://github.com/unicorn-engine/unicorn/blob/master/ChangeLog"
[project.optional-dependencies]
test = [
"pytest",
"pytest-cov",
"capstone==6.0.0a2;python_version>'3.7'",
"capstone==5.0.1;python_version<='3.7'"
]
[tool.setuptools.packages.find]
include = ["unicorn*"]
[tool.versioningit]

View File

@@ -102,12 +102,17 @@ def build_libraries():
has_msbuild = shutil.which('msbuild') is not None
conf = 'Debug' if int(os.getenv('DEBUG', 0)) else 'Release'
cmake_args = ['cmake', '-B', BUILD_DIR, "-DCMAKE_BUILD_TYPE=" + conf]
if os.getenv("UNICORN_TRACER"):
cmake_args += ["-DUNICORN_TRACER=on"]
if conf == 'Debug':
cmake_args += ["-DUNICORN_LOGGING=on"]
if has_msbuild and sys.platform == 'win32':
generators = os.getenv('GENERATORS') or 'Visual Studio 16 2019'
plat = 'Win32' if platform.architecture()[0] == '32bit' else 'x64'
subprocess.check_call(['cmake', '-B', BUILD_DIR, '-G', "Visual Studio 16 2019", "-A", plat,
"-DCMAKE_BUILD_TYPE=" + conf], cwd=UC_DIR)
cmake_args += ['-G', generators, "-A", plat]
subprocess.check_call(cmake_args, cwd=UC_DIR)
subprocess.check_call(['msbuild', 'unicorn.sln', '-m', '-p:Platform=' + plat, '-p:Configuration=' + conf],
cwd=BUILD_DIR)
@@ -115,11 +120,7 @@ def build_libraries():
shutil.copy(os.path.join(obj_dir, LIBRARY_FILE), LIBS_DIR)
shutil.copy(os.path.join(obj_dir, STATIC_LIBRARY_FILE), LIBS_DIR)
else:
cmake_args = ["cmake", '-B', BUILD_DIR, '-S', UC_DIR, "-DCMAKE_BUILD_TYPE=" + conf]
if os.getenv("TRACE"):
cmake_args += ["-DUNICORN_TRACER=on"]
if conf == "Debug":
cmake_args += ["-DUNICORN_LOGGING=on"]
cmake_args += ['-S', UC_DIR]
subprocess.check_call(cmake_args, cwd=UC_DIR)
threads = os.getenv("THREADS", "4")
subprocess.check_call(["cmake", "--build", ".", "-j" + threads], cwd=BUILD_DIR)

View File

@@ -2,7 +2,6 @@
# Sample code for ARM of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.arm_const import *

View File

@@ -2,7 +2,6 @@
# Sample code for ARM64 of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.arm64_const import *

View File

@@ -3,7 +3,6 @@
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
# AARCH64 Python sample ported by zhangwm <rustydaar@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.arm64_const import *

View File

@@ -1,7 +1,6 @@
#!/usr/bin/env python
# Sample code for ARM big endian of Unicorn. zhangwm <rustydaar@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.arm_const import *

View File

@@ -2,8 +2,6 @@
# Sample code for Unicorn.
# By Lazymio(@wtdcode), 2021
import pytest
import sys
from unicorn import *
from unicorn.x86_const import *
from datetime import datetime
@@ -36,7 +34,6 @@ def time_emulation(uc, start, end):
# TODO: Check if worth adapting the ctl_request_cache method for py2 bindings
@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def test_uc_ctl_tb_cache():
# Initialize emulator in X86-32bit mode
uc = Uc(UC_ARCH_X86, UC_MODE_32)
@@ -84,7 +81,6 @@ def trace_tcg_sub(uc, address, arg1, arg2, size, data):
# TODO: Check if worth adapting the hook_add method for py2 bindings
@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def test_uc_ctl_exits():
uc = Uc(UC_ARCH_X86, UC_MODE_32)
addr = 0x1000

View File

@@ -2,7 +2,6 @@
# Sample code for ARM of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.m68k_const import *

View File

@@ -2,7 +2,6 @@
# Sample code for MIPS of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.mips_const import *

View File

@@ -2,8 +2,6 @@
# Unicorn sample for auditing network connection and file handling in shellcode.
# Nguyen Tan Cong <shenlongbk@gmail.com>
from __future__ import print_function
import pytest
import struct
import uuid
from unicorn import *
@@ -361,7 +359,6 @@ def hook_intr(uc, intno, user_data):
print_sockcall(msg)
@pytest.mark.parametrize("code", [X86_SEND_ETCPASSWD, X86_BIND_TCP, X86_REVERSE_TCP, X86_REVERSE_TCP_2])
# Test X86 32 bit
def test_i386(code):
global fd_chains

View File

@@ -1,7 +1,6 @@
#!/usr/bin/env python
# Sample code for PPC of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.ppc_const import *

View File

@@ -1,7 +1,6 @@
#!/usr/bin/env python
# Sample code for RISCV of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.riscv_const import *

View File

@@ -3,8 +3,6 @@
# Nguyen Anh Quynh <aquynh@gmail.com>
# KaiJern Lau <kj@theshepherdlab.io>
from __future__ import print_function
import pytest
from unicorn import *
from unicorn.x86_const import *
@@ -134,8 +132,6 @@ def hook_syscall64(mu, user_data):
mu.emu_stop()
@pytest.mark.parametrize("mode,code",
[(UC_MODE_32, X86_CODE32_SELF), (UC_MODE_32, X86_CODE32), (UC_MODE_64, X86_CODE64)])
# Test X86 32 bit
def test_i386(mode, code):
if mode == UC_MODE_32:

View File

@@ -2,7 +2,6 @@
# Sample code for SPARC of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
from __future__ import print_function
from unicorn import *
from unicorn.sparc_const import *

View File

@@ -5,7 +5,6 @@
Copyright 2022 Aptiv
"""
from __future__ import print_function
from unicorn import *
from unicorn.tricore_const import *

View File

@@ -1,7 +1,6 @@
#!/usr/bin/env python
# Sample code for X86 of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
from __future__ import print_function
import pickle
from unicorn import *
from unicorn.x86_const import *

View File

@@ -1,7 +1,4 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.arm64_const import *

View File

@@ -1,10 +1,7 @@
import regress
from unicorn import *
from unicorn.arm_const import *
MAIN_ADDRESS = 0x8d68
ADDRESS = MAIN_ADDRESS & ~(0x1000 - 1)
STACK_ADDR = ADDRESS + 0x1000

View File

@@ -1,7 +1,4 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.arm_const import *

View File

@@ -1,15 +1,11 @@
#!/usr/bin/python
# Added by Peter Mackay, relating to issue 571
# "ARM NEON/VFP support seems to exist but is disabled by default"
# Added by Peter Mackay, relating to issue 571
# ARM NEON/VFP support seems to exist but is disabled by default
# https://github.com/unicorn-engine/unicorn/issues/571
import regress
from unicorn import *
from unicorn.arm_const import *
CODE = (
b'\x11\xEE\x50\x1F' # MRC p15, #0, r1, c1, c0, #2
b'\x41\xF4\x70\x01' # ORR r1, r1, #(0xf << 20)
@@ -23,6 +19,7 @@ CODE = (
BASE = 0x1000
class FpVfpDisabled(regress.RegressTest):
def runTest(self):

View File

@@ -1,14 +1,14 @@
#!/usr/bin/env python
# Sample code for ARM of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
#
import platform
import regress
import sys
import unittest
from unicorn import *
from unicorn.arm_const import *
# code to be emulated
ARM_CODE = (
b"\x37\x00\xa0\xe3" # mov r0, #0x37
@@ -32,6 +32,7 @@ def hook_code(uc, address, size, user_data):
class TestInitInputCrash(regress.RegressTest):
@unittest.skipIf(sys.platform == 'win32' or platform.machine().lower() not in ('x86_64', 'arm64'), 'TO BE CHECKED!')
def test_arm(self):
regress.logger.debug("Emulate ARM code")

View File

@@ -1,44 +1,44 @@
import regress
import sys
import unittest
from unicorn import *
from unicorn.arm_const import *
SHELLCODE = bytes.fromhex(
'03 f0 8f e0' # 0001F894 ADD PC, PC, R3
'0d 07 21 f4' # 0001F898 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F89C VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8A0 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8A4 VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8A8 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8AC VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8B0 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8B4 VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8B8 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8BC VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8C0 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8C4 VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8C8 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8CC VST1.8 {D0}, [R12]!
'04 00 12 e3' # 0001F8D0 TST R2, #4
'04 30 91 14' # 0001F8D4 LDRNE R3, [R1],#4
'04 30 8c 14' # 0001F8D8 STRNE R3, [R12],#4
'82 2f b0 e1' # 0001F8DC MOVS R2, R2,LSL#31
'b2 30 d1 20' # 0001F8E0 LDRHCS R3, [R1],#2
'00 10 d1 15' # 0001F8E4 LDRBNE R1, [R1]
'b2 30 cc 20' # 0001F8E8 STRHCS R3, [R12],#2
'00 10 cc 15' # 0001F8EC STRBNE R1, [R12]
SHELLCODE = (
b'\x03\xF0\x8F\xE0' # 0001F894 ADD PC, PC, R3
b'\x0D\x07\x21\xF4' # 0001F898 VLD1.8 {D0}, [R1]!
b'\x0D\x07\x0C\xF4' # 0001F89C VST1.8 {D0}, [R12]!
b'\x0D\x07\x21\xF4' # 0001F8A0 VLD1.8 {D0}, [R1]!
b'\x0D\x07\x0C\xF4' # 0001F8A4 VST1.8 {D0}, [R12]!
b'\x0D\x07\x21\xF4' # 0001F8A8 VLD1.8 {D0}, [R1]!
b'\x0D\x07\x0C\xF4' # 0001F8AC VST1.8 {D0}, [R12]!
b'\x0D\x07\x21\xF4' # 0001F8B0 VLD1.8 {D0}, [R1]!
b'\x0D\x07\x0C\xF4' # 0001F8B4 VST1.8 {D0}, [R12]!
b'\x0D\x07\x21\xF4' # 0001F8B8 VLD1.8 {D0}, [R1]!
b'\x0D\x07\x0C\xF4' # 0001F8BC VST1.8 {D0}, [R12]!
b'\x0D\x07\x21\xF4' # 0001F8C0 VLD1.8 {D0}, [R1]!
b'\x0D\x07\x0C\xF4' # 0001F8C4 VST1.8 {D0}, [R12]!
b'\x0D\x07\x21\xF4' # 0001F8C8 VLD1.8 {D0}, [R1]!
b'\x0D\x07\x0C\xF4' # 0001F8CC VST1.8 {D0}, [R12]!
b'\x04\x00\x12\xE3' # 0001F8D0 TST R2, #4
b'\x04\x30\x91\x14' # 0001F8D4 LDRNE R3, [R1],#4
b'\x04\x30\x8C\x14' # 0001F8D8 STRNE R3, [R12],#4
b'\x82\x2F\xB0\xE1' # 0001F8DC MOVS R2, R2,LSL#31
b'\xB2\x30\xD1\x20' # 0001F8E0 LDRHCS R3, [R1],#2
b'\x00\x10\xD1\x15' # 0001F8E4 LDRBNE R1, [R1]
b'\xB2\x30\xCC\x20' # 0001F8E8 STRHCS R3, [R12],#2
b'\x00\x10\xCC\x15' # 0001F8EC STRBNE R1, [R12]
)
BASE = 0x1F894
COPY_SRC = 0x1000
COPY_DST = 0x2000
COPY_LEN = 8
DATA = b'c8' * COPY_LEN
class ArmMemcpy(regress.RegressTest):
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def test_arm_memcpy(self):
uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)
@@ -46,7 +46,7 @@ class ArmMemcpy(regress.RegressTest):
uc.mem_map(COPY_DST, 0x1000)
uc.mem_map(BASE & ~(0x1000 - 1), 0x1000)
uc.mem_write(COPY_SRC, DATA)
uc.mem_write(BASE, bytes(SHELLCODE))
uc.mem_write(BASE, SHELLCODE)
uc.reg_write_batch((
(UC_ARM_REG_R12, COPY_DST),

View File

@@ -1,13 +1,13 @@
#!/usr/bin/python
import platform
import regress
import unittest
from unicorn import *
from unicorn.arm_const import *
class MovHang(regress.RegressTest):
@unittest.skipIf(platform.machine().lower() == 'aarch64', reason='TO BE CHECKED!')
def runTest(self):
uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)
uc.mem_map(0x1000, 0x1000)

View File

@@ -1,9 +1,5 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.arm_const import *
class VldrPcInsn(regress.RegressTest):

View File

@@ -1,9 +1,5 @@
import regress
from unicorn import *
from unicorn.arm_const import *
CODE = (
b'\x00\x00\x8a\xe0' # ADD R0, R10, R0

View File

@@ -1,12 +1,9 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
class Hang(regress.RegressTest):
class BadRam(regress.RegressTest):
def runTest(self):
PAGE_SIZE = 0x5000
CODE_ADDR = 0x400000

View File

@@ -1,14 +1,10 @@
#!/usr/bin/env python
# reg_write() can't modify PC from within trace callbacks
# issue #210
import regress
from unicorn import *
from unicorn.arm_const import *
BASE_ADDRESS = 0x10000000
THUMB_CODE = b"\x83\xb0" * 5 # sub sp, #0xc
TARGET_PC = 0xffffffff

View File

@@ -1,12 +1,11 @@
#!/usr/bin/env python
import platform
import regress
import sys
import unittest
from unicorn import *
from unicorn.arm_const import *
from unicorn.x86_const import *
# count down from maxint to zero
_VALID_CODE = (
b'\x31\xc9' # xor ecx, ecx
@@ -44,6 +43,8 @@ class TestCtl(regress.RegressTest):
self.assertEqual(UC_MODE_BIG_ENDIAN, uc.ctl_get_mode())
self.assertEqual(UC_CPU_ARM_CORTEX_M0, uc.ctl_get_cpu_model())
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
@unittest.skipIf(sys.platform == 'win32' or platform.machine().lower() not in ('x86_64', 'arm64'), 'TO BE CHECKED!')
def test_page_size(self):
SIZE_4KB = 4 * 1024 ** 1
SIZE_2MB = 2 * 1024 ** 2
@@ -77,6 +78,7 @@ class TestCtl(regress.RegressTest):
# are we still with the valid value?
self.assertEqual(SIZE_2MB, uc.ctl_get_page_size())
@unittest.skipIf(platform.machine().lower() == 'aarch64', reason='TO BE CHECKED!')
def test_timeout(self):
MILLIS_1S = 1000
@@ -137,6 +139,7 @@ class TestCtl(regress.RegressTest):
# not failing on an invalid instruction is another good indication for that
self.assertEqual(GOOD_EXIT, uc.reg_read(UC_X86_REG_EIP))
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def test_tlb_mode(self):
MAPPING_LO = 0x0000000001000000
MAPPING_HI = 0x0010000000000000
@@ -155,7 +158,7 @@ class TestCtl(regress.RegressTest):
uc.mem_map(MAPPING_HI, 0x1000)
uc.mem_write(MAPPING_HI, NOPSLED)
# this should prevents us from mapping to high addresses
# this should prevent us from mapping to high addresses
uc.ctl_set_tlb_mode(UC_TLB_CPU)
# this should fail

View File

@@ -1,14 +1,12 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
import regress
CODE_ADDR = 0x0
binary1 = b'\xb8\x02\x00\x00\x00'
binary2 = b'\xb8\x01\x00\x00\x00'
class CrashTB(regress.RegressTest):
def runTest(self):
@@ -32,6 +30,6 @@ class CrashTB(regress.RegressTest):
self.assertEqual(0x1, mu.reg_read(UC_X86_REG_RAX))
if __name__ == '__main__':
regress.main()

View File

@@ -1,11 +1,11 @@
#!/usr/bin/python
# From issue #1 of Ryan Hileman
from unicorn import *
import regress
from unicorn import *
CODE = b"\x90\x91\x92"
class DeadLock(regress.RegressTest):
def runTest(self):
@@ -16,5 +16,6 @@ class DeadLock(regress.RegressTest):
with self.assertRaises(UcError):
mu.emu_start(0x100000, 0x1000 + len(CODE))
if __name__ == '__main__':
regress.main()

View File

@@ -1,27 +1,22 @@
#!/usr/bin/python
import binascii
import regress
from unicorn import *
from unicorn.x86_const import *
CODE = binascii.unhexlify((
"8B 74 01 28" # mov esi, dword ptr [ecx + eax + 0x28] mapped: 0x1000
"03 F0" # add esi, eax 0x1004
"8D 45 FC" # lea eax, dword ptr [ebp - 4] 0x1006
"50" # push eax 0x1009
"6A 40" # push 0x40 0x100A
"6A 10" # push 0x10 0x100C
"56" # push esi 0x100E
).replace(' ', ''))
CODE = (
b'\x8B\x74\x01\x28' # mov esi, dword ptr [ecx + eax + 0x28] mapped: 0x1000
b'\x03\xF0' # add esi, eax 0x1004
b'\x8D\x45\xFC' # lea eax, dword ptr [ebp - 4] 0x1006
b'\x50' # push eax 0x1009
b'\x6A\x40' # push 0x40 0x100A
b'\x6A\x10' # push 0x10 0x100C
b'\x56' # push esi 0x100E
)
BASE = 0x1000
STACK = 0x4000
class HookCodeStopEmuTest(regress.RegressTest):
class EmuClearErrorsTest(regress.RegressTest):
def test_hook_code_stop_emu(self):
mu = Uc(UC_ARCH_X86, UC_MODE_32)

View File

@@ -1,9 +1,8 @@
#!/usr/bin/python
""" See https://github.com/unicorn-engine/unicorn/issues/65 """
import unicorn
import regress
import unicorn
class EmuStopSegFault(regress.RegressTest):
@@ -16,5 +15,6 @@ class EmuStopSegFault(regress.RegressTest):
# The following should not trigger a null pointer dereference
self.assertEqual(None, mu.emu_stop())
if __name__ == '__main__':
regress.main()

View File

@@ -1,6 +1,5 @@
#!/usr/bin/python
"""See https://github.com/unicorn-engine/unicorn/issues/161
"""
See https://github.com/unicorn-engine/unicorn/issues/161
Ensure that constants which are specified via a typedef, rather than an enum,
are included in the bindings by the script for autogenerating mappings for

View File

@@ -1,11 +1,9 @@
#!/usr/bin/python
import regress
import sys
import unittest
from unicorn import *
from unicorn.x86_const import *
from capstone import Cs, CS_ARCH_X86, CS_ARCH_X86, CS_MODE_64, CS_MODE_32
from capstone import Cs, CS_ARCH_X86, CS_MODE_64, CS_MODE_32
CODE = (
b'\xc7\x04\x24\x7f\x03\x00\x00' # mov DWORD PTR [rsp],0x37f
@@ -29,6 +27,7 @@ def hook_code(uc, addr, size, user_data):
class FpuIP(regress.RegressTest):
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def test_32(self):
mu = Uc(UC_ARCH_X86, UC_MODE_32)
cs = Cs(CS_ARCH_X86, CS_MODE_32)
@@ -43,6 +42,7 @@ class FpuIP(regress.RegressTest):
self.assertSequenceEqual(b'\x7f\x03\x00\x00\x00\x00\x00\x00', mu.mem_read(STACK + 8, 8))
self.assertSequenceEqual(b'\x55\x55\x00\x00\x00\x00\x00\x00', mu.mem_read(STACK + 16, 8))
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def test_64(self):
mu = Uc(UC_ARCH_X86, UC_MODE_64)
cs = Cs(CS_ARCH_X86, CS_MODE_64)

View File

@@ -1,11 +1,7 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
CODE = (
b'\x9b\xd9\x3c\x24' # fstcw WORD PTR [esp]
b'\x59' # pop ecx
@@ -17,7 +13,6 @@ STACK = 0x00000f00
def hook_mem_write(uc, access, address, size, value, user_data):
regress.logger.debug("mem WRITE to: %#x, size = %u, value = %#x", address, size, value)
return True

View File

@@ -1,8 +1,5 @@
#!/usr/bin/python
import binascii
import regress
from unicorn import *
from unicorn.x86_const import *
@@ -31,6 +28,7 @@ def hook_intr(uc, intno, user_data):
class Hang(regress.RegressTest):
def runTest(self):
# self modifying shellcode execve('/bin/sh')
shellcode = (

View File

@@ -1,11 +1,9 @@
#!/usr/bin/env python3
import regress
import sys
import unittest
from unicorn import Uc, UcError, UC_ARCH_X86, UC_MODE_64
from unicorn.unicorn_const import UC_TLB_VIRTUAL, UC_TLB_CPU, UC_ERR_FETCH_UNMAPPED
MAX_INTEL_INSN_SIZE = 15
@@ -23,8 +21,10 @@ class TestMem(regress.RegressTest):
self.uc.mem_map(address, 0x1000)
self.uc.mem_write(address, payload)
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def test_virt_high_mapping(self):
"""Mapping memory at high addresses should work when TLB mode
"""
Mapping memory at high addresses should work when TLB mode
is set to VIRTUAL.
"""
@@ -42,8 +42,10 @@ class TestMem(regress.RegressTest):
except UcError:
self.fail('high mapping failed at %#018x' % code)
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def test_cpu_high_mapping(self):
"""Mapping memory at high addresses should work fail TLB mode
"""
Mapping memory at high addresses should work fail TLB mode
is set to CPU (default).
"""

View File

@@ -1,21 +1,15 @@
#!/usr/bin/env python
""" https://github.com/unicorn-engine/unicorn/issues/165 """
import regress
from unicorn import *
def hook_mem_read_unmapped(mu, access, address, size, value, user_data):
pass
class TestHook(regress.RegressTest):
def test_excessive_hooks(self):
mu = Uc(UC_ARCH_X86, UC_MODE_32)
for _ in range(1337):
mu.hook_add(UC_HOOK_MEM_READ_UNMAPPED, hook_mem_read_unmapped)
mu.hook_add(UC_HOOK_MEM_READ_UNMAPPED, lambda *args, **kwargs: None)
if __name__ == '__main__':

View File

@@ -1,10 +1,6 @@
#!/usr/bin/python
""" https://github.com/unicorn-engine/unicorn/issues/334 """
'''https://github.com/unicorn-engine/unicorn/issues/334'''
from __future__ import print_function
import regress
from unicorn import *
from unicorn.x86_const import *
@@ -26,6 +22,7 @@ CODE = (
EP = ADDRESS + 0x54
def hook_code(mu, address, size, user_data):
regress.logger.debug(">>> Tracing instruction at %#x, instruction size = %u", address, size)

View File

@@ -1,11 +1,7 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
CODE = (
b'\x48\xc7\xc0\x03\x00\x00\x00' # 0x1000: mov rax, 3
b'\x0f\x05' # 0x1007: syscall

View File

@@ -5,7 +5,7 @@ CODE = b"\x90" * 3
CODE_ADDR = 0x1000
class HookCounter(object):
class HookCounter:
"""Counts number of hook calls."""
def __init__(self):

View File

@@ -1,11 +1,7 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
PAGE_SIZE = 0x1000
ACCESS_ADDR = 0x1000
@@ -16,6 +12,7 @@ CODE = (
BASE = 0x00000000
def hook_mem_read(uc, access, address, size, value, data):
regress.logger.debug("Reading at %#x", address)
# BUG: unicorn will segfault when calling "uc.mem_write" to write to a location that was mapped only as UC_PROT_READ

View File

@@ -1,32 +1,25 @@
#!/usr/bin/python
# By Mariano Graziano
import platform
import regress
import struct
import sys
import unittest
from unicorn import *
from unicorn.x86_const import *
if sys.version_info.major == 2:
range = xrange
mu = 0
class Init(regress.RegressTest):
def init_unicorn(self, ip, sp, counter):
global mu
#print "[+] Emulating IP: %x SP: %x - Counter: %x" % (ip, sp, counter)
mu = Uc(UC_ARCH_X86, UC_MODE_64)
mu.mem_map(0x1000000, 2 * 1024 * 1024)
mu.mem_write(0x1000000, b"\x90")
mu.mem_map(0x8000000, 8 * 1024 * 1024)
mu.reg_write(UC_X86_REG_RSP, sp)
regress.logger.debug("[+] Emulating IP: %x SP: %x - Counter: %x" % (ip, sp, counter))
self.emulator = Uc(UC_ARCH_X86, UC_MODE_64)
self.emulator.mem_map(0x1000000, 2 * 1024 * 1024)
self.emulator.mem_write(0x1000000, b"\x90")
self.emulator.mem_map(0x8000000, 8 * 1024 * 1024)
self.emulator.reg_write(UC_X86_REG_RSP, sp)
content = self.generate_value(counter)
mu.mem_write(sp, content)
self.emulator.mem_write(sp, content)
self.set_hooks()
def generate_value(self, counter):
@@ -36,46 +29,41 @@ class Init(regress.RegressTest):
return struct.pack("<Q", address)
def set_hooks(self):
global mu
mu.hook_add(UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, self.hook_mem_invalid)
mu.hook_add(UC_HOOK_MEM_FETCH_UNMAPPED, self.hook_mem_fetch_unmapped)
self.emulator.hook_add(UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, self.hook_mem_invalid)
self.emulator.hook_add(UC_HOOK_MEM_FETCH_UNMAPPED, self.hook_mem_fetch_unmapped)
def hook_mem_invalid(self, uc, access, address, size, value, user_data):
global mu
regress.logger.debug("[ HOOK_MEM_INVALID - Address: 0x%x ]", address)
if access == UC_MEM_WRITE_UNMAPPED:
regress.logger.debug(">>> Missing memory is being WRITE at 0x%x, data size = %u, data value = 0x%x", address, size, value)
regress.logger.debug(">>> Missing memory is being WRITE at 0x%x, data size = %u, data value = 0x%x",
address, size, value)
address_page = address & 0xFFFFFFFFFFFFF000
mu.mem_map(address_page, 2 * 1024 * 1024)
mu.mem_write(address, str(value))
uc.mem_map(address_page, 2 * 1024 * 1024)
uc.mem_write(address, str(value))
return True
else:
return False
def hook_mem_fetch_unmapped(self, uc, access, address, size, value, user_data):
global mu
regress.logger.debug("[ HOOK_MEM_FETCH - Address: 0x%x ]", address)
regress.logger.debug("[ mem_fetch_unmapped: faulting address at 0x%x ]", address)
mu.mem_write(0x1000003, b"\x90")
mu.reg_write(UC_X86_REG_RIP, 0x1000001)
uc.mem_write(0x1000003, b"\x90")
uc.reg_write(UC_X86_REG_RIP, 0x1000001)
return True
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
@unittest.skipIf(sys.platform == 'win32' or platform.machine().lower() not in ('x86_64', 'arm64'), 'TO BE CHECKED!')
def runTest(self):
global mu
ips = range(0x1000000, 0x1001000)
sps = range(0x8000000, 0x8001000)
for i, (ip, sp) in enumerate(zip(ips, sps)):
self.init_unicorn(ip, sp, i)
mu.emu_start(0x1000000, 0x1000000 + 0x1)
self.emulator.emu_start(0x1000000, 0x1000000 + 0x1)
if __name__ == '__main__':

View File

@@ -1,16 +1,12 @@
import regress
from unicorn import *
from unicorn.x86_const import *
from capstone import *
CODE = bytes.fromhex(
'48 31 c0' # xor rax,rax
'48 0f c7 f0' # rdrand rax
'f4' # hlt
CODE = (
b'\x48\x31\xc0' # xor rax,rax
b'\x48\x0f\xc7\xf0' # rdrand rax
b'\xf4' # hlt
)
BASE = 0x100000

View File

@@ -1,12 +1,9 @@
#!/usr/bin/env python
# Test callback that returns False to cancel emulation
from __future__ import print_function
import regress
from unicorn import *
from unicorn.x86_const import *
import regress
X86_CODE32_MEM_WRITE = b"\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov [0xaaaaaaaa], ecx; INC ecx; DEC edx

View File

@@ -1,16 +1,13 @@
#!/usr/bin/env python
""" See https://github.com/unicorn-engine/unicorn/issues/82 """
import regress
from unicorn import *
from unicorn.x86_const import *
CODE_ADDR = 0x10101000
CODE = b'\xff\xe3' # jmp ebx
class JumEbxHang(regress.RegressTest):
def runTest(self):
mu = Uc(UC_ARCH_X86, UC_MODE_32)

View File

@@ -1,13 +1,11 @@
#!/usr/bin/env python
# Mariano Graziano
import binascii
import regress
import sys
import unittest
from unicorn import *
from unicorn.x86_const import *
# set rdx to either 0xbabe or 0xc0ca, based on a comparison.
# rdx would never be set to 0xbabe unless we set zf to 1
CODE = (
@@ -68,7 +66,7 @@ class Jumping(regress.RegressTest):
# callback for tracing instructions
def hook_code(self, uc, address, size, _):
insn = uc.mem_read(address, size)
regress.logger.debug(">>> Tracing instruction at %#x : %s", address, binascii.hexlify(insn))
regress.logger.debug(">>> Tracing instruction at %#x : %s", address, insn.hex())
regs = uc.reg_read_batch((
UC_X86_REG_RAX, UC_X86_REG_RBX, UC_X86_REG_RCX, UC_X86_REG_RDX,
@@ -94,7 +92,6 @@ class Jumping(regress.RegressTest):
self.multipath()
regress.logger.debug("-" * 32)
def setUp(self):
# decide how to fixate zf value: 0 to clear, 1 to set
self.fixed_zf = 1
@@ -110,6 +107,7 @@ class Jumping(regress.RegressTest):
self.uc = uc
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def runTest(self):
# tracing all basic blocks with customized callback
self.uc.hook_add(UC_HOOK_BLOCK, self.hook_block)
@@ -120,7 +118,8 @@ class Jumping(regress.RegressTest):
# emulate machine code in infinite time
self.uc.emu_start(BASE, BASE + len(CODE))
self.assertEqual(self.uc.reg_read(UC_X86_REG_RDX), 0xbabe, "rdx contains the wrong value. eflags modification failed")
self.assertEqual(self.uc.reg_read(UC_X86_REG_RDX), 0xbabe,
"rdx contains the wrong value. eflags modification failed")
if __name__ == '__main__':

View File

@@ -1,13 +1,9 @@
#!/usr/bin/python
import gc
import regress
import weakref
from unicorn import *
from unicorn.x86_const import *
ADDRESS = 0x8048000
STACK_ADDRESS = 0xffff000
STACK_SIZE = 0x1000
@@ -26,10 +22,10 @@ CODE = (
EP = ADDRESS + 0x54
# Dictionary to keep weak references to instances
instances = weakref.WeakValueDictionary()
def create_instance(key, *args, **kwargs):
obj = Uc(*args, **kwargs)
instances[key] = obj
@@ -56,18 +52,18 @@ def emu_loop(key):
regress.logger.debug("EIP: %#x", emu.reg_read(UC_X86_REG_EIP))
def debugMem():
gc.collect() # don't care about stuff that would be garbage collected properly
assert(len(instances) == 0)
class EmuLoopReferenceTest(regress.RegressTest):
def debug_mem(self):
gc.collect() # don't care about stuff that would be garbage collected properly
self.assertEqual(len(instances), 0)
def runTest(self):
for i in range(5):
emu_loop('obj%d' % i)
debugMem()
self.debug_mem()
if __name__ == '__main__':

View File

@@ -1,12 +1,9 @@
#!/usr/bin/python
# By Ryan Hileman, issue #9
# this prints out 2 lines and the contents must be the same
import regress
from unicorn import *
from unicorn.x86_const import *
class MemMap(regress.RegressTest):

View File

@@ -1,9 +1,5 @@
#!/usr/bin/env python
import regress
from unicorn import *
from unicorn.x86_const import *
class MmapSeg1(regress.RegressTest):

View File

@@ -1,11 +1,9 @@
#!/usr/bin/python
import regress
import sys
import unittest
from capstone import *
from unicorn import *
CODE = (
b'\x00\x00\xa4\x12' # beq $a0, $s5, 0x4008a0
b'\x6a\x00\x82\x28' # slti $v0, $a0, 0x6a
@@ -17,6 +15,7 @@ BASE = 0x400000
class MipsBranchDelay(regress.RegressTest):
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def runTest(self):
md = Cs(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_LITTLE_ENDIAN)

View File

@@ -1,10 +1,7 @@
import regress
from unicorn import *
from unicorn.mips_const import *
CODE = b'\x44\x43\xF8\x00' # cfc1 $v1, FCSR
BASE = 0x416CB0

View File

@@ -1,11 +1,9 @@
#!/usr/bin/python
import regress
import sys
import unittest
from unicorn import *
from unicorn.mips_const import *
CODE = (
b'\x00\x00\x00\x00' # nop
b'\x00\x00\xa4\x8f' # lw $a0, 0($sp)
@@ -16,6 +14,7 @@ BASE = 0x20000000
class MipsExcept(regress.RegressTest):
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def runTest(self):
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN)

View File

@@ -1,16 +1,12 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.mips_const import *
CODE = b'\x34\x21\x34\x56' # ori $at, $at, 0x3456
BASE = 0x10000000
class MipsSyscall(regress.RegressTest):
class MipsKernelMMU(regress.RegressTest):
def test_syscall(self):
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN)

View File

@@ -1,11 +1,9 @@
#!/usr/bin/python
import regress
import sys
import unittest
from unicorn import *
from unicorn.mips_const import *
CODE = (
b'\xf8\xff\x01\x24' # addiu $at, $zero, -8
b'\x24\xe8\xa1\x03' # and $sp, $sp, $at
@@ -17,11 +15,12 @@ CODE = (
BASE = 0x4010dc
def code_hook(uc, addr, size, user_data):
regress.logger.debug('code hook: pc=%08x sp=%08x', addr, uc.reg_read(UC_MIPS_REG_SP))
def run(step) -> int:
def run(step):
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN)
if step:
@@ -45,6 +44,8 @@ def run(step) -> int:
class MipsSingleStep(regress.RegressTest):
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def runTest(self):
sp1 = run(step=False)
sp2 = run(step=True)

View File

@@ -1,16 +1,14 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.mips_const import *
CODE = b'\x0c\x00\x00\x00' # syscall
BASE = 0x40000
def intr_hook(uc, intno, data):
regress.logger.debug('interrupt=%d, v0=%d, pc=%#010x', intno, uc.reg_read(UC_MIPS_REG_V0), uc.reg_read(UC_MIPS_REG_PC))
regress.logger.debug('interrupt=%d, v0=%d, pc=%#010x', intno, uc.reg_read(UC_MIPS_REG_V0),
uc.reg_read(UC_MIPS_REG_PC))
class MipsSyscall(regress.RegressTest):

View File

@@ -1,11 +1,7 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
CODE = (
b'\x8e\xe8' # mov gs, eax
b'\xb8\x01\x00\x00\x00' # mov eax, 1
@@ -14,7 +10,7 @@ CODE = (
BASE = 0x1000
class VldrPcInsn(regress.RegressTest):
class MovGsEax(regress.RegressTest):
def runTest(self):
uc = Uc(UC_ARCH_X86, UC_MODE_32)

View File

@@ -1,12 +1,10 @@
#!/usr/bin/python
# By Ryan Hileman, issue #3
import regress
import sys
import unittest
from capstone import Cs, CS_ARCH_X86, CS_MODE_64
from unicorn import *
from unicorn.x86_const import *
CODE = b'\xf2\x0f\x10\x05\xaa\x12\x00\x00'
@@ -24,6 +22,8 @@ def hook_code(uc, addr, size, md):
class Movsd(regress.RegressTest):
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def runTest(self):
addr = 0x400000
mu = Uc(UC_ARCH_X86, UC_MODE_64)

View File

@@ -1,9 +1,7 @@
#!/usr/bin/env python
import regress
from unicorn import *
# OS X: OK with 2047 iterations.
# OS X: Crashes at 2048:th iteration ("qemu: qemu_thread_create: Resource temporarily unavailable").
# Linux: No crashes observed.

View File

@@ -1,15 +1,22 @@
#!/usr/bin/env python
import platform
import resource
import regress
import sys
import unittest
from unicorn import *
try:
# Only available on Unix: https://docs.python.org/3/library/resource.html
import resource
except:
pass
ITERATIONS = 10000
class MemoryLeak(regress.RegressTest):
@unittest.skipIf(sys.platform == 'win32', reason='Test for Unix only')
@unittest.skipIf(platform.machine().lower() == 'aarch64', reason='TO BE CHECKED!')
def test(self):
if platform.system() == "Darwin":
rusage_multiplier = 1

View File

@@ -1,8 +1,6 @@
#!/usr/bin/python
# By Ryan Hileman, issue #91
import regress
from unicorn import *
from unicorn.x86_const import *

View File

@@ -1,27 +1,23 @@
#!/usr/bin/env python
""" See https://github.com/unicorn-engine/unicorn/issues/98 """
import regress
from unicorn import *
ADDR = 0xffaabbcc
def hook_mem_invalid(mu, access, address, size, value, user_data):
class RegWriteSignExt(regress.RegressTest):
def hook_mem_invalid(self, mu, access, address, size, value, user_data):
regress.logger.debug(">>> Access type: %u, expected value: 0x%x, actual value: 0x%x", access, ADDR, address)
assert(address == ADDR)
self.assertEqual(address, ADDR)
mu.mem_map(address & 0xfffff000, 4 * 1024)
mu.mem_write(address, b'\xcc')
return True
class RegWriteSignExt(regress.RegressTest):
def runTest(self):
mu = Uc(UC_ARCH_X86, UC_MODE_32)
mu.reg_write(x86_const.UC_X86_REG_EBX, ADDR)
@@ -30,7 +26,7 @@ class RegWriteSignExt(regress.RegressTest):
# jmp ebx
mu.mem_write(0x10000000, b'\xff\xe3')
mu.hook_add(UC_HOOK_MEM_FETCH_UNMAPPED | UC_HOOK_MEM_FETCH_PROT, hook_mem_invalid)
mu.hook_add(UC_HOOK_MEM_FETCH_UNMAPPED | UC_HOOK_MEM_FETCH_PROT, self.hook_mem_invalid)
mu.emu_start(0x10000000, 0x10000000 + 2, count=1)

View File

@@ -1,27 +1,25 @@
#!/usr/bin/env python
import glob
import logging
import os
import unittest
class RegressTest(unittest.TestCase):
"""Regress test case dummy class.
"""
""" Regress test case dummy class. """
def main():
unittest.main()
def __setup_logger(name):
"""Set up a unified logger for all tests.
"""
""" Set up a unified logger for all tests. """
instance = logging.getLogger(name)
instance.propagate = False
if not instance.handlers:
handler = logging.StreamHandler()
formatter = logging.Formatter('[%(levelname)s] %(message)s')
if not instance.hasHandlers():
handler.setFormatter(formatter)
instance.addHandler(handler)
@@ -29,36 +27,4 @@ def __setup_logger(name):
logger = __setup_logger('UnicornRegress')
logger.setLevel(os.environ.get("UNICORN_DEBUG", "INFO").upper())
def main():
unittest.main()
if __name__ == '__main__':
suite = unittest.TestSuite()
logger.info('starting discovery')
# Find all unittest type in this directory and run it.
directory = os.path.dirname(__file__) or '.'
pyfiles = glob.glob(directory + '/*.py')
modules = [os.path.splitext(os.path.basename(f))[0] for f in pyfiles if os.path.isfile(f) and f != __file__]
logger.info('%d test modules found', len(modules))
for mname in modules:
try:
module = __import__(mname)
except ImportError as ex:
logger.error('could not load %s: %s is missing', mname, ex.name)
else:
tests = unittest.defaultTestLoader.loadTestsFromModule(module)
suite.addTests(tests)
logger.debug('found %d test cases in %s', tests.countTestCases(), mname)
logger.info('%d test cases were added', suite.countTestCases())
unittest.TextTestRunner().run(suite)
logger.setLevel((os.getenv('REGRESS_LOG_LEVEL') or 'INFO').upper())

View File

@@ -1,11 +1,7 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
PAGE_SIZE = 0x1000
CODE = b'\xf3\xaa' # rep stosb

View File

@@ -1,4 +1,3 @@
#!/usr/bin/python
#
# This test demonstrates emulation behavior within and across
# basic blocks.
@@ -6,11 +5,9 @@
import binascii
import struct
import regress
from unicorn import *
from unicorn.x86_const import *
CODE = (
b"\xb8\x00\x00\x00\x00" # 1000: mov eax,0x0
b"\x40" # 1005: inc eax
@@ -116,13 +113,11 @@ class RunAcrossBBTest(regress.RegressTest):
showpc(mu)
#######################################################################
# emu_run ONE:
# exectue four instructions, until the last instruction in a BB
#######################################################################
mu.emu_start(0x1000, 0x100c)
# should exec the following four instructions:
# 1000: b8 00 00 00 00 mov eax,0x0 <
@@ -143,13 +138,11 @@ class RunAcrossBBTest(regress.RegressTest):
"unexpected stack value")
showpc(mu)
#######################################################################
# emu_run TWO
# execute one instruction that jumps to a new BB
#######################################################################
mu.emu_start(0x100c, 0x1010)
# should exec one instruction that jumps to 0x1010:
# 100c: c3 ret -----------+
@@ -165,21 +158,18 @@ class RunAcrossBBTest(regress.RegressTest):
self.assertEqual(0x2800, mu.reg_read(UC_X86_REG_ESP), "unexpected SP (3)")
showpc(mu)
#######################################################################
# emu_run THREE
# execute three instructions to verify things work as expected
#######################################################################
mu.emu_start(0x1010, 0x1016)
# should exec the following three instructions:
# 1010: b8 00 00 00 00 mov eax,0x0 <
# 1015: 40 inc eax <
# 1016: 40 inc eax <
self.assertEqual(0x1016, mu.reg_read(UC_X86_REG_EIP),
"unexpected PC (4): 0x%x vs 0x%x" % (
0x1016, mu.reg_read(UC_X86_REG_EIP)))
"unexpected PC (4): 0x%x vs 0x%x" % (0x1016, mu.reg_read(UC_X86_REG_EIP)))
showpc(mu)
except UcError as e:

View File

@@ -1,5 +1,3 @@
#!/usr/bin/env python
import regress
import unicorn
@@ -9,5 +7,6 @@ class SegfaultOnStop(regress.RegressTest):
unicorn.Uc(unicorn.UC_ARCH_X86, unicorn.UC_MODE_64).emu_stop()
self.assertTrue(True, "If not reached, then we have a crashing bug.")
if __name__ == '__main__':
regress.main()

View File

@@ -1,11 +1,7 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.sparc_const import *
CODE = (
b"\xb0\x06\x20\x01" # 0: b0 06 20 01 inc %i0
b"\xb2\x06\x60\x01" # 4: b2 06 60 01 inc %i1
@@ -13,7 +9,8 @@ CODE = (
BASE = 0x00000000
class TestSparcRegRead(regress.RegressTest):
class TestSparc64RegRead(regress.RegressTest):
def runTest(self):
uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC64 | UC_MODE_BIG_ENDIAN)

View File

@@ -1,11 +1,9 @@
#!/usr/bin/python
import regress
import sys
import unittest
from unicorn import *
from unicorn.sparc_const import *
PAGE_SIZE = 1 * 1024 * 1024
CODE = (
@@ -50,7 +48,9 @@ def hook_code(uc, addr, size, ud):
regress.logger.debug("executing at 0x%04x", uc.reg_read(UC_SPARC_REG_PC))
class TestSparcRegRead(regress.RegressTest):
class TestSparc32RegRead(regress.RegressTest):
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def runTest(self):
uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC32 | UC_MODE_BIG_ENDIAN)

View File

@@ -1,10 +1,7 @@
import regress
import regress
from unicorn import *
from unicorn.arm_const import *
# issue #287
# Initial Register States: R0=3, R1=24, R2=16, R3=0
#
@@ -100,6 +97,7 @@ CODE = (
BASE = 0x00000000
def show_regs(uc):
regress.logger.debug('R0 : %08x', uc.reg_read(UC_ARM_REG_R0))
regress.logger.debug('R1 : %08x', uc.reg_read(UC_ARM_REG_R1))
@@ -126,7 +124,7 @@ def show_regs(uc):
regress.logger.debug('zero : %d', (flags >> 30) & 0b1)
class TestReadMem(regress.RegressTest):
class TestIssue287(regress.RegressTest):
def runTest(self):
uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)

View File

@@ -1,9 +1,9 @@
#!/usr/bin/python
# By Mariano Graziano
import struct
import platform
import regress
import struct
import unittest
from unicorn import *
from unicorn.x86_const import *
@@ -44,7 +44,8 @@ class Emulator:
return True
def hook_mem_invalid(self, uc, access, address, size, value, user_data):
regress.logger.debug("invalid mem access: access type = %d, to = %#x, size = %u, value = %#x", access, address, size, value)
regress.logger.debug("invalid mem access: access type = %d, to = %#x, size = %u, value = %#x", access, address,
size, value)
return True
@@ -65,7 +66,7 @@ class Emulator:
self.mu.reg_write(reg, value)
class Init(regress.RegressTest):
class TranslatorBuffer(regress.RegressTest):
def init_unicorn(self, ip, sp, magic):
emu = Emulator(ip, sp)
@@ -74,6 +75,7 @@ class Init(regress.RegressTest):
emu.emu(1)
@unittest.skipIf(platform.machine().lower() == 'aarch64', reason='TO BE CHECKED!')
def runTest(self):
ip_base = 0x000fffff816a0000 # was: 0xffffffff816a0000
sp_base = 0x000f88001b800000 # was: 0xffff88001b800000

View File

@@ -1,13 +1,10 @@
#!/usr/bin/env python
# Moshe Kravchik
import binascii
import regress
from unicorn import *
from unicorn.arm_const import *
# enable VFP
ENABLE_VFP_CODE = (
b"\x4f\xf4\x70\x03" # 00000016 mov.w r3, #0xf00000
@@ -17,7 +14,6 @@ ENABLE_VFP_CODE = (
b"\xe8\xee\x10\x3a" # 0000bfbe vmsr fpexc, r3
)
VLD_CODE = b"\x21\xf9\x0f\x6a" # 0000002a vld1.8 {d6, d7}, [r1]
VST_CODE = b"\x00\xf9\x0f\x6a" # 0000002e vst1.8 {d6, d7}, [r0]
@@ -27,6 +23,7 @@ SCRATCH_ADDRESS = 0x1000
class SIMDNotReadArm(regress.RegressTest):
def runTest(self):
code = ENABLE_VFP_CODE + VLD_CODE + VST_CODE
regress.logger.debug("Emulate THUMB code")

View File

@@ -1,11 +1,7 @@
#!/usr/bin/env python
import regress
from unicorn import *
from unicorn.x86_const import *
X86_CODE64 = b"\x90" # NOP

View File

@@ -1,13 +1,11 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
import regress
binary1 = b'\xb8\x02\x00\x00\x00' # mov eax, 2
binary2 = b'\xb8\x01\x00\x00\x00' # mov eax, 1
class WrongRIP(regress.RegressTest):
def test_step(self):
@@ -66,6 +64,6 @@ class WrongRIP(regress.RegressTest):
self.assertEqual(0x1, mu.reg_read(UC_X86_REG_EAX))
self.assertEqual(len(bin4), mu.reg_read(UC_X86_REG_EIP))
if __name__ == '__main__':
regress.main()

View File

@@ -1,12 +1,7 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
from unicorn.arm_const import *
CODE = (
b'\x48\x31' # adds r1, #0x48
b'\xff\x57' # ldrsb r7, [r7, r7]

View File

@@ -1,11 +1,10 @@
#!/usr/bin/python
# By Ryan Hileman, issue #16
import regress
from unicorn import *
from unicorn.arm_const import *
from unicorn.arm64_const import *
import regress
class WrongSPArm(regress.RegressTest):
@@ -24,5 +23,6 @@ class WrongSPArm(regress.RegressTest):
uc.reg_write(UC_ARM_REG_SP, 4)
self.assertEqual(0x4, uc.reg_read(UC_ARM_REG_SP))
if __name__ == '__main__':
regress.main()

View File

@@ -1,7 +1,4 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *

View File

@@ -1,7 +1,4 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
@@ -19,7 +16,6 @@ class WrongEFLAGS(regress.RegressTest):
uc.mem_write(0x6000b0, CODE)
uc.emu_start(0x6000b0, 0, count=1)
# Here's the original execution trace for this on actual hardware.
#
# (gdb) x/i $pc

View File

@@ -1,11 +1,7 @@
#!/usr/bin/env python
import regress
from unicorn import *
from unicorn.x86_const import *
CODE_ADDR = 0x40000
CODE_SIZE = 0x1000
@@ -15,16 +11,15 @@ SCRATCH_SIZE = 0x1000
SEGMENT_ADDR = 0x5000
SEGMENT_SIZE = 0x1000
FSMSR = 0xC0000100
GSMSR = 0xC0000101
def set_msr(uc, msr, value, scratch=SCRATCH_ADDR):
'''
"""
set the given model-specific register (MSR) to the given value.
this will clobber some memory at the given scratch address, as it emits some code.
'''
"""
# save clobbered registers
orax = uc.reg_read(UC_X86_REG_RAX)
ordx = uc.reg_read(UC_X86_REG_RDX)
@@ -47,10 +42,10 @@ def set_msr(uc, msr, value, scratch=SCRATCH_ADDR):
def get_msr(uc, msr, scratch=SCRATCH_ADDR):
'''
"""
fetch the contents of the given model-specific register (MSR).
this will clobber some memory at the given scratch address, as it emits some code.
'''
"""
# save clobbered registers
orax = uc.reg_read(UC_X86_REG_RAX)
ordx = uc.reg_read(UC_X86_REG_RDX)
@@ -75,32 +70,32 @@ def get_msr(uc, msr, scratch=SCRATCH_ADDR):
def set_gs(uc, addr):
'''
"""
set the GS.base hidden descriptor-register field to the given address.
this enables referencing the gs segment on x86-64.
'''
"""
return set_msr(uc, GSMSR, addr)
def get_gs(uc):
'''
"""
fetch the GS.base hidden descriptor-register field.
'''
"""
return get_msr(uc, GSMSR)
def set_fs(uc, addr):
'''
"""
set the FS.base hidden descriptor-register field to the given address.
this enables referencing the fs segment on x86-64.
'''
"""
return set_msr(uc, FSMSR, addr)
def get_fs(uc):
'''
"""
fetch the FS.base hidden descriptor-register field.
'''
"""
return get_msr(uc, FSMSR)

View File

@@ -1,7 +1,4 @@
#!/usr/bin/python
import regress
from unicorn import *
from unicorn.x86_const import *
@@ -21,7 +18,6 @@ class WrongEFLAGS2(regress.RegressTest):
uc.mem_write(0x6000b0, CODE)
uc.emu_start(0x6000b0, 0, count=1)
# Here's the original execution trace for this on actual hardware.
#
# (gdb) x/i $eip
@@ -39,5 +35,6 @@ class WrongEFLAGS2(regress.RegressTest):
self.assertEqual(0x202, uc.reg_read(UC_X86_REG_EFLAGS))
if __name__ == '__main__':
regress.main()

View File

@@ -1,9 +1,5 @@
#!/usr/bin/env python
import regress
from unicorn import *
from unicorn.x86_const import *
CODE = (
b'\xb8\x00\x00\x00\x02' # mov eax, 0x2000000

View File

@@ -1,12 +1,8 @@
#!/usr/bin/env python
import regress
from unicorn import *
from unicorn.x86_const import *
from struct import pack
F_GRANULARITY = 0x8
F_PROT_32 = 0x4
F_LONG = 0x2
@@ -38,6 +34,7 @@ S_PRIV_0 = 0x0
CODE = b'\x65\x33\x0d\x18\x00\x00\x00' # xor ecx, dword ptr gs:[0x18]
def create_selector(idx, flags):
to_ret = flags
to_ret |= idx << 3
@@ -72,6 +69,7 @@ GDT_ENTRY_SIZE = 0x8
SEGMENT_ADDR = 0x5000
SEGMENT_SIZE = 0x1000
class GdtRead(regress.RegressTest):
def test_gdt(self):
@@ -85,7 +83,8 @@ class GdtRead(regress.RegressTest):
uc.mem_write(CODE_ADDR, CODE)
uc.mem_write(SEGMENT_ADDR + 0x18, b'AAAA')
gdt_entry = create_gdt_entry(SEGMENT_ADDR, SEGMENT_SIZE, A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_3 | A_DIR_CON_BIT, F_PROT_32)
gdt_entry = create_gdt_entry(SEGMENT_ADDR, SEGMENT_SIZE,
A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_3 | A_DIR_CON_BIT, F_PROT_32)
uc.mem_write(GDT_ADDR + 8, gdt_entry)
uc.reg_write(UC_X86_REG_GDTR, (0, GDT_ADDR, GDT_LIMIT, 0x0))

View File

@@ -1,10 +1,7 @@
import regress
from unicorn import *
from unicorn.x86_const import *
CODE = (
b'\x8b\x83\xd4\x05\x00\x00' # mov eax, DWORD PTR [ebx+0x5d4]
b'\x8b\x93\x80\x05\x00\x00' # mov edx, DWORD PTR [ebx+0x580]

View File

@@ -1,8 +1,5 @@
#!/usr/bin/env python
import os
import regress
from unicorn import *
from unicorn.x86_const import *
@@ -12,12 +9,14 @@ filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'x86_self_m
CODE_ADDR = 0x08048000
STACK_ADDR = 0x2000000
CODE = open(filename, 'rb').read()
with open(filename, 'rb') as f:
CODE = f.read()
CODE_SIZE = len(CODE) + (0x1000 - len(CODE) % 0x1000)
STACK_SIZE = 0x8000
ENTRY_POINT = 0x8048074
def hook_intr(uc, intno, data):
uc.emu_stop()

View File

@@ -1,10 +1,7 @@
import regress
from unicorn import *
from unicorn.x86_const import *
NOPSLED = b"\x90" * 5