Merge branch 'dev' into uc-py-next
This commit is contained in:
commit
7819912abb
6
.github/workflows/Crate-publishing.yml
vendored
6
.github/workflows/Crate-publishing.yml
vendored
@ -67,6 +67,12 @@ jobs:
|
||||
run: |
|
||||
choco install ninja cmake
|
||||
|
||||
- name: '🛠️ macOS build dependencies'
|
||||
if: contains(matrix.config.os, 'macOS')
|
||||
shell: bash
|
||||
run: |
|
||||
brew install p7zip cmake ninja pkg-config
|
||||
|
||||
- name: '🚧 Cargo test'
|
||||
if: "!startsWith(github.ref, 'refs/tags')"
|
||||
run: |
|
||||
|
436
.github/workflows/Nuget-publishing.yml
vendored
Normal file
436
.github/workflows/Nuget-publishing.yml
vendored
Normal file
@ -0,0 +1,436 @@
|
||||
name: Nuget 📦 Distribution
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- ".gitignore"
|
||||
- "docs/**"
|
||||
- "README"
|
||||
- "CREDITS.TXT"
|
||||
- "COPYING_GLIB"
|
||||
- "COPYING.LGPL2"
|
||||
- "AUTHORS.TXT"
|
||||
- "CHANGELOG"
|
||||
- "COPYING"
|
||||
branches:
|
||||
- dev
|
||||
- master
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
Windows:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
name: ${{ matrix.config.name }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
os: windows-2019,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-ver: '3.8',
|
||||
name: 'windows-x64 MSVC 64bit shared',
|
||||
msvc-arch: x64,
|
||||
artifact: 'windows_msvc64_shared.7z',
|
||||
shared: 'yes',
|
||||
build_type: 'Release',
|
||||
archiver: '7z a',
|
||||
generators: 'Visual Studio 16 2019'
|
||||
}
|
||||
- {
|
||||
os: windows-2019,
|
||||
arch: x86,
|
||||
python-arch: x86,
|
||||
python-ver: '3.8',
|
||||
name: 'windows-x86 MSVC 32bit shared',
|
||||
msvc-arch: x86,
|
||||
artifact: 'windows_msvc32_shared.7z',
|
||||
shared: 'yes',
|
||||
build_type: 'Release',
|
||||
archiver: '7z a',
|
||||
generators: 'Visual Studio 16 2019'
|
||||
}
|
||||
compiler: [ gcc ]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: '🛠️ Win MSVC 64 setup'
|
||||
if: contains(matrix.config.name, 'MSVC 64')
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
|
||||
- name: '🛠️ Win MSVC 64 dev cmd setup'
|
||||
if: contains(matrix.config.name, 'MSVC 64')
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x64
|
||||
|
||||
- name: '🚧 Win MSVC 64 build'
|
||||
if: contains(matrix.config.name, 'MSVC 64')
|
||||
shell: bash
|
||||
run: |
|
||||
choco install ninja cmake
|
||||
ninja --version
|
||||
cmake --version
|
||||
mkdir build
|
||||
cmake \
|
||||
-S . \
|
||||
-B . \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip --config ${{ matrix.config.build_type }}
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
mv Release instdir
|
||||
|
||||
- name: '🛠️ Win MSVC 32 setup'
|
||||
if: contains(matrix.config.name, 'MSVC 32')
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x86
|
||||
|
||||
- name: '🚧 Win MSVC 32 build'
|
||||
if: contains(matrix.config.name, 'MSVC 32')
|
||||
shell: bash
|
||||
run: |
|
||||
choco install ninja cmake
|
||||
ninja --version
|
||||
cmake --version
|
||||
mkdir build
|
||||
cmake \
|
||||
-S . \
|
||||
-B . \
|
||||
-A "win32" \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip --config ${{ matrix.config.build_type }}
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
mv Release instdir
|
||||
|
||||
- name: '📦 Pack artifact'
|
||||
if: always()
|
||||
shell: bash
|
||||
working-directory: instdir
|
||||
run: |
|
||||
ls -laR
|
||||
${{ matrix.config.archiver }} ../${{ matrix.config.artifact }} . ../test*
|
||||
|
||||
- name: '📤 Upload artifact'
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
path: ./${{ matrix.config.artifact }}
|
||||
name: ${{ matrix.config.artifact }}
|
||||
|
||||
Macos:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
name: ${{ matrix.config.name }} - ${{ matrix.compiler }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
os: macos-latest,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-ver: '3.8',
|
||||
name: 'macos-x64 cmake shared',
|
||||
shared: 'yes',
|
||||
artifact: 'macos-cmake-shared-x64.7z',
|
||||
build_type: 'Release',
|
||||
archiver: '7za a',
|
||||
generators: 'Ninja'
|
||||
}
|
||||
compiler: [ gcc ]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: '🚧 Mac build'
|
||||
if: contains(matrix.config.name, 'macos-x64')
|
||||
shell: bash
|
||||
run: |
|
||||
brew install p7zip cmake ninja pkg-config
|
||||
ninja --version
|
||||
cmake --version
|
||||
mkdir build
|
||||
mkdir instdir
|
||||
cmake \
|
||||
-S . \
|
||||
-B . \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
|
||||
- name: '📦 Pack artifact'
|
||||
if: always()
|
||||
shell: bash
|
||||
working-directory: instdir
|
||||
run: |
|
||||
ls -laR
|
||||
${{ matrix.config.archiver }} ../${{ matrix.config.artifact }} . ../test*
|
||||
|
||||
- name: '📤 Upload artifact'
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
path: ./${{ matrix.config.artifact }}
|
||||
name: ${{ matrix.config.artifact }}
|
||||
|
||||
Linux:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
name: ${{ matrix.config.name }} - ${{ matrix.compiler }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
os: ubuntu-latest,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-ver: '3.8',
|
||||
name: 'ubuntu-x64 cmake shared',
|
||||
shared: 'yes',
|
||||
artifact: 'ubuntu-cmake-shared-x64.7z',
|
||||
build_type: 'Release',
|
||||
archiver: '7z a',
|
||||
generators: 'Ninja'
|
||||
}
|
||||
- {
|
||||
os: ubuntu-latest,
|
||||
arch: x86,
|
||||
python-arch: x86,
|
||||
python-ver: '3.8',
|
||||
name: 'ubuntu-x86 cmake shared',
|
||||
shared: 'yes',
|
||||
artifact: 'ubuntu-cmake-shared-x86.7z',
|
||||
build_type: 'Release',
|
||||
archiver: '7z a',
|
||||
generators: 'Ninja'
|
||||
}
|
||||
- {
|
||||
os: ubuntu-latest,
|
||||
arch: aarch64,
|
||||
python-arch: aarch64,
|
||||
python-ver: '3.8',
|
||||
name: 'ubuntu-aarch64 cmake',
|
||||
artifact: 'ubuntu-cmake-aarch64.7z',
|
||||
build_type: 'Release',
|
||||
archiver: '7z a',
|
||||
generators: 'Ninja',
|
||||
distro: ubuntu20.04
|
||||
}
|
||||
- {
|
||||
os: ubuntu-latest,
|
||||
arch: ppc64le,
|
||||
python-arch: ppc,
|
||||
python-ver: '3.8',
|
||||
name: 'ubuntu-ppc64le cmake',
|
||||
artifact: 'ubuntu-cmake-ppc64le.7z',
|
||||
build_type: 'Release',
|
||||
archiver: '7z a',
|
||||
generators: 'Ninja',
|
||||
distro: ubuntu20.04
|
||||
}
|
||||
compiler: [ gcc ]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: '🚧 Linux x64/x86 build'
|
||||
if: contains(matrix.config.arch, 'x64') || contains(matrix.config.arch, 'x86')
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: |
|
||||
if [ ${{ matrix.config.arch }} == 'x64' ]; then
|
||||
sudo apt install -q -y libcmocka-dev ninja-build
|
||||
else
|
||||
export CFLAGS="-m32" LDFLAGS="-m32" LDFLAGS_STATIC="-m32" UNICORN_QEMU_FLAGS="--cpu=i386"
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt install -q -y lib32ncurses-dev lib32z1-dev lib32gcc-9-dev libc6-dev-i386 gcc-multilib \
|
||||
libcmocka-dev:i386 libcmocka0:i386 libc6:i386 libgcc-s1:i386 ninja-build
|
||||
fi
|
||||
mkdir build
|
||||
mkdir instdir
|
||||
cmake \
|
||||
-S . \
|
||||
-B . \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
|
||||
- name: '🚧 Linux ppc64le/aarch64 build'
|
||||
if: contains(matrix.config.arch, 'ppc64le') || contains(matrix.config.arch, 'aarch64')
|
||||
uses: uraimo/run-on-arch-action@v2.0.5
|
||||
with:
|
||||
arch: ${{ matrix.config.arch }}
|
||||
distro: ${{ matrix.config.distro }}
|
||||
setup: |
|
||||
mkdir -p "${PWD}/instdir"
|
||||
dockerRunArgs: |
|
||||
--volume "${PWD}/instdir:/instdir"
|
||||
shell: /bin/sh
|
||||
install: |
|
||||
apt-get update -q -y
|
||||
apt-get install -q -y git cmake build-essential automake libcmocka-dev pkg-config ${{ matrix.compiler }} ninja-build
|
||||
run: |
|
||||
mkdir build
|
||||
cmake \
|
||||
-S . \
|
||||
-B . \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=/instdir
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
|
||||
- name: '📦 Pack artifact'
|
||||
if: always()
|
||||
shell: bash
|
||||
working-directory: instdir
|
||||
run: |
|
||||
ls -laR
|
||||
${{ matrix.config.archiver }} ../${{ matrix.config.artifact }} . ../test*
|
||||
|
||||
- name: '📤 Upload artifact'
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
path: ./${{ matrix.config.artifact }}
|
||||
name: ${{ matrix.config.artifact }}
|
||||
|
||||
publish:
|
||||
needs: ["Windows", "Macos", "Linux"]
|
||||
if: ${{ needs.Windows.result == 'success' && needs.Macos.result == 'success' && needs.Linux.result == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: 🛠️ Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: 🛠️ Extract artifacts
|
||||
shell: python
|
||||
run: |
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
artifactPath = os.path.join(os.getcwd(), "artifacts")
|
||||
bindingsPath = os.path.join(os.getcwd(), "bindings", "dotnet", "UnicornEngine")
|
||||
|
||||
ARTIFACT_CONFIG = {
|
||||
"ubuntu-cmake-aarch64.7z": {
|
||||
"sourceDir": "lib/",
|
||||
"sourceFile": "libunicorn.so.*",
|
||||
"destDir": "runtimes/linux-arm64/native",
|
||||
"destFile": "libunicorn.so"
|
||||
},
|
||||
"ubuntu-cmake-ppc64le.7z": {
|
||||
"sourceDir": "lib/",
|
||||
"sourceFile": "libunicorn.so.*",
|
||||
"destDir": "runtimes/linux-ppc64le/native",
|
||||
"destFile": "libunicorn.so"
|
||||
},
|
||||
"ubuntu-cmake-shared-x86.7z": {
|
||||
"sourceDir": "lib/",
|
||||
"sourceFile": "libunicorn.so.*",
|
||||
"destDir": "runtimes/linux-x64/native",
|
||||
"destFile": "libunicorn.so"
|
||||
},
|
||||
"macos-cmake-shared-x64.7z": {
|
||||
"sourceDir": "lib/",
|
||||
"sourceFile": "libunicorn.*.dylib",
|
||||
"destDir": "runtimes/osx-x64/native",
|
||||
"destFile": "libunicorn.dylib"
|
||||
},
|
||||
"windows_msvc64_shared.7z": {
|
||||
"sourceDir": "",
|
||||
"sourceFile": "unicorn.dll",
|
||||
"destDir": "runtimes/win-x64/native",
|
||||
"destFile": "unicorn.dll"
|
||||
},
|
||||
"windows_msvc32_shared.7z": {
|
||||
"sourceDir": "",
|
||||
"sourceFile": "unicorn.dll",
|
||||
"destDir": "runtimes/win-x86/native",
|
||||
"destFile": "unicorn.dll"
|
||||
}
|
||||
}
|
||||
|
||||
if len(os.listdir(artifactPath)) < len(ARTIFACT_CONFIG.keys()):
|
||||
print("Some artifacts are missing. Aborting.")
|
||||
exit(1)
|
||||
|
||||
for artifact in os.listdir(artifactPath):
|
||||
if artifact in ARTIFACT_CONFIG.keys():
|
||||
print("Working on:", artifact)
|
||||
config = ARTIFACT_CONFIG[artifact]
|
||||
destDir = os.path.join(bindingsPath, config["destDir"])
|
||||
print("Creating dir:", destDir)
|
||||
os.makedirs(destDir, exist_ok=True)
|
||||
|
||||
print(f"Extracting library from 7z file to: {config['destDir']}/{config['sourceFile']}")
|
||||
result = subprocess.run(["7z", "e", f"-o{destDir}/", os.path.join(artifactPath, artifact), f"{config['sourceDir']}{config['sourceFile']}"])
|
||||
result.check_returncode()
|
||||
|
||||
if config["sourceFile"] != config["destFile"]:
|
||||
output = subprocess.run(["ls", destDir], stdout=subprocess.PIPE)
|
||||
sourceFile = output.stdout.decode().strip()
|
||||
print(f"Renaming {sourceFile} to {config['destFile']}")
|
||||
os.rename(os.path.join(destDir, sourceFile), os.path.join(destDir, config["destFile"]))
|
||||
|
||||
print("Done!")
|
||||
|
||||
- name: 🛠️ Get short sha
|
||||
id: git_short_sha
|
||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
- name: 🛠️ Authenticate to Github Packages
|
||||
working-directory: bindings/dotnet/UnicornEngine
|
||||
run: dotnet nuget add source --username "${{ github.repository_owner }}" --password "${{ secrets.GITHUB_TOKEN }}" --store-password-in-clear-text --name github "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json"
|
||||
|
||||
- name: 🛠️ List all native libraries
|
||||
working-directory: bindings/dotnet/UnicornEngine
|
||||
run: find ./runtimes -type f -print
|
||||
|
||||
- name: 🚧 Package .NET distribution
|
||||
working-directory: bindings/dotnet/UnicornEngine
|
||||
run: |
|
||||
[[ "${{ github.ref_name }}" == "master" ]] \
|
||||
&& dotnet pack -c Release \
|
||||
|| dotnet pack -c Release --version-suffix="${{ steps.git_short_sha.outputs.result }}"
|
||||
|
||||
- name: '📤 Upload artifact'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
path: ${{ github.workspace }}/bindings/dotnet/UnicornEngine/bin/Release/UnicornEngine.Unicorn.*.nupkg
|
||||
|
||||
- name: 📦 Publish to Github Packages
|
||||
working-directory: bindings/dotnet/UnicornEngine
|
||||
run: dotnet nuget push "bin/Release/UnicornEngine.Unicorn.*.nupkg" --source "github" --api-key "${{ secrets.GHPR_TOKEN }}"
|
||||
|
||||
- name: 📦 Publish Nuget package
|
||||
working-directory: bindings/dotnet/UnicornEngine
|
||||
run: dotnet nuget push "bin/Release/UnicornEngine.Unicorn.*.nupkg" -k "$NUGET_AUTH_TOKEN" -s https://api.nuget.org/v3/index.json
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_KEY }}
|
7
.github/workflows/PyPI-publishing.yml
vendored
7
.github/workflows/PyPI-publishing.yml
vendored
@ -96,7 +96,12 @@ jobs:
|
||||
run: |
|
||||
choco install ninja cmake
|
||||
|
||||
- name: '🛠️ Install dependencies'
|
||||
- name: '🛠️ macOS dependencies'
|
||||
if: contains(matrix.config.name, 'macos')
|
||||
run: |
|
||||
brew install p7zip cmake ninja pkg-config
|
||||
|
||||
- name: '🛠️ pip dependencies'
|
||||
run: |
|
||||
pip install setuptools wheel
|
||||
|
||||
|
4
.github/workflows/build-uc2.yml
vendored
4
.github/workflows/build-uc2.yml
vendored
@ -305,7 +305,7 @@ jobs:
|
||||
if: contains(matrix.config.name, 'macos-x64')
|
||||
shell: bash
|
||||
run: |
|
||||
brew install p7zip cmake ninja
|
||||
brew install p7zip cmake ninja pkg-config
|
||||
ninja --version
|
||||
cmake --version
|
||||
mkdir build
|
||||
@ -325,7 +325,7 @@ jobs:
|
||||
if: contains(matrix.config.name, 'android')
|
||||
shell: bash
|
||||
run: |
|
||||
brew install p7zip cmake ninja
|
||||
brew install p7zip cmake ninja pkg-config
|
||||
mkdir build
|
||||
mkdir instdir
|
||||
cmake . -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \
|
||||
|
6
Brewfile
6
Brewfile
@ -1,6 +0,0 @@
|
||||
# Travis CI setup for MacOS Brew
|
||||
|
||||
# used for testing framework
|
||||
brew "cmocka"
|
||||
# used for cross assembly of code for testing
|
||||
brew "crosstool-ng"
|
@ -45,7 +45,7 @@ set(CMAKE_C_STANDARD 11)
|
||||
|
||||
set(UNICORN_VERSION_MAJOR 2)
|
||||
set(UNICORN_VERSION_MINOR 0)
|
||||
set(UNICORN_VERSION_PATCH 1)
|
||||
set(UNICORN_VERSION_PATCH 2)
|
||||
|
||||
include(bundle_static.cmake)
|
||||
|
||||
|
17
Cargo.toml
17
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "unicorn-engine"
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
authors = ["Ziqiao Kong", "Lukas Seidel"]
|
||||
documentation = "https://github.com/unicorn-engine/unicorn/wiki"
|
||||
edition = "2021"
|
||||
@ -39,5 +39,16 @@ cmake = { version = "0.1" }
|
||||
pkg-config = { version = "0.3" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
dynamic_linkage = []
|
||||
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_riscv = []
|
||||
arch_mips = []
|
||||
arch_sparc = []
|
||||
arch_m68k = []
|
||||
arch_ppc = []
|
||||
arch_s390x = []
|
||||
arch_tricore = []
|
||||
|
@ -90,10 +90,10 @@ template = {
|
||||
'comment_close': '',
|
||||
},
|
||||
'dotnet': {
|
||||
'header': "// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT\n\nnamespace UnicornManaged.Const\n\nopen System\n\n[<AutoOpen>]\nmodule %s =\n",
|
||||
'header': "// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT\n\nnamespace UnicornEngine.Const\n\nopen System\n\n[<AutoOpen>]\nmodule %s =\n",
|
||||
'footer': "\n",
|
||||
'line_format': ' let UC_%s = %s\n',
|
||||
'out_file': os.path.join('dotnet', 'UnicornManaged', 'Const', '%s.fs'),
|
||||
'out_file': os.path.join('dotnet', 'UnicornEngine', 'Const', '%s.fs'),
|
||||
# prefixes for constant filenames of all archs - case sensitive
|
||||
'arm.h': 'Arm',
|
||||
'arm64.h': 'Arm64',
|
||||
|
@ -5,7 +5,7 @@ VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnicornSamples", "UnicornSamples\UnicornSamples.csproj", "{B80B5987-1E24-4309-8BF9-C4F91270F21C}"
|
||||
EndProject
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "UnicornManaged", "UnicornManaged\UnicornManaged.fsproj", "{0C21F1C1-2725-4A46-9022-1905F85822A5}"
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "UnicornEngine", "UnicornEngine\UnicornEngine.fsproj", "{0C21F1C1-2725-4A46-9022-1905F85822A5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace UnicornManaged.Binding
|
||||
namespace UnicornEngine.Binding
|
||||
|
||||
|
||||
module BindingFactory =
|
@ -1,4 +1,4 @@
|
||||
namespace UnicornManaged.Binding
|
||||
namespace UnicornEngine.Binding
|
||||
|
||||
open System
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace UnicornManaged.Binding
|
||||
namespace UnicornEngine.Binding
|
||||
|
||||
open System
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace UnicornManaged.Binding
|
||||
namespace UnicornEngine.Binding
|
||||
|
||||
open System
|
||||
open System.Runtime.InteropServices
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
||||
@ -9,13 +9,13 @@ module Common =
|
||||
let UC_API_MAJOR = 2
|
||||
|
||||
let UC_API_MINOR = 0
|
||||
let UC_API_PATCH = 1
|
||||
let UC_API_EXTRA = 255
|
||||
let UC_API_PATCH = 2
|
||||
let UC_API_EXTRA = 1
|
||||
let UC_VERSION_MAJOR = 2
|
||||
|
||||
let UC_VERSION_MINOR = 0
|
||||
let UC_VERSION_PATCH = 1
|
||||
let UC_VERSION_EXTRA = 255
|
||||
let UC_VERSION_PATCH = 2
|
||||
let UC_VERSION_EXTRA = 1
|
||||
let UC_SECOND_SCALE = 1000000
|
||||
let UC_MILISECOND_SCALE = 1000
|
||||
let UC_ARCH_ARM = 1
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,6 +1,6 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
namespace UnicornEngine.Const
|
||||
|
||||
open System
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace UnicornManaged
|
||||
namespace UnicornEngine
|
||||
|
||||
open System
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace UnicornManaged
|
||||
namespace UnicornEngine
|
||||
|
||||
open System
|
||||
open System.Runtime.InteropServices
|
||||
@ -14,10 +14,10 @@ type internal BlockHookInternal = delegate of IntPtr * Int64 * Int32 * IntPtr ->
|
||||
type internal InterruptHookInternal = delegate of IntPtr * Int32 * IntPtr -> unit
|
||||
|
||||
[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>]
|
||||
type internal MemReadHookInternal = delegate of IntPtr * Int64 * Int32 * IntPtr -> unit
|
||||
type internal MemReadHookInternal = delegate of IntPtr * Int32 * Int64 * Int32 * IntPtr -> unit
|
||||
|
||||
[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>]
|
||||
type internal MemWriteHookInternal = delegate of IntPtr * Int64 * Int32 * Int64 * IntPtr -> unit
|
||||
type internal MemWriteHookInternal = delegate of IntPtr * Int32 * Int64 * Int32 * Int64 * IntPtr -> unit
|
||||
|
||||
[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>]
|
||||
type internal EventMemHookInternal = delegate of IntPtr * Int32 * Int64 * Int32 * Int64 * IntPtr-> Boolean
|
@ -1,11 +1,11 @@
|
||||
namespace UnicornManaged
|
||||
namespace UnicornEngine
|
||||
|
||||
open System
|
||||
open System.Collections.Generic
|
||||
open System.Runtime.InteropServices
|
||||
open System.Linq
|
||||
open UnicornManaged.Const
|
||||
open UnicornManaged.Binding
|
||||
open UnicornEngine.Const
|
||||
open UnicornEngine.Binding
|
||||
|
||||
// exported hooks
|
||||
type CodeHook = delegate of Unicorn * Int64 * Int32 * Object -> unit
|
||||
@ -32,6 +32,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
let _outHooks = new List<(OutHook * Object)>()
|
||||
let _syscallHooks = new List<(SyscallHook * Object)>()
|
||||
let _disposablePointers = new List<nativeint>()
|
||||
let _hookInternals = new List<Object>();
|
||||
|
||||
let _eventMemMap =
|
||||
[
|
||||
@ -153,7 +154,9 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
|
||||
|
||||
if _codeHooks |> Seq.isEmpty then
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline))
|
||||
let codeHookInternal = new CodeHookInternal(trampoline)
|
||||
_hookInternals.Add(codeHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(codeHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
@ -172,7 +175,9 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
|
||||
|
||||
if _blockHooks |> Seq.isEmpty then
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new BlockHookInternal(trampoline))
|
||||
let blockHookInternal = new BlockHookInternal(trampoline)
|
||||
_hookInternals.Add(blockHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(blockHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
@ -188,7 +193,9 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, intNumber, userData))
|
||||
|
||||
if _interruptHooks |> Seq.isEmpty then
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InterruptHookInternal(trampoline))
|
||||
let interruptHookInternal = new InterruptHookInternal(trampoline)
|
||||
_hookInternals.Add(interruptHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(interruptHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, hookBegin, hookEnd) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
@ -202,12 +209,14 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
hookDel _interruptHooks callback
|
||||
|
||||
member this.AddMemReadHook(callback: MemReadHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
|
||||
let trampoline(u: IntPtr) (_eventType: Int32) (addr: Int64) (size: Int32) (user: IntPtr) =
|
||||
_memReadHooks
|
||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
|
||||
|
||||
if _memReadHooks |> Seq.isEmpty then
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemReadHookInternal(trampoline))
|
||||
let memReadHookInternal = new MemReadHookInternal(trampoline)
|
||||
_hookInternals.Add(memReadHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(memReadHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
@ -218,12 +227,14 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
hookDel _memReadHooks callback
|
||||
|
||||
member this.AddMemWriteHook(callback: MemWriteHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
|
||||
let trampoline(u: IntPtr) (_eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
|
||||
_memWriteHooks
|
||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, value, userData))
|
||||
|
||||
if _memWriteHooks |> Seq.isEmpty then
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemWriteHookInternal(trampoline))
|
||||
let memWriteHookInternal = new MemWriteHookInternal(trampoline)
|
||||
_hookInternals.Add(memWriteHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(memWriteHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
@ -247,9 +258,11 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|
||||
|> Seq.filter(fun eventFlag -> _memEventHooks.[eventFlag] |> Seq.isEmpty)
|
||||
|> Seq.iter(fun eventFlag ->
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new EventMemHookInternal(trampoline))
|
||||
let memEventHookInternal = new EventMemHookInternal(trampoline)
|
||||
_hookInternals.Add(memEventHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(memEventHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0) |> this.CheckResult with
|
||||
match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
)
|
||||
|
||||
@ -272,9 +285,11 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
|> Seq.last
|
||||
|
||||
if _inHooks |> Seq.isEmpty then
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InHookInternal(trampoline))
|
||||
let inHookInternal = new InHookInternal(trampoline)
|
||||
_hookInternals.Add(inHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(inHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_IN) |> this.CheckResult with
|
||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_IN) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
|
||||
_inHooks.Add(callback, userData)
|
||||
@ -288,9 +303,11 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, port, size, value, userData))
|
||||
|
||||
if _outHooks |> Seq.isEmpty then
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new OutHookInternal(trampoline))
|
||||
let outHookInternal = new OutHookInternal(trampoline)
|
||||
_hookInternals.Add(outHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(outHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_OUT) |> this.CheckResult with
|
||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_OUT) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
|
||||
_outHooks.Add(callback, userData)
|
||||
@ -304,9 +321,11 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, userData))
|
||||
|
||||
if _syscallHooks |> Seq.isEmpty then
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(new SyscallHookInternal(trampoline))
|
||||
let syscallHookInternal = new SyscallHookInternal(trampoline)
|
||||
_hookInternals.Add(syscallHookInternal)
|
||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(syscallHookInternal)
|
||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with
|
||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with
|
||||
| Some e -> raise e | None -> ()
|
||||
|
||||
_syscallHooks.Add(callback, userData)
|
@ -1,11 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>UnicornManaged</RootNamespace>
|
||||
<AssemblyName>UnicornManaged</AssemblyName>
|
||||
<PackageId>UnicornEngine.Unicorn</PackageId>
|
||||
<Authors>UnicornEngine</Authors>
|
||||
<Copyright>Copyright © Antonio Parata 2016</Copyright>
|
||||
<RepositoryUrl>https://github.com/unicorn-engine/unicorn</RepositoryUrl>
|
||||
<Version>2.0.0</Version>
|
||||
<PackageDescription>.NET bindings for unicorn</PackageDescription>
|
||||
<VersionPrefix>2.0.2-rc1</VersionPrefix>
|
||||
<VersionSuffix>$(VersionSuffix)</VersionSuffix>
|
||||
<ProjectGuid>0c21f1c1-2725-4a46-9022-1905f85822a5</ProjectGuid>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
@ -15,6 +17,10 @@
|
||||
<WarningLevel>3</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Const\Arm.fs" />
|
||||
<Compile Include="Const\Arm64.fs" />
|
||||
@ -36,4 +42,8 @@
|
||||
<Compile Include="ConvertUtility.fs" />
|
||||
<Compile Include="Unicorn.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="runtimes\**" PackagePath="runtimes" Visible="false" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,4 +1,4 @@
|
||||
namespace UnicornManaged
|
||||
namespace UnicornEngine
|
||||
|
||||
open System
|
||||
|
@ -3,8 +3,8 @@ using Gee.External.Capstone.X86;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using UnicornManaged;
|
||||
using UnicornManaged.Const;
|
||||
using UnicornEngine;
|
||||
using UnicornEngine.Const;
|
||||
|
||||
namespace UnicornSamples
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
<AssemblyName>UnicornSamples</AssemblyName>
|
||||
<Copyright>Copyright © Antonio Parata 2016</Copyright>
|
||||
<RepositoryUrl>https://github.com/unicorn-engine/unicorn</RepositoryUrl>
|
||||
<Version>2.0.0</Version>
|
||||
<Version>2.0.2-rc1</Version>
|
||||
<ProjectGuid>{B80B5987-1E24-4309-8BF9-C4F91270F21C}</ProjectGuid>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
@ -17,9 +17,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\UnicornManaged\UnicornManaged.fsproj">
|
||||
<ProjectReference Include="..\UnicornEngine\UnicornEngine.fsproj">
|
||||
<Project>{0c21f1c1-2725-4a46-9022-1905f85822a5}</Project>
|
||||
<Name>UnicornManaged</Name>
|
||||
<Name>UnicornEngine</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -3,8 +3,8 @@ using Gee.External.Capstone.X86;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using UnicornManaged;
|
||||
using UnicornManaged.Const;
|
||||
using UnicornEngine;
|
||||
using UnicornEngine.Const;
|
||||
|
||||
namespace UnicornSamples
|
||||
{
|
||||
|
@ -4,13 +4,13 @@ const (
|
||||
API_MAJOR = 2
|
||||
|
||||
API_MINOR = 0
|
||||
API_PATCH = 1
|
||||
API_EXTRA = 255
|
||||
API_PATCH = 2
|
||||
API_EXTRA = 1
|
||||
VERSION_MAJOR = 2
|
||||
|
||||
VERSION_MINOR = 0
|
||||
VERSION_PATCH = 1
|
||||
VERSION_EXTRA = 255
|
||||
VERSION_PATCH = 2
|
||||
VERSION_EXTRA = 1
|
||||
SECOND_SCALE = 1000000
|
||||
MILISECOND_SCALE = 1000
|
||||
ARCH_ARM = 1
|
||||
|
@ -6,13 +6,13 @@ public interface UnicornConst {
|
||||
public static final int UC_API_MAJOR = 2;
|
||||
|
||||
public static final int UC_API_MINOR = 0;
|
||||
public static final int UC_API_PATCH = 1;
|
||||
public static final int UC_API_EXTRA = 255;
|
||||
public static final int UC_API_PATCH = 2;
|
||||
public static final int UC_API_EXTRA = 1;
|
||||
public static final int UC_VERSION_MAJOR = 2;
|
||||
|
||||
public static final int UC_VERSION_MINOR = 0;
|
||||
public static final int UC_VERSION_PATCH = 1;
|
||||
public static final int UC_VERSION_EXTRA = 255;
|
||||
public static final int UC_VERSION_PATCH = 2;
|
||||
public static final int UC_VERSION_EXTRA = 1;
|
||||
public static final int UC_SECOND_SCALE = 1000000;
|
||||
public static final int UC_MILISECOND_SCALE = 1000;
|
||||
public static final int UC_ARCH_ARM = 1;
|
||||
|
@ -7,13 +7,13 @@ interface
|
||||
const UC_API_MAJOR = 2;
|
||||
|
||||
UC_API_MINOR = 0;
|
||||
UC_API_PATCH = 1;
|
||||
UC_API_EXTRA = 255;
|
||||
UC_API_PATCH = 2;
|
||||
UC_API_EXTRA = 1;
|
||||
UC_VERSION_MAJOR = 2;
|
||||
|
||||
UC_VERSION_MINOR = 0;
|
||||
UC_VERSION_PATCH = 1;
|
||||
UC_VERSION_EXTRA = 255;
|
||||
UC_VERSION_PATCH = 2;
|
||||
UC_VERSION_EXTRA = 1;
|
||||
UC_SECOND_SCALE = 1000000;
|
||||
UC_MILISECOND_SCALE = 1000;
|
||||
UC_ARCH_ARM = 1;
|
||||
|
@ -8,6 +8,7 @@ import subprocess
|
||||
import shutil
|
||||
import sys
|
||||
import platform
|
||||
import setuptools
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import setup
|
||||
@ -29,7 +30,7 @@ SRC_DIR = os.path.join(ROOT_DIR, 'src')
|
||||
UC_DIR = SRC_DIR if os.path.exists(SRC_DIR) else os.path.join(ROOT_DIR, '../..')
|
||||
BUILD_DIR = os.path.join(UC_DIR, 'build_python')
|
||||
|
||||
VERSION = "2.0.1.post1"
|
||||
VERSION = "2.0.2"
|
||||
|
||||
if SYSTEM == 'darwin':
|
||||
LIBRARY_FILE = "libunicorn.2.dylib"
|
||||
|
@ -2,13 +2,13 @@
|
||||
UC_API_MAJOR = 2
|
||||
|
||||
UC_API_MINOR = 0
|
||||
UC_API_PATCH = 1
|
||||
UC_API_EXTRA = 255
|
||||
UC_API_PATCH = 2
|
||||
UC_API_EXTRA = 1
|
||||
UC_VERSION_MAJOR = 2
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_PATCH = 1
|
||||
UC_VERSION_EXTRA = 255
|
||||
UC_VERSION_PATCH = 2
|
||||
UC_VERSION_EXTRA = 1
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
|
@ -4,13 +4,13 @@ module UnicornEngine
|
||||
UC_API_MAJOR = 2
|
||||
|
||||
UC_API_MINOR = 0
|
||||
UC_API_PATCH = 1
|
||||
UC_API_EXTRA = 255
|
||||
UC_API_PATCH = 2
|
||||
UC_API_EXTRA = 1
|
||||
UC_VERSION_MAJOR = 2
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_PATCH = 1
|
||||
UC_VERSION_EXTRA = 255
|
||||
UC_VERSION_PATCH = 2
|
||||
UC_VERSION_EXTRA = 1
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
|
@ -84,6 +84,43 @@ fn build_with_cmake() {
|
||||
config.generator("Ninja");
|
||||
}
|
||||
|
||||
let mut archs = String::new();
|
||||
|
||||
if std::env::var("CARGO_FEATURE_ARCH_X86").is_ok() {
|
||||
archs.push_str("x86;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_ARM").is_ok() {
|
||||
archs.push_str("arm;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_AARCH64").is_ok() {
|
||||
archs.push_str("aarch64;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_RISCV").is_ok() {
|
||||
archs.push_str("riscv;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_MIPS").is_ok() {
|
||||
archs.push_str("mips;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_SPARC").is_ok() {
|
||||
archs.push_str("sparc;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_M68K").is_ok() {
|
||||
archs.push_str("m68k;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_PPC").is_ok() {
|
||||
archs.push_str("ppc;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_S390X").is_ok() {
|
||||
archs.push_str("s390x;");
|
||||
}
|
||||
if std::env::var("CARGO_FEATURE_ARCH_TRICORE").is_ok() {
|
||||
archs.push_str("tricore;");
|
||||
}
|
||||
|
||||
if !archs.is_empty() {
|
||||
archs.pop();
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -91,6 +128,7 @@ fn build_with_cmake() {
|
||||
let dst = config
|
||||
.define("UNICORN_BUILD_TESTS", "OFF")
|
||||
.define("UNICORN_INSTALL", "OFF")
|
||||
.define("UNICORN_ARCH", archs)
|
||||
.no_build_target(true)
|
||||
.build();
|
||||
println!(
|
||||
|
@ -1,10 +1,11 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::Unicorn;
|
||||
use crate::{Unicorn, UnicornInner};
|
||||
|
||||
use super::unicorn_const::{uc_error, Arch, HookType, MemRegion, MemType, Mode, Query};
|
||||
use core::ffi::c_void;
|
||||
use alloc::rc::Weak;
|
||||
use core::{cell::UnsafeCell, ffi::c_void};
|
||||
use libc::{c_char, c_int};
|
||||
|
||||
pub type uc_handle = *mut c_void;
|
||||
@ -89,7 +90,7 @@ extern "C" {
|
||||
|
||||
pub struct UcHook<'a, D: 'a, F: 'a> {
|
||||
pub callback: F,
|
||||
pub uc: Unicorn<'a, D>,
|
||||
pub uc: Weak<UnsafeCell<UnicornInner<'a, D>>>,
|
||||
}
|
||||
|
||||
pub trait IsUcHook<'a> {}
|
||||
@ -106,8 +107,11 @@ where
|
||||
F: FnMut(&mut crate::Unicorn<D>, u64, usize) -> u64,
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc, offset, size)
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc, offset, size)
|
||||
}
|
||||
|
||||
pub extern "C" fn mmio_write_callback_proxy<D, F>(
|
||||
@ -120,8 +124,11 @@ pub extern "C" fn mmio_write_callback_proxy<D, F>(
|
||||
F: FnMut(&mut crate::Unicorn<D>, u64, usize, u64),
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc, offset, size, value);
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc, offset, size, value);
|
||||
}
|
||||
|
||||
pub extern "C" fn code_hook_proxy<D, F>(
|
||||
@ -133,8 +140,11 @@ pub extern "C" fn code_hook_proxy<D, F>(
|
||||
F: FnMut(&mut crate::Unicorn<D>, u64, u32),
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc, address, size);
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc, address, size);
|
||||
}
|
||||
|
||||
pub extern "C" fn block_hook_proxy<D, F>(
|
||||
@ -146,8 +156,11 @@ pub extern "C" fn block_hook_proxy<D, F>(
|
||||
F: FnMut(&mut crate::Unicorn<D>, u64, u32),
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc, address, size);
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc, address, size);
|
||||
}
|
||||
|
||||
pub extern "C" fn mem_hook_proxy<D, F>(
|
||||
@ -162,8 +175,11 @@ where
|
||||
F: FnMut(&mut crate::Unicorn<D>, MemType, u64, usize, i64) -> bool,
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc, mem_type, address, size as usize, value)
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc, mem_type, address, size as usize, value)
|
||||
}
|
||||
|
||||
pub extern "C" fn intr_hook_proxy<D, F>(uc: uc_handle, value: u32, user_data: *mut UcHook<D, F>)
|
||||
@ -171,8 +187,11 @@ where
|
||||
F: FnMut(&mut crate::Unicorn<D>, u32),
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc, value);
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc, value);
|
||||
}
|
||||
|
||||
pub extern "C" fn insn_in_hook_proxy<D, F>(
|
||||
@ -180,12 +199,16 @@ pub extern "C" fn insn_in_hook_proxy<D, F>(
|
||||
port: u32,
|
||||
size: usize,
|
||||
user_data: *mut UcHook<D, F>,
|
||||
) where
|
||||
) -> u32
|
||||
where
|
||||
F: FnMut(&mut crate::Unicorn<D>, u32, usize) -> u32,
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc, port, size);
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc, port, size)
|
||||
}
|
||||
|
||||
pub extern "C" fn insn_invalid_hook_proxy<D, F>(uc: uc_handle, user_data: *mut UcHook<D, F>) -> bool
|
||||
@ -193,8 +216,11 @@ where
|
||||
F: FnMut(&mut crate::Unicorn<D>) -> bool,
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc)
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc)
|
||||
}
|
||||
|
||||
pub extern "C" fn insn_out_hook_proxy<D, F>(
|
||||
@ -207,8 +233,11 @@ pub extern "C" fn insn_out_hook_proxy<D, F>(
|
||||
F: FnMut(&mut crate::Unicorn<D>, u32, usize, u32),
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc, port, size, value);
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc, port, size, value);
|
||||
}
|
||||
|
||||
pub extern "C" fn insn_sys_hook_proxy<D, F>(uc: uc_handle, user_data: *mut UcHook<D, F>)
|
||||
@ -216,6 +245,9 @@ where
|
||||
F: FnMut(&mut crate::Unicorn<D>),
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
debug_assert_eq!(uc, user_data.uc.get_handle());
|
||||
(user_data.callback)(&mut user_data.uc);
|
||||
let mut user_data_uc = Unicorn {
|
||||
inner: user_data.uc.upgrade().unwrap(),
|
||||
};
|
||||
debug_assert_eq!(uc, user_data_uc.get_handle());
|
||||
(user_data.callback)(&mut user_data_uc);
|
||||
}
|
||||
|
@ -369,17 +369,13 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut read_data = read_callback.map(|c| {
|
||||
Box::new(ffi::UcHook {
|
||||
callback: c,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
})
|
||||
});
|
||||
let mut write_data = write_callback.map(|c| {
|
||||
Box::new(ffi::UcHook {
|
||||
callback: c,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
})
|
||||
});
|
||||
|
||||
@ -388,12 +384,18 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
self.get_handle(),
|
||||
address,
|
||||
size,
|
||||
ffi::mmio_read_callback_proxy::<D, R> as _,
|
||||
match read_data {
|
||||
Some(_) => ffi::mmio_read_callback_proxy::<D, R> as _,
|
||||
None => ptr::null_mut(),
|
||||
},
|
||||
match read_data {
|
||||
Some(ref mut d) => d.as_mut() as *mut _ as _,
|
||||
None => ptr::null_mut(),
|
||||
},
|
||||
ffi::mmio_write_callback_proxy::<D, W> as _,
|
||||
match write_data {
|
||||
Some(_) => ffi::mmio_write_callback_proxy::<D, W> as _,
|
||||
None => ptr::null_mut(),
|
||||
},
|
||||
match write_data {
|
||||
Some(ref mut d) => d.as_mut() as *mut _ as _,
|
||||
None => ptr::null_mut(),
|
||||
@ -586,7 +588,8 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
return Err(uc_error::ARCH);
|
||||
}
|
||||
|
||||
let err: uc_error = unsafe { ffi::uc_reg_read(self.get_handle(), curr_reg_id, value.as_mut_ptr() as _) };
|
||||
let err: uc_error =
|
||||
unsafe { ffi::uc_reg_read(self.get_handle(), curr_reg_id, value.as_mut_ptr() as _) };
|
||||
|
||||
if err == uc_error::OK {
|
||||
boxed = value.into_boxed_slice();
|
||||
@ -622,9 +625,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut hook_ptr = core::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::UcHook {
|
||||
callback,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
@ -654,9 +655,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut hook_ptr = core::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::UcHook {
|
||||
callback,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
@ -697,9 +696,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut hook_ptr = core::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::UcHook {
|
||||
callback,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
@ -730,9 +727,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut hook_ptr = core::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::UcHook {
|
||||
callback,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
@ -763,9 +758,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut hook_ptr = core::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::UcHook {
|
||||
callback,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
@ -796,9 +789,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut hook_ptr = core::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::UcHook {
|
||||
callback,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
@ -830,9 +821,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut hook_ptr = core::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::UcHook {
|
||||
callback,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
@ -870,9 +859,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let mut hook_ptr = core::ptr::null_mut();
|
||||
let mut user_data = Box::new(ffi::UcHook {
|
||||
callback,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
uc: Rc::downgrade(&self.inner),
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
|
@ -409,7 +409,7 @@ struct uc_context {
|
||||
};
|
||||
|
||||
// check if this address is mapped in (via uc_mem_map())
|
||||
MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address);
|
||||
MemoryRegion *find_memory_region(struct uc_struct *uc, uint64_t address);
|
||||
|
||||
// We have to support 32bit system so we can't hold uint64_t on void*
|
||||
static inline void uc_add_exit(uc_engine *uc, uint64_t addr)
|
||||
|
@ -72,9 +72,9 @@ typedef size_t uc_hook;
|
||||
// Unicorn API version
|
||||
#define UC_API_MAJOR 2
|
||||
#define UC_API_MINOR 0
|
||||
#define UC_API_PATCH 1
|
||||
#define UC_API_PATCH 2
|
||||
// Release candidate version, 255 means the official release.
|
||||
#define UC_API_EXTRA 255
|
||||
#define UC_API_EXTRA 1
|
||||
|
||||
// Unicorn package version
|
||||
#define UC_VERSION_MAJOR UC_API_MAJOR
|
||||
|
@ -7,3 +7,10 @@
|
||||
#define CONFIG_CMPXCHG128 1
|
||||
// #define CONFIG_ATOMIC64 1
|
||||
#define CONFIG_PLUGIN 1
|
||||
|
||||
// QEMU by default allocates (and commits) 1GB memory on Windows, and multiple Unicorn instances will result in OOM error easily.
|
||||
// Unfortunately, Windows doesn't have a similar demand paging feature like mmap(), therefore a workaround is to use tcg regions mechanism.
|
||||
// Note most Unicorn hacks (and even QEMU!) relies on the assumption that the translation memory won't run out and thus it might result
|
||||
// in some unexpected errors. If that is case, define WIN32_QEMU_ALLOC_BUFFER to align with QEMU and Unicorn <= 2.0.1 behavior.
|
||||
//
|
||||
// #define WIN32_QEMU_ALLOC_BUFFER
|
@ -1436,7 +1436,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
bool handled;
|
||||
HOOK_FOREACH_VAR_DECLARE;
|
||||
struct uc_struct *uc = env->uc;
|
||||
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||
MemoryRegion *mr = find_memory_region(uc, addr);
|
||||
|
||||
// memory might be still unmapped while reading or fetching
|
||||
if (mr == NULL) {
|
||||
@ -1480,7 +1480,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
|
||||
if (handled) {
|
||||
uc->invalid_error = UC_ERR_OK;
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr = find_memory_region(uc, addr);
|
||||
if (mr == NULL) {
|
||||
uc->invalid_error = UC_ERR_MAP;
|
||||
cpu_exit(uc->cpu);
|
||||
@ -2010,7 +2010,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
}
|
||||
|
||||
// Load the latest memory mapping.
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr = find_memory_region(uc, addr);
|
||||
|
||||
// Unicorn: callback on invalid memory
|
||||
if (mr == NULL) {
|
||||
@ -2037,7 +2037,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
return;
|
||||
} else {
|
||||
uc->invalid_error = UC_ERR_OK;
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr = find_memory_region(uc, addr);
|
||||
if (mr == NULL) {
|
||||
uc->invalid_error = UC_ERR_MAP;
|
||||
cpu_exit(uc->cpu);
|
||||
|
@ -869,6 +869,7 @@ static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
|
||||
return buf;
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
#ifdef WIN32_QEMU_ALLOC_BUFFER
|
||||
static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
|
||||
{
|
||||
TCGContext *tcg_ctx = uc->tcg_ctx;
|
||||
@ -876,6 +877,23 @@ static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
|
||||
return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
#else
|
||||
static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
|
||||
{
|
||||
TCGContext *tcg_ctx = uc->tcg_ctx;
|
||||
size_t size = tcg_ctx->code_gen_buffer_size;
|
||||
|
||||
void* ptr = VirtualAlloc(NULL, size, MEM_RESERVE,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
|
||||
// for prolog init
|
||||
VirtualAlloc(ptr,
|
||||
uc->qemu_real_host_page_size * UC_TCG_REGION_PAGES_COUNT,
|
||||
MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
void free_code_gen_buffer(struct uc_struct *uc)
|
||||
{
|
||||
TCGContext *tcg_ctx = uc->tcg_ctx;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#ifndef QEMU_CPU_H
|
||||
#define QEMU_CPU_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "exec/hwaddr.h"
|
||||
#include "exec/memattrs.h"
|
||||
#include "qemu/bitmap.h"
|
||||
|
@ -35,6 +35,11 @@
|
||||
#include "tcg-apple-jit.h"
|
||||
#include "qemu/int128.h"
|
||||
|
||||
// Unicorn: Default region size for win32
|
||||
#if defined(_WIN32) && !defined(WIN32_QEMU_ALLOC_BUFFER)
|
||||
#define UC_TCG_REGION_PAGES_COUNT (128) // Note less pages may cause unexpected and subtle errors.
|
||||
#endif
|
||||
|
||||
/* XXX: make safe guess about sizes */
|
||||
#define MAX_OP_PER_INSTR 266
|
||||
|
||||
|
@ -4816,7 +4816,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
|
||||
}
|
||||
|
||||
// Sync PC in advance
|
||||
gen_jmp_im(s, pc_start);
|
||||
gen_jmp_im(s, pc_start - s->cs_base);
|
||||
|
||||
// save the last operand
|
||||
prev_op = tcg_last_op(tcg_ctx);
|
||||
@ -9314,7 +9314,7 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
|
||||
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
||||
TCGContext *tcg_ctx = dc->uc->tcg_ctx;
|
||||
|
||||
dc->prev_pc = dc->base.pc_next;
|
||||
dc->prev_pc = dc->base.pc_next - dc->cs_base;
|
||||
tcg_gen_insn_start(tcg_ctx, dc->base.pc_next, dc->cc_op);
|
||||
}
|
||||
|
||||
|
@ -69,17 +69,6 @@ void x86_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
CPUArchState *env = uc->cpu->env_ptr;
|
||||
|
||||
env->features[FEAT_1_EDX] = CPUID_CX8 | CPUID_CMOV | CPUID_SSE2 |
|
||||
CPUID_FXSR | CPUID_SSE | CPUID_CLFLUSH;
|
||||
env->features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 |
|
||||
CPUID_EXT_SSE42 | CPUID_EXT_AES |
|
||||
CPUID_EXT_CX16;
|
||||
env->features[FEAT_8000_0001_EDX] = CPUID_EXT2_3DNOW | CPUID_EXT2_RDTSCP;
|
||||
env->features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM |
|
||||
CPUID_EXT3_SKINIT | CPUID_EXT3_CR8LEG;
|
||||
env->features[FEAT_7_0_EBX] = CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 |
|
||||
CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP;
|
||||
|
||||
memset(env->regs, 0, sizeof(env->regs));
|
||||
memset(env->segs, 0, sizeof(env->segs));
|
||||
memset(env->cr, 0, sizeof(env->cr));
|
||||
|
@ -24,6 +24,10 @@
|
||||
|
||||
#include "../tcg-pool.inc.c"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
@ -3768,11 +3772,6 @@ static void tcg_target_init(TCGContext *s)
|
||||
have_movbe = (c & bit_MOVBE) != 0;
|
||||
have_popcnt = (c & bit_POPCNT) != 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// FIXME: detect AVX1 & AVX2: https://gist.github.com/hi2p-perim/7855506
|
||||
have_avx1 = true;
|
||||
have_avx2 = true;
|
||||
#else
|
||||
/* There are a number of things we must check before we can be
|
||||
sure of not hitting invalid opcode. */
|
||||
if (c & bit_OSXSAVE) {
|
||||
@ -3780,13 +3779,18 @@ static void tcg_target_init(TCGContext *s)
|
||||
/* The xgetbv instruction is not available to older versions of
|
||||
* the assembler, so we encode the instruction manually.
|
||||
*/
|
||||
#ifndef _MSC_VER
|
||||
asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcrl), "=d" (xcrh) : "c" (0));
|
||||
#else
|
||||
unsigned long long bv = _xgetbv(0);
|
||||
xcrl = bv & 0xFFFFFFFF;
|
||||
xcrh = (bv >> 32) & 0xFFFFFFFF;
|
||||
#endif
|
||||
if ((xcrl & 6) == 6) {
|
||||
have_avx1 = (c & bit_AVX) != 0;
|
||||
have_avx2 = (b7 & bit_AVX2) != 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -23,6 +23,8 @@
|
||||
*/
|
||||
|
||||
/* define it to use liveness analysis (better code) */
|
||||
#include "tcg/tcg.h"
|
||||
#include <stdio.h>
|
||||
#define USE_TCG_OPTIMIZATIONS
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
@ -406,6 +408,13 @@ static void tcg_region_assign(TCGContext *s, size_t curr_region)
|
||||
s->code_gen_buffer = start;
|
||||
s->code_gen_ptr = start;
|
||||
s->code_gen_buffer_size = (char *)end - (char *)start;
|
||||
#if defined(WIN32) && !defined(WIN32_QEMU_ALLOC_BUFFER)
|
||||
VirtualAlloc(
|
||||
s->code_gen_buffer,
|
||||
ROUND_UP(s->code_gen_buffer_size, s->uc->qemu_real_host_page_size),
|
||||
MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
#endif
|
||||
memset(s->code_gen_buffer, 0x00, s->code_gen_buffer_size);
|
||||
s->code_gen_highwater = (char *)end - TCG_HIGHWATER;
|
||||
}
|
||||
@ -500,7 +509,11 @@ void tcg_region_init(TCGContext *tcg_ctx)
|
||||
size_t n_regions;
|
||||
size_t i;
|
||||
|
||||
#if defined(WIN32) && !defined(WIN32_QEMU_ALLOC_BUFFER)
|
||||
n_regions = size / (tcg_ctx->uc->qemu_real_host_page_size * UC_TCG_REGION_PAGES_COUNT);
|
||||
#else
|
||||
n_regions = 1;
|
||||
#endif
|
||||
|
||||
/* The first region will be 'aligned - buf' bytes larger than the others */
|
||||
aligned = (void *)QEMU_ALIGN_PTR_UP(buf, page_size);
|
||||
@ -537,6 +550,11 @@ void tcg_region_init(TCGContext *tcg_ctx)
|
||||
}
|
||||
|
||||
tcg_ctx->tree = g_tree_new(tb_tc_cmp);
|
||||
|
||||
#if defined(WIN32) && !defined(WIN32_QEMU_ALLOC_BUFFER)
|
||||
// Allocate a region immediately, or the highwater is not set correctly.
|
||||
tcg_region_alloc(tcg_ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1229,6 +1229,36 @@ static void test_x86_lazy_mapping(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static void test_x86_16_incorrect_ip_cb(uc_engine *uc, uint64_t address, uint32_t size, void* data)
|
||||
{
|
||||
uint16_t cs, ip;
|
||||
|
||||
OK(uc_reg_read(uc, UC_X86_REG_CS, &cs));
|
||||
OK(uc_reg_read(uc, UC_X86_REG_IP, &ip));
|
||||
|
||||
TEST_CHECK(cs == 0x20);
|
||||
TEST_CHECK(address == ((cs << 4) + ip));
|
||||
}
|
||||
|
||||
static void test_x86_16_incorrect_ip(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_hook hk1, hk2;
|
||||
uint16_t cs = 0x20;
|
||||
char code[] = "\x41"; // INC cx;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_16, code, sizeof(code) - 1);
|
||||
|
||||
OK(uc_hook_add(uc, &hk1, UC_HOOK_BLOCK, test_x86_16_incorrect_ip_cb, NULL, 1, 0));
|
||||
OK(uc_hook_add(uc, &hk2, UC_HOOK_CODE, test_x86_16_incorrect_ip_cb, NULL, 1, 0));
|
||||
|
||||
OK(uc_reg_write(uc, UC_X86_REG_CS, &cs));
|
||||
|
||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {
|
||||
{"test_x86_in", test_x86_in},
|
||||
{"test_x86_out", test_x86_out},
|
||||
@ -1271,4 +1301,5 @@ TEST_LIST = {
|
||||
{"test_x86_unaligned_access", test_x86_unaligned_access},
|
||||
#endif
|
||||
{"test_x86_lazy_mapping", test_x86_lazy_mapping},
|
||||
{"test_x86_16_incorrect_ip", test_x86_16_incorrect_ip},
|
||||
{NULL, NULL}};
|
||||
|
49
uc.c
49
uc.c
@ -552,7 +552,7 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size)
|
||||
size_t count = 0, len;
|
||||
|
||||
while (count < size) {
|
||||
MemoryRegion *mr = memory_mapping(uc, address);
|
||||
MemoryRegion *mr = find_memory_region(uc, address);
|
||||
if (mr) {
|
||||
len = (size_t)MIN(size - count, mr->end - address);
|
||||
count += len;
|
||||
@ -587,7 +587,7 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size)
|
||||
|
||||
// memory area can overlap adjacent memory blocks
|
||||
while (count < size) {
|
||||
MemoryRegion *mr = memory_mapping(uc, address);
|
||||
MemoryRegion *mr = find_memory_region(uc, address);
|
||||
if (mr) {
|
||||
len = (size_t)MIN(size - count, mr->end - address);
|
||||
if (uc->read_mem(&uc->address_space_memory, address, bytes, len) ==
|
||||
@ -632,7 +632,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes,
|
||||
|
||||
// memory area can overlap adjacent memory blocks
|
||||
while (count < size) {
|
||||
MemoryRegion *mr = memory_mapping(uc, address);
|
||||
MemoryRegion *mr = find_memory_region(uc, address);
|
||||
if (mr) {
|
||||
uint32_t operms = mr->perms;
|
||||
if (!(operms & UC_PROT_WRITE)) { // write protected
|
||||
@ -976,8 +976,7 @@ static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size)
|
||||
}
|
||||
|
||||
// common setup/error checking shared between uc_mem_map and uc_mem_map_ptr
|
||||
static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size,
|
||||
uint32_t perms, MemoryRegion *block)
|
||||
static uc_err mem_map(uc_engine *uc, MemoryRegion *block)
|
||||
{
|
||||
MemoryRegion **regions;
|
||||
int pos;
|
||||
@ -1060,8 +1059,7 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms)
|
||||
return res;
|
||||
}
|
||||
|
||||
return mem_map(uc, address, size, perms,
|
||||
uc->memory_map(uc, address, size, perms));
|
||||
return mem_map(uc, uc->memory_map(uc, address, size, perms));
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
@ -1085,8 +1083,7 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size,
|
||||
return res;
|
||||
}
|
||||
|
||||
return mem_map(uc, address, size, UC_PROT_ALL,
|
||||
uc->memory_map_ptr(uc, address, size, perms, ptr));
|
||||
return mem_map(uc, uc->memory_map_ptr(uc, address, size, perms, ptr));
|
||||
}
|
||||
|
||||
UNICORN_EXPORT
|
||||
@ -1108,9 +1105,8 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size,
|
||||
|
||||
// The callbacks do not need to be checked for NULL here, as their presence
|
||||
// (or lack thereof) will determine the permissions used.
|
||||
return mem_map(uc, address, size, UC_PROT_NONE,
|
||||
uc->memory_map_io(uc, address, size, read_cb, write_cb,
|
||||
user_data_read, user_data_write));
|
||||
return mem_map(uc, uc->memory_map_io(uc, address, size, read_cb, write_cb,
|
||||
user_data_read, user_data_write));
|
||||
}
|
||||
|
||||
// Create a backup copy of the indicated MemoryRegion.
|
||||
@ -1254,14 +1250,7 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr,
|
||||
|
||||
// Find the correct and large enough (which contains our target mr)
|
||||
// to create the content backup.
|
||||
QLIST_FOREACH(block, &uc->ram_list.blocks, next)
|
||||
{
|
||||
// block->offset is the offset within ram_addr_t, not GPA
|
||||
if (block->mr->addr <= mr->addr &&
|
||||
block->used_length + block->mr->addr >= mr->end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
block = mr->ram_block;
|
||||
|
||||
if (block == NULL) {
|
||||
return false;
|
||||
@ -1423,14 +1412,14 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||
addr = address;
|
||||
count = 0;
|
||||
while (count < size) {
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr = find_memory_region(uc, addr);
|
||||
len = (size_t)MIN(size - count, mr->end - addr);
|
||||
if (mr->ram) {
|
||||
if (!split_region(uc, mr, addr, len, false)) {
|
||||
return UC_ERR_NOMEM;
|
||||
}
|
||||
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr = find_memory_region(uc, addr);
|
||||
// will this remove EXEC permission?
|
||||
if (((mr->perms & UC_PROT_EXEC) != 0) &&
|
||||
((perms & UC_PROT_EXEC) == 0)) {
|
||||
@ -1444,7 +1433,7 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||
return UC_ERR_NOMEM;
|
||||
}
|
||||
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr = find_memory_region(uc, addr);
|
||||
mr->perms = perms;
|
||||
}
|
||||
|
||||
@ -1503,7 +1492,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||
addr = address;
|
||||
count = 0;
|
||||
while (count < size) {
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr = find_memory_region(uc, addr);
|
||||
len = (size_t)MIN(size - count, mr->end - addr);
|
||||
if (!mr->ram) {
|
||||
if (!split_mmio_region(uc, mr, addr, len, true)) {
|
||||
@ -1517,7 +1506,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||
|
||||
// if we can retrieve the mapping, then no splitting took place
|
||||
// so unmap here
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr = find_memory_region(uc, addr);
|
||||
if (mr != NULL) {
|
||||
uc->memory_unmap(uc, mr);
|
||||
}
|
||||
@ -1529,7 +1518,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||
}
|
||||
|
||||
// find the memory region of this address
|
||||
MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address)
|
||||
MemoryRegion *find_memory_region(struct uc_struct *uc, uint64_t address)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@ -1544,14 +1533,16 @@ MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address)
|
||||
// try with the cache index first
|
||||
i = uc->mapped_block_cache_index;
|
||||
|
||||
if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr &&
|
||||
if (i < uc->mapped_block_count &&
|
||||
address >= uc->mapped_blocks[i]->addr &&
|
||||
address < uc->mapped_blocks[i]->end) {
|
||||
return uc->mapped_blocks[i];
|
||||
}
|
||||
|
||||
i = bsearch_mapped_blocks(uc, address);
|
||||
|
||||
if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr &&
|
||||
if (i < uc->mapped_block_count &&
|
||||
address >= uc->mapped_blocks[i]->addr &&
|
||||
address <= uc->mapped_blocks[i]->end - 1)
|
||||
return uc->mapped_blocks[i];
|
||||
|
||||
@ -2431,4 +2422,4 @@ void trace_end(uc_tracer *tracer, trace_loc loc, const char *fmt, ...)
|
||||
fprintf(stderr, "%.6fus\n",
|
||||
(double)(end - tracer->starts[loc]) / (double)(1000));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user