import Unicorn2
This commit is contained in:
parent
772558119a
commit
aaaea14214
|
@ -12,8 +12,6 @@
|
||||||
*.jar
|
*.jar
|
||||||
*~
|
*~
|
||||||
|
|
||||||
qemu/config-all-devices.mak
|
|
||||||
|
|
||||||
qemu/aarch64-softmmu/
|
qemu/aarch64-softmmu/
|
||||||
qemu/aarch64eb-softmmu/
|
qemu/aarch64eb-softmmu/
|
||||||
qemu/arm-softmmu/
|
qemu/arm-softmmu/
|
||||||
|
@ -29,6 +27,8 @@ qemu/i386-softmmu/
|
||||||
qemu/x86_64-softmmu/
|
qemu/x86_64-softmmu/
|
||||||
qemu/ppc-softmmu/
|
qemu/ppc-softmmu/
|
||||||
qemu/ppc64-softmmu/
|
qemu/ppc64-softmmu/
|
||||||
|
qemu/riscv32-softmmu/
|
||||||
|
qemu/riscv64-softmmu/
|
||||||
|
|
||||||
tags
|
tags
|
||||||
qemu/config-host.ld
|
qemu/config-host.ld
|
||||||
|
@ -67,8 +67,6 @@ bindings/python/unicorn.egg-info/
|
||||||
bindings/python/unicorn/lib/
|
bindings/python/unicorn/lib/
|
||||||
bindings/python/unicorn/include/
|
bindings/python/unicorn/include/
|
||||||
bindings/python/MANIFEST
|
bindings/python/MANIFEST
|
||||||
bindings/rust/target/
|
|
||||||
bindings/rust/Cargo.lock
|
|
||||||
config.log
|
config.log
|
||||||
|
|
||||||
|
|
||||||
|
|
147
.travis.yml
147
.travis.yml
|
@ -4,19 +4,10 @@ env:
|
||||||
script:
|
script:
|
||||||
- |
|
- |
|
||||||
if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
|
if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
|
||||||
if [[ "$TRAVIS_COMPILER" == "clang" ]]; then
|
choco install cygwin cyg-get && \
|
||||||
choco install cygwin cyg-get && \
|
cyg-get.bat default autoconf automake make gcc-core clang pkg-config libpcre-devel cmake python27-setuptools ruby wget && \
|
||||||
cyg-get.bat default autoconf automake make gcc-core clang pkg-config libpcre-devel cmake python27-setuptools ruby wget && \
|
export SHELLOPTS && set -o igncr \
|
||||||
export SHELLOPTS && set -o igncr && \
|
cmd.exe //C "C:\\tools\\cygwin\\bin\\bash.exe -lc 'cd /cygdrive/$TRAVIS_BUILD_DIR; make header; make; ./install-cmocka-linux.sh; export PATH="$PATH":/cygdrive/$TRAVIS_BUILD_DIR:/cygdrive/$TRAVIS_BUILD_DIR/cmocka/src; make test'"
|
||||||
cmd.exe //C "C:\\tools\\cygwin\\bin\\bash.exe -lc 'cd /cygdrive/$TRAVIS_BUILD_DIR; make header; make'"
|
|
||||||
else
|
|
||||||
choco install cygwin cyg-get && \
|
|
||||||
cyg-get.bat default autoconf automake make gcc-core clang pkg-config libpcre-devel cmake python27-setuptools ruby wget && \
|
|
||||||
export SHELLOPTS && set -o igncr && \
|
|
||||||
cmd.exe //C "C:\\tools\\cygwin\\bin\\bash.exe -lc 'cd /cygdrive/$TRAVIS_BUILD_DIR; make header; make; ./install-cmocka-linux.sh; export PATH="$PATH":/cygdrive/$TRAVIS_BUILD_DIR:/cygdrive/$TRAVIS_BUILD_DIR/cmocka/src; make test'"
|
|
||||||
fi
|
|
||||||
elif [[ "$TRAVIS_CPU_ARCH" == "arm64" ]]; then
|
|
||||||
make header && make && make -C tests/unit test && make -C tests/regress test
|
|
||||||
else
|
else
|
||||||
make header && make && make -C bindings/go && make -C bindings/go test && make test
|
make header && make && make -C bindings/go && make -C bindings/go test && make test
|
||||||
fi
|
fi
|
||||||
|
@ -25,52 +16,28 @@ compiler:
|
||||||
- gcc
|
- gcc
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
|
- osx
|
||||||
- windows
|
- windows
|
||||||
arch:
|
|
||||||
- amd64
|
|
||||||
- arm64
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
exclude:
|
|
||||||
- os: windows
|
|
||||||
arch: arm64
|
|
||||||
include:
|
include:
|
||||||
|
- name: "Linux arm64 clang C"
|
||||||
- name: "Compiler: clang C"
|
arch: arm64
|
||||||
os: osx
|
os: linux
|
||||||
osx_image: xcode10.1
|
|
||||||
python: 3.7
|
|
||||||
compiler: clang
|
compiler: clang
|
||||||
before_cache:
|
language: c
|
||||||
- brew cleanup
|
env:
|
||||||
- find /usr/local/Homebrew \! -regex ".+\.git.+" -delete;
|
- PATH=$PATH:/usr/local/opt/binutils/bin
|
||||||
cache:
|
script: make header && make && make -C tests/unit test && make -C tests/regress test
|
||||||
directories:
|
|
||||||
- $HOME/Library/Caches/Homebrew
|
|
||||||
- /usr/local/Homebrew
|
|
||||||
before_install:
|
|
||||||
- cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core && git stash && git clean -d -f
|
|
||||||
script:
|
|
||||||
- cd $TRAVIS_BUILD_DIR
|
|
||||||
- make header && make && make -C bindings/go && make -C bindings/go test && make test
|
|
||||||
|
|
||||||
- name: "Compiler: gcc C"
|
- name: "Linux arm64 gcc C"
|
||||||
os: osx
|
arch: arm64
|
||||||
osx_image: xcode10.1
|
os: linux
|
||||||
python: 3.7
|
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
before_cache:
|
language: c
|
||||||
- brew cleanup
|
env:
|
||||||
- find /usr/local/Homebrew \! -regex ".+\.git.+" -delete;
|
- PATH=$PATH:/usr/local/opt/binutils/bin
|
||||||
cache:
|
script: make header && make && make -C tests/unit test && make -C tests/regress test
|
||||||
directories:
|
|
||||||
- $HOME/Library/Caches/Homebrew
|
|
||||||
- /usr/local/Homebrew
|
|
||||||
before_install:
|
|
||||||
- cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core && git stash && git clean -d -f
|
|
||||||
script:
|
|
||||||
- cd $TRAVIS_BUILD_DIR
|
|
||||||
- make header && make && make -C bindings/go && make -C bindings/go test && make test
|
|
||||||
|
|
||||||
- name: "Linux clang ASAN"
|
- name: "Linux clang ASAN"
|
||||||
os: linux
|
os: linux
|
||||||
|
@ -81,9 +48,7 @@ matrix:
|
||||||
- CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link"
|
- CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link"
|
||||||
- CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link"
|
- CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link"
|
||||||
- LDFLAGS="-fsanitize=address"
|
- LDFLAGS="-fsanitize=address"
|
||||||
script:
|
script: make header && make && make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||||
- make header && make
|
|
||||||
- make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
|
||||||
|
|
||||||
- name: "Linux clang MSAN"
|
- name: "Linux clang MSAN"
|
||||||
os: linux
|
os: linux
|
||||||
|
@ -94,9 +59,7 @@ matrix:
|
||||||
- CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize=fuzzer-no-link"
|
- CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize=fuzzer-no-link"
|
||||||
- CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize=fuzzer-no-link"
|
- CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize=fuzzer-no-link"
|
||||||
- LDFLAGS="-fsanitize=memory"
|
- LDFLAGS="-fsanitize=memory"
|
||||||
script:
|
script: make header && make && make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||||
- make header && make
|
|
||||||
- make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
|
||||||
|
|
||||||
- name: "Linux clang USAN"
|
- name: "Linux clang USAN"
|
||||||
os: linux
|
os: linux
|
||||||
|
@ -107,9 +70,7 @@ matrix:
|
||||||
- CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fsanitize=fuzzer-no-link"
|
- CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fsanitize=fuzzer-no-link"
|
||||||
- CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fsanitize=fuzzer-no-link"
|
- CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fsanitize=fuzzer-no-link"
|
||||||
- LDFLAGS="-fsanitize=undefined"
|
- LDFLAGS="-fsanitize=undefined"
|
||||||
script:
|
script: make header && make && make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||||
- make header && make
|
|
||||||
- make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
|
||||||
|
|
||||||
- name: "Linux 32bit"
|
- name: "Linux 32bit"
|
||||||
os: linux
|
os: linux
|
||||||
|
@ -164,42 +125,6 @@ matrix:
|
||||||
- cp libunicorn.* ../
|
- cp libunicorn.* ../
|
||||||
- make -C ../tests/unit test && make -C ../tests/regress test
|
- make -C ../tests/unit test && make -C ../tests/regress test
|
||||||
|
|
||||||
- name: "Linux Cmake Static 32bit"
|
|
||||||
os: linux
|
|
||||||
compiler: gcc
|
|
||||||
env:
|
|
||||||
- CFLAGS="-m32" LDFLAGS="-m32" LDFLAGS_STATIC="-m32" UNICORN_QEMU_FLAGS="--cpu=i386"
|
|
||||||
- PATH=$PATH:/usr/local/opt/binutils/bin
|
|
||||||
script:
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake -DCMAKE_BUILD_TYPE=Release -DUNICORN_ARCH=x86 -DUNICORN_BUILD_SHARED=OFF .. && make -j8
|
|
||||||
# temporarily disable test for static build
|
|
||||||
# - cp libunicorn.* ../
|
|
||||||
# - make -C ../tests/unit test && make -C ../tests/regress test
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- lib32ncurses5-dev
|
|
||||||
- lib32z1-dev
|
|
||||||
- libpthread-stubs0-dev
|
|
||||||
- lib32gcc-4.8-dev
|
|
||||||
- libc6-dev-i386
|
|
||||||
- gcc-multilib
|
|
||||||
- libcmocka-dev:i386
|
|
||||||
|
|
||||||
- name: "Linux Cmake Static 64bit"
|
|
||||||
os: linux
|
|
||||||
compiler: gcc
|
|
||||||
env:
|
|
||||||
- PATH=$PATH:/usr/local/opt/binutils/bin
|
|
||||||
script:
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake -DCMAKE_BUILD_TYPE=Release -DUNICORN_BUILD_SHARED=OFF .. && make -j8
|
|
||||||
# - cp libunicorn.* ../
|
|
||||||
# - make -C ../tests/unit test && make -C ../tests/regress test
|
|
||||||
|
|
||||||
- name: "MacOSX brew"
|
- name: "MacOSX brew"
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode10.1
|
osx_image: xcode10.1
|
||||||
|
@ -289,14 +214,12 @@ matrix:
|
||||||
- export LDFLAGS="-m32"
|
- export LDFLAGS="-m32"
|
||||||
- export LDFLAGS_STATIC="-m32"
|
- export LDFLAGS_STATIC="-m32"
|
||||||
- export UNICORN_QEMU_FLAGS="--cpu=i386"
|
- export UNICORN_QEMU_FLAGS="--cpu=i386"
|
||||||
# before_cache:
|
before_cache:
|
||||||
# - $msys2 pacman --sync --clean --noconfirm
|
- $msys2 pacman --sync --clean --noconfirm
|
||||||
# cache:
|
cache:
|
||||||
# timeout:
|
directories:
|
||||||
# 1000
|
- $HOME/AppData/Local/Temp/chocolatey
|
||||||
# directories:
|
- /C/tools/msys64
|
||||||
# - $HOME/AppData/Local/Temp/chocolatey
|
|
||||||
# - /C/tools/msys64
|
|
||||||
script:
|
script:
|
||||||
- $shell make header; $shell make; cp unicorn.dll /C/Windows/SysWOW64/; $shell make test
|
- $shell make header; $shell make; cp unicorn.dll /C/Windows/SysWOW64/; $shell make test
|
||||||
|
|
||||||
|
@ -333,14 +256,12 @@ matrix:
|
||||||
- export CC=x86_64-w64-mingw32-gcc
|
- export CC=x86_64-w64-mingw32-gcc
|
||||||
- export AR=gcc-ar
|
- export AR=gcc-ar
|
||||||
- export RANLIB=gcc-ranlib
|
- export RANLIB=gcc-ranlib
|
||||||
# before_cache:
|
before_cache:
|
||||||
# - $msys2 pacman --sync --clean --noconfirm
|
- $msys2 pacman --sync --clean --noconfirm
|
||||||
# cache:
|
cache:
|
||||||
# timeout:
|
directories:
|
||||||
# 1000
|
- $HOME/AppData/Local/Temp/chocolatey
|
||||||
# directories:
|
- /C/tools/msys64
|
||||||
# - $HOME/AppData/Local/Temp/chocolatey
|
|
||||||
# - /C/tools/msys64
|
|
||||||
script:
|
script:
|
||||||
- $shell make header; $shell make; cp unicorn.dll /C/Windows/System32/; $shell make test
|
- $shell make header; $shell make; cp unicorn.dll /C/Windows/System32/; $shell make test
|
||||||
addons:
|
addons:
|
||||||
|
|
1252
CMakeLists.txt
1252
CMakeLists.txt
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,10 @@ Key developers
|
||||||
==============
|
==============
|
||||||
Nguyen Anh Quynh <aquynh -at- gmail.com>
|
Nguyen Anh Quynh <aquynh -at- gmail.com>
|
||||||
Dang Hoang Vu <dang.hvu -at- gmail.com>
|
Dang Hoang Vu <dang.hvu -at- gmail.com>
|
||||||
|
Huitao Chen (chenhuitao)
|
||||||
Ziqiao Kong (lazymio)
|
Ziqiao Kong (lazymio)
|
||||||
|
KaiJernLau (xwings)
|
||||||
|
|
||||||
|
|
||||||
Beta testers (in no particular order)
|
Beta testers (in no particular order)
|
||||||
==============================
|
==============================
|
||||||
|
@ -72,5 +75,6 @@ Philippe Antoine (Catena cyber): fuzzing
|
||||||
Huitao Chen (chenhuitao) & KaiJern Lau (xwings): Cmake support
|
Huitao Chen (chenhuitao) & KaiJern Lau (xwings): Cmake support
|
||||||
Huitao Chen (chenhuitao) & KaiJern Lau (xwings): Python3 support for building
|
Huitao Chen (chenhuitao) & KaiJern Lau (xwings): Python3 support for building
|
||||||
Kevin Foo (chfl4gs): Travis-CI migration
|
Kevin Foo (chfl4gs): Travis-CI migration
|
||||||
|
Simon Gorchakov: PowerPC target
|
||||||
|
Stuart Dootson (studoot): MSVC compatibility with PowerPC target support
|
||||||
Ziqiao Kong (lazymio): uc_context_free() API and various bug fix & improvement.
|
Ziqiao Kong (lazymio): uc_context_free() API and various bug fix & improvement.
|
||||||
Sven Almgren (blindmatrix): bug fix
|
|
||||||
|
|
71
ChangeLog
71
ChangeLog
|
@ -1,76 +1,5 @@
|
||||||
This file details the changelog of Unicorn Engine.
|
This file details the changelog of Unicorn Engine.
|
||||||
|
|
||||||
-------------------------------
|
|
||||||
[Version 1.0.3]: May 26th, 2021
|
|
||||||
|
|
||||||
- Fix some building issues
|
|
||||||
- Fix build with LLVM on Powerpc64(le)
|
|
||||||
- cmake: enable UNICORN_HAS_ARMEB when ARM is on
|
|
||||||
- Better support MingW building
|
|
||||||
- Better support FreeBSD host
|
|
||||||
- Better support VS2008/VS2010
|
|
||||||
|
|
||||||
- Fix some issues in the core:
|
|
||||||
- Fix wrong sync after UC_ERR_[READ, WRITE, FETCH]_[UNMAPPED, PROT]
|
|
||||||
- Support querying architecture mode besides arm
|
|
||||||
- Fix pausing within Thumb2 ITE blocks
|
|
||||||
|
|
||||||
- Arm:
|
|
||||||
- Support Arm BE8 mode
|
|
||||||
|
|
||||||
- X86:
|
|
||||||
- Fix FPIP & FTST instructions
|
|
||||||
|
|
||||||
- Bindings:
|
|
||||||
- Java: remove deprecated javah and build with javac
|
|
||||||
- Python: handle exceptions raised in hook functions
|
|
||||||
- Rust binding
|
|
||||||
|
|
||||||
-----------------------------------
|
|
||||||
[Version 1.0.2]: October 21st, 2020
|
|
||||||
|
|
||||||
- Fix Java binding compilation
|
|
||||||
- Enable building for ARM little-endian only (ignore big-endian)
|
|
||||||
|
|
||||||
------------------------------------
|
|
||||||
[Version 1.0.2-rc6]: Sept 24th, 2020
|
|
||||||
|
|
||||||
- Add uc_context_free() API
|
|
||||||
- Fix context saving/retoring API (core & Python binding)
|
|
||||||
|
|
||||||
------------------------------------
|
|
||||||
[Version 1.0.2-rc5]: Sept 22nd, 2020
|
|
||||||
|
|
||||||
- Add cmake option to build Unicorn as a static library
|
|
||||||
- Fix error handling of mmap()
|
|
||||||
- uc_emu_start() can be reentrant
|
|
||||||
- Fix naming conflicts when built with systemd
|
|
||||||
- Fix setjmp/longjmp on native Windows
|
|
||||||
- Fix enabled hooks even after deleting them
|
|
||||||
- X86:
|
|
||||||
- Fix 64bit fstenv
|
|
||||||
- Fix IP value of 16bit mode
|
|
||||||
- ARM:
|
|
||||||
- Fix APSR handling
|
|
||||||
- Python: Remove UC_ERR_TIMEOUT
|
|
||||||
|
|
||||||
-----------------------------------
|
|
||||||
[Version 1.0.2-rc4]: May 29th, 2020
|
|
||||||
|
|
||||||
- No longer require Python to build
|
|
||||||
- Fix recursive UC_HOOK_MEM callbacks for cross pages access
|
|
||||||
- Remove UC_ERR_TIMEOUT, so timeout on uc_emu_start() is not considered error
|
|
||||||
- Added UC_QUERY_TIMEOUT to query exit reason
|
|
||||||
- Fix UAF when deleting hook while in hook callback
|
|
||||||
- Ensure that hooks are unaffected by a request to stop emulation.
|
|
||||||
- Fix block hooks being called twice after an early exit from execution.
|
|
||||||
- Fix binding install on python2 (MacOS)
|
|
||||||
- X86:
|
|
||||||
- Support read/write STn registers
|
|
||||||
- Support read/write X64 base regs
|
|
||||||
- ARM64:
|
|
||||||
- Support some new registers
|
|
||||||
|
|
||||||
----------------------------------
|
----------------------------------
|
||||||
[Version 1.0.1]: April 20th, 2017
|
[Version 1.0.1]: April 20th, 2017
|
||||||
|
|
||||||
|
|
424
Makefile
424
Makefile
|
@ -1,424 +0,0 @@
|
||||||
# Unicorn Emulator Engine
|
|
||||||
# By Dang Hoang Vu <dang.hvu -at- gmail.com>, 2015
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: all clean install uninstall dist header
|
|
||||||
|
|
||||||
include config.mk
|
|
||||||
include pkgconfig.mk # package version
|
|
||||||
|
|
||||||
LIBNAME = unicorn
|
|
||||||
UNAME_S := $(shell uname -s)
|
|
||||||
# SMP_MFLAGS is used for controlling the amount of parallelism used
|
|
||||||
# in external 'make' invocations. If the user doesn't override it, it
|
|
||||||
# does "-j4". That is, it uses 4 job threads. If you want to use more or less,
|
|
||||||
# pass in a different -jX, with X being the number of threads.
|
|
||||||
# For example, to completely disable parallel building, pass "-j1".
|
|
||||||
# If you want to use 16 job threads, use "-j16".
|
|
||||||
SMP_MFLAGS := -j4
|
|
||||||
|
|
||||||
UC_GET_OBJ = $(shell for i in \
|
|
||||||
$$(grep '$(1)' $(2) | \
|
|
||||||
grep '\.o' | cut -d '=' -f 2); do \
|
|
||||||
echo $$i | grep '\.o' > /dev/null 2>&1; \
|
|
||||||
if [ $$? = 0 ]; then \
|
|
||||||
echo '$(3)'$$i; \
|
|
||||||
fi; done; echo)
|
|
||||||
|
|
||||||
UC_TARGET_OBJ = $(filter-out qemu/../%,$(call UC_GET_OBJ,obj-,qemu/Makefile.objs, qemu/))
|
|
||||||
UC_TARGET_OBJ += $(call UC_GET_OBJ,obj-,qemu/hw/core/Makefile.objs, qemu/hw/core/)
|
|
||||||
UC_TARGET_OBJ += $(call UC_GET_OBJ,obj-,qemu/qapi/Makefile.objs, qemu/qapi/)
|
|
||||||
UC_TARGET_OBJ += $(call UC_GET_OBJ,obj-,qemu/qobject/Makefile.objs, qemu/qobject/)
|
|
||||||
UC_TARGET_OBJ += $(call UC_GET_OBJ,obj-,qemu/qom/Makefile.objs, qemu/qom/)
|
|
||||||
UC_TARGET_OBJ += $(call UC_GET_OBJ,obj-y,qemu/util/Makefile.objs, qemu/util/)
|
|
||||||
ifneq ($(filter MINGW%,$(UNAME_S)),)
|
|
||||||
UC_TARGET_OBJ += $(call UC_GET_OBJ,obj-$$(CONFIG_WIN32),qemu/util/Makefile.objs, qemu/util/)
|
|
||||||
else
|
|
||||||
UC_TARGET_OBJ += $(call UC_GET_OBJ,obj-$$(CONFIG_POSIX),qemu/util/Makefile.objs, qemu/util/)
|
|
||||||
endif
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_X86 = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/x86_64-softmmu/)
|
|
||||||
UC_TARGET_OBJ_X86 += $(call UC_GET_OBJ,obj-,qemu/hw/i386/Makefile.objs, qemu/x86_64-softmmu/hw/i386/)
|
|
||||||
UC_TARGET_OBJ_X86 += $(call UC_GET_OBJ,obj-,qemu/hw/intc/Makefile.objs, qemu/x86_64-softmmu/hw/intc/)
|
|
||||||
UC_TARGET_OBJ_X86 += $(call UC_GET_OBJ,obj-,qemu/target-i386/Makefile.objs, qemu/x86_64-softmmu/target-i386/)
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_ARM = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/arm-softmmu/)
|
|
||||||
UC_TARGET_OBJ_ARM += $(call UC_GET_OBJ,obj-,qemu/hw/arm/Makefile.objs, qemu/arm-softmmu/hw/arm/)
|
|
||||||
UC_TARGET_OBJ_ARM += $(call UC_GET_OBJ,obj-y,qemu/target-arm/Makefile.objs, qemu/arm-softmmu/target-arm/)
|
|
||||||
UC_TARGET_OBJ_ARM += $(call UC_GET_OBJ,obj-$$(CONFIG_SOFTMMU),qemu/target-arm/Makefile.objs, qemu/arm-softmmu/target-arm/)
|
|
||||||
UC_TARGET_OBJ_ARM += $(call UC_GET_OBJ,obj-$$(TARGET_ARM),qemu/target-arm/Makefile.objs, qemu/arm-softmmu/target-arm/)
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_ARMEB = $(subst /arm-softmmu/,/armeb-softmmu/,$(UC_TARGET_OBJ_ARM))
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_M68K = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/m68k-softmmu/)
|
|
||||||
UC_TARGET_OBJ_M68K += $(call UC_GET_OBJ,obj-,qemu/hw/m68k/Makefile.objs, qemu/m68k-softmmu/hw/m68k/)
|
|
||||||
UC_TARGET_OBJ_M68K += $(call UC_GET_OBJ,obj-,qemu/target-m68k/Makefile.objs, qemu/m68k-softmmu/target-m68k/)
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_AARCH64 = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/aarch64-softmmu/)
|
|
||||||
UC_TARGET_OBJ_AARCH64 += $(call UC_GET_OBJ,obj-,qemu/hw/arm/Makefile.objs, qemu/aarch64-softmmu/hw/arm/)
|
|
||||||
UC_TARGET_OBJ_AARCH64 += $(call UC_GET_OBJ,obj-y,qemu/target-arm/Makefile.objs, qemu/aarch64-softmmu/target-arm/)
|
|
||||||
UC_TARGET_OBJ_AARCH64 += $(call UC_GET_OBJ,obj-$$(CONFIG_SOFTMMU),qemu/target-arm/Makefile.objs, qemu/aarch64-softmmu/target-arm/)
|
|
||||||
UC_TARGET_OBJ_AARCH64 += $(call UC_GET_OBJ,obj-$$(TARGET_AARCH64),qemu/target-arm/Makefile.objs, qemu/aarch64-softmmu/target-arm/)
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_AARCH64EB = $(subst /aarch64-softmmu/,/aarch64eb-softmmu/,$(UC_TARGET_OBJ_AARCH64))
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_MIPS = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/mips-softmmu/)
|
|
||||||
UC_TARGET_OBJ_MIPS += $(call UC_GET_OBJ,obj-,qemu/hw/mips/Makefile.objs, qemu/mips-softmmu/hw/mips/)
|
|
||||||
UC_TARGET_OBJ_MIPS += $(call UC_GET_OBJ,obj-,qemu/target-mips/Makefile.objs, qemu/mips-softmmu/target-mips/)
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_MIPSEL = $(subst /mips-softmmu/,/mipsel-softmmu/,$(UC_TARGET_OBJ_MIPS))
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_MIPS64 = $(subst /mips-softmmu/,/mips64-softmmu/,$(UC_TARGET_OBJ_MIPS))
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_MIPS64EL = $(subst /mips-softmmu/,/mips64el-softmmu/,$(UC_TARGET_OBJ_MIPS))
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_SPARC = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/sparc-softmmu/)
|
|
||||||
UC_TARGET_OBJ_SPARC += $(call UC_GET_OBJ,obj-,qemu/hw/sparc/Makefile.objs, qemu/sparc-softmmu/hw/sparc/)
|
|
||||||
UC_TARGET_OBJ_SPARC += $(call UC_GET_OBJ,obj-y,qemu/target-sparc/Makefile.objs, qemu/sparc-softmmu/target-sparc/)
|
|
||||||
UC_TARGET_OBJ_SPARC += $(call UC_GET_OBJ,obj-$$(TARGET_SPARC),qemu/target-sparc/Makefile.objs, qemu/sparc-softmmu/target-sparc/)
|
|
||||||
|
|
||||||
UC_TARGET_OBJ_SPARC64 = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/sparc64-softmmu/)
|
|
||||||
UC_TARGET_OBJ_SPARC64 += $(call UC_GET_OBJ,obj-,qemu/hw/sparc64/Makefile.objs, qemu/sparc64-softmmu/hw/sparc64/)
|
|
||||||
UC_TARGET_OBJ_SPARC64 += $(call UC_GET_OBJ,obj-y,qemu/target-sparc/Makefile.objs, qemu/sparc64-softmmu/target-sparc/)
|
|
||||||
UC_TARGET_OBJ_SPARC64 += $(call UC_GET_OBJ,obj-$$(TARGET_SPARC64),qemu/target-sparc/Makefile.objs, qemu/sparc64-softmmu/target-sparc/)
|
|
||||||
|
|
||||||
ifneq (,$(findstring x86,$(UNICORN_ARCHS)))
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_X86)
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_X86
|
|
||||||
UNICORN_TARGETS += x86_64-softmmu,
|
|
||||||
endif
|
|
||||||
ifneq (,$(findstring arm,$(UNICORN_ARCHS)))
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_ARM)
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_ARMEB)
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_ARM
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_ARMEB
|
|
||||||
UNICORN_TARGETS += arm-softmmu,
|
|
||||||
UNICORN_TARGETS += armeb-softmmu,
|
|
||||||
endif
|
|
||||||
ifneq (,$(findstring m68k,$(UNICORN_ARCHS)))
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_M68K)
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_M68K
|
|
||||||
UNICORN_TARGETS += m68k-softmmu,
|
|
||||||
endif
|
|
||||||
ifneq (,$(findstring aarch64,$(UNICORN_ARCHS)))
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_AARCH64)
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_AARCH64EB)
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_ARM64
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_ARM64EB
|
|
||||||
UNICORN_TARGETS += aarch64-softmmu,
|
|
||||||
UNICORN_TARGETS += aarch64eb-softmmu,
|
|
||||||
endif
|
|
||||||
ifneq (,$(findstring mips,$(UNICORN_ARCHS)))
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_MIPS)
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_MIPSEL)
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_MIPS64)
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_MIPS64EL)
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_MIPS
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_MIPSEL
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_MIPS64
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_MIPS64EL
|
|
||||||
UNICORN_TARGETS += mips-softmmu,
|
|
||||||
UNICORN_TARGETS += mipsel-softmmu,
|
|
||||||
UNICORN_TARGETS += mips64-softmmu,
|
|
||||||
UNICORN_TARGETS += mips64el-softmmu,
|
|
||||||
endif
|
|
||||||
ifneq (,$(findstring sparc,$(UNICORN_ARCHS)))
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_SPARC)
|
|
||||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_SPARC64)
|
|
||||||
UNICORN_CFLAGS += -DUNICORN_HAS_SPARC
|
|
||||||
UNICORN_TARGETS += sparc-softmmu,sparc64-softmmu,
|
|
||||||
endif
|
|
||||||
|
|
||||||
UC_OBJ_ALL = $(UC_TARGET_OBJ) list.o uc.o
|
|
||||||
|
|
||||||
UNICORN_CFLAGS += -fPIC
|
|
||||||
|
|
||||||
# Verbose output?
|
|
||||||
V ?= 0
|
|
||||||
|
|
||||||
# on MacOS, by default do not compile in Universal format
|
|
||||||
MACOS_UNIVERSAL ?= no
|
|
||||||
|
|
||||||
ifeq ($(UNICORN_DEBUG),yes)
|
|
||||||
CFLAGS += -g
|
|
||||||
else
|
|
||||||
CFLAGS += -O3
|
|
||||||
UNICORN_QEMU_FLAGS += --disable-debug-info
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(UNICORN_ASAN),yes)
|
|
||||||
CC = clang -fsanitize=address -fno-omit-frame-pointer
|
|
||||||
CXX = clang++ -fsanitize=address -fno-omit-frame-pointer
|
|
||||||
AR = llvm-ar
|
|
||||||
LDFLAGS := -fsanitize=address ${LDFLAGS}
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(CROSS),)
|
|
||||||
CC ?= cc
|
|
||||||
AR ?= ar
|
|
||||||
RANLIB ?= ranlib
|
|
||||||
STRIP ?= strip
|
|
||||||
else
|
|
||||||
CC = $(CROSS)-gcc
|
|
||||||
AR = $(CROSS)-ar
|
|
||||||
RANLIB = $(CROSS)-ranlib
|
|
||||||
STRIP = $(CROSS)-strip
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(PKG_EXTRA),)
|
|
||||||
PKG_VERSION = $(PKG_MAJOR).$(PKG_MINOR)
|
|
||||||
else
|
|
||||||
PKG_VERSION = $(PKG_MAJOR).$(PKG_MINOR).$(PKG_EXTRA)
|
|
||||||
endif
|
|
||||||
|
|
||||||
API_MAJOR=$(shell echo `grep -e UC_API_MAJOR include/unicorn/unicorn.h | grep -v = | awk '{print $$3}'` | awk '{print $$1}')
|
|
||||||
|
|
||||||
# Apple?
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
|
||||||
EXT = dylib
|
|
||||||
VERSION_EXT = $(API_MAJOR).$(EXT)
|
|
||||||
$(LIBNAME)_LDFLAGS += -dynamiclib -install_name @rpath/lib$(LIBNAME).$(VERSION_EXT) -current_version $(PKG_MAJOR).$(PKG_MINOR).$(PKG_EXTRA) -compatibility_version $(PKG_MAJOR).$(PKG_MINOR)
|
|
||||||
AR_EXT = a
|
|
||||||
UNICORN_CFLAGS += -fvisibility=hidden
|
|
||||||
|
|
||||||
ifeq ($(MACOS_UNIVERSAL),yes)
|
|
||||||
$(LIBNAME)_LDFLAGS += -m32 -arch i386 -m64 -arch x86_64
|
|
||||||
UNICORN_CFLAGS += -m32 -arch i386 -m64 -arch x86_64
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Cygwin?
|
|
||||||
else ifneq ($(filter CYGWIN%,$(UNAME_S)),)
|
|
||||||
EXT = dll
|
|
||||||
AR_EXT = a
|
|
||||||
BIN_EXT = .exe
|
|
||||||
UNICORN_CFLAGS := $(UNICORN_CFLAGS:-fPIC=)
|
|
||||||
#UNICORN_QEMU_FLAGS += --disable-stack-protector
|
|
||||||
|
|
||||||
# mingw?
|
|
||||||
else ifneq ($(filter MINGW%,$(UNAME_S)),)
|
|
||||||
EXT = dll
|
|
||||||
AR_EXT = a
|
|
||||||
BIN_EXT = .exe
|
|
||||||
UNICORN_QEMU_FLAGS += --disable-stack-protector
|
|
||||||
UNICORN_CFLAGS := $(UNICORN_CFLAGS:-fPIC=)
|
|
||||||
$(LIBNAME)_LDFLAGS += -Wl,--output-def,unicorn.def
|
|
||||||
DO_WINDOWS_EXPORT = 1
|
|
||||||
|
|
||||||
# Haiku
|
|
||||||
else ifneq ($(filter Haiku%,$(UNAME_S)),)
|
|
||||||
EXT = so
|
|
||||||
VERSION_EXT = $(EXT).$(API_MAJOR)
|
|
||||||
AR_EXT = a
|
|
||||||
$(LIBNAME)_LDFLAGS += -Wl,-Bsymbolic-functions,-soname,lib$(LIBNAME).$(VERSION_EXT)
|
|
||||||
UNICORN_CFLAGS := $(UNICORN_CFLAGS:-fPIC=)
|
|
||||||
UNICORN_QEMU_FLAGS += --disable-stack-protector
|
|
||||||
|
|
||||||
# Linux, Darwin
|
|
||||||
else
|
|
||||||
EXT = so
|
|
||||||
VERSION_EXT = $(EXT).$(API_MAJOR)
|
|
||||||
AR_EXT = a
|
|
||||||
$(LIBNAME)_LDFLAGS += -Wl,-Bsymbolic-functions,-soname,lib$(LIBNAME).$(VERSION_EXT)
|
|
||||||
UNICORN_CFLAGS += -fvisibility=hidden
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(UNICORN_SHARED),yes)
|
|
||||||
ifneq ($(filter MINGW%,$(UNAME_S)),)
|
|
||||||
LIBRARY = $(LIBNAME).$(EXT)
|
|
||||||
else ifneq ($(filter CYGWIN%,$(UNAME_S)),)
|
|
||||||
LIBRARY = cyg$(LIBNAME).$(EXT)
|
|
||||||
LIBRARY_DLLA = lib$(LIBNAME).$(EXT).$(AR_EXT)
|
|
||||||
$(LIBNAME)_LDFLAGS += -Wl,--out-implib=$(LIBRARY_DLLA)
|
|
||||||
$(LIBNAME)_LDFLAGS += -lssp
|
|
||||||
# Linux, Darwin
|
|
||||||
else
|
|
||||||
LIBRARY = lib$(LIBNAME).$(VERSION_EXT)
|
|
||||||
LIBRARY_SYMLINK = lib$(LIBNAME).$(EXT)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(UNICORN_STATIC),yes)
|
|
||||||
ifneq ($(filter MINGW%,$(UNAME_S)),)
|
|
||||||
ARCHIVE = $(LIBNAME).$(AR_EXT)
|
|
||||||
# Cygwin, Linux, Darwin
|
|
||||||
else
|
|
||||||
ARCHIVE = lib$(LIBNAME).$(AR_EXT)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
INSTALL_BIN ?= install
|
|
||||||
INSTALL_DATA ?= $(INSTALL_BIN) -m0644
|
|
||||||
INSTALL_LIB ?= $(INSTALL_BIN) -m0755
|
|
||||||
PKGCFGF = $(LIBNAME).pc
|
|
||||||
PREFIX ?= /usr
|
|
||||||
DESTDIR ?=
|
|
||||||
|
|
||||||
LIBDIRARCH ?= lib
|
|
||||||
# Uncomment the below line to installs x86_64 libs to lib64/ directory.
|
|
||||||
# Or better, pass 'LIBDIRARCH=lib64' to 'make install/uninstall' via 'make.sh'.
|
|
||||||
#LIBDIRARCH ?= lib64
|
|
||||||
|
|
||||||
LIBDIR ?= $(PREFIX)/$(LIBDIRARCH)
|
|
||||||
INCDIR ?= $(PREFIX)/include
|
|
||||||
BINDIR ?= $(PREFIX)/bin
|
|
||||||
|
|
||||||
LIBDATADIR ?= $(LIBDIR)
|
|
||||||
|
|
||||||
# Don't redefine $LIBDATADIR when global environment variable
|
|
||||||
# USE_GENERIC_LIBDATADIR is set. This is used by the pkgsrc framework.
|
|
||||||
|
|
||||||
ifndef USE_GENERIC_LIBDATADIR
|
|
||||||
ifeq ($(UNAME_S), FreeBSD)
|
|
||||||
LIBDATADIR = $(PREFIX)/libdata
|
|
||||||
else ifeq ($(UNAME_S), DragonFly)
|
|
||||||
LIBDATADIR = $(PREFIX)/libdata
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(PKG_EXTRA),)
|
|
||||||
PKGCFGDIR = $(LIBDATADIR)/pkgconfig
|
|
||||||
else
|
|
||||||
PKGCFGDIR ?= $(LIBDATADIR)/pkgconfig
|
|
||||||
endif
|
|
||||||
|
|
||||||
$(LIBNAME)_LDFLAGS += -lm
|
|
||||||
|
|
||||||
.PHONY: test fuzz bindings clean FORCE
|
|
||||||
|
|
||||||
all: unicorn
|
|
||||||
$(MAKE) -C samples
|
|
||||||
|
|
||||||
qemu/config-host.mak: qemu/configure
|
|
||||||
cd qemu && \
|
|
||||||
./configure --cc="${CC}" --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ${UNICORN_QEMU_FLAGS}
|
|
||||||
@printf "$(UNICORN_ARCHS)" > config.log
|
|
||||||
|
|
||||||
uc.o: qemu/config-host.mak FORCE
|
|
||||||
$(MAKE) -C qemu $(SMP_MFLAGS)
|
|
||||||
|
|
||||||
$(UC_TARGET_OBJ) list.o: uc.o
|
|
||||||
@echo "--- $^ $@" > /dev/null
|
|
||||||
|
|
||||||
unicorn: $(LIBRARY) $(ARCHIVE)
|
|
||||||
|
|
||||||
$(LIBRARY): $(UC_OBJ_ALL)
|
|
||||||
ifeq ($(UNICORN_SHARED),yes)
|
|
||||||
ifeq ($(V),0)
|
|
||||||
$(call log,GEN,$(LIBRARY))
|
|
||||||
@$(CC) $(CFLAGS) -shared $(UC_OBJ_ALL) -o $(LIBRARY) $($(LIBNAME)_LDFLAGS)
|
|
||||||
@-ln -sf $(LIBRARY) $(LIBRARY_SYMLINK)
|
|
||||||
else
|
|
||||||
$(CC) $(CFLAGS) -shared $(UC_OBJ_ALL) -o $(LIBRARY) $($(LIBNAME)_LDFLAGS)
|
|
||||||
-ln -sf $(LIBRARY) $(LIBRARY_SYMLINK)
|
|
||||||
endif
|
|
||||||
ifeq ($(DO_WINDOWS_EXPORT),1)
|
|
||||||
ifneq ($(filter MINGW32%,$(UNAME_S)),)
|
|
||||||
cmd //C "windows_export.bat x86"
|
|
||||||
else
|
|
||||||
cmd //C "windows_export.bat x64"
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
$(ARCHIVE): $(UC_OBJ_ALL)
|
|
||||||
ifeq ($(UNICORN_STATIC),yes)
|
|
||||||
ifeq ($(V),0)
|
|
||||||
$(call log,GEN,$(ARCHIVE))
|
|
||||||
@$(AR) q $(ARCHIVE) $(UC_OBJ_ALL)
|
|
||||||
@$(RANLIB) $(ARCHIVE)
|
|
||||||
else
|
|
||||||
$(AR) q $(ARCHIVE) $(UC_OBJ_ALL)
|
|
||||||
$(RANLIB) $(ARCHIVE)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
$(PKGCFGF):
|
|
||||||
$(generate-pkgcfg)
|
|
||||||
|
|
||||||
|
|
||||||
fuzz: all
|
|
||||||
$(MAKE) -C tests/fuzz all
|
|
||||||
|
|
||||||
test: all
|
|
||||||
$(MAKE) -C tests/unit test
|
|
||||||
$(MAKE) -C tests/regress test
|
|
||||||
$(MAKE) -C bindings test
|
|
||||||
|
|
||||||
install: $(LIBRARY) $(ARCHIVE) $(PKGCFGF)
|
|
||||||
install -d $(DESTDIR)$(LIBDIR)
|
|
||||||
ifeq ($(UNICORN_SHARED),yes)
|
|
||||||
ifneq ($(filter CYGWIN%,$(UNAME_S)),)
|
|
||||||
$(INSTALL_LIB) $(LIBRARY) $(DESTDIR)$(BINDIR)
|
|
||||||
$(INSTALL_DATA) $(LIBRARY_DLLA) $(DESTDIR)$(LIBDIR)
|
|
||||||
else
|
|
||||||
$(INSTALL_LIB) $(LIBRARY) $(DESTDIR)$(LIBDIR)
|
|
||||||
endif
|
|
||||||
ifneq ($(VERSION_EXT),)
|
|
||||||
cd $(DESTDIR)$(LIBDIR) && \
|
|
||||||
ln -sf lib$(LIBNAME).$(VERSION_EXT) lib$(LIBNAME).$(EXT)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
ifeq ($(UNICORN_STATIC),yes)
|
|
||||||
$(INSTALL_DATA) $(ARCHIVE) $(DESTDIR)$(LIBDIR)
|
|
||||||
endif
|
|
||||||
install -d $(DESTDIR)$(INCDIR)/$(LIBNAME)
|
|
||||||
$(INSTALL_DATA) include/unicorn/*.h $(DESTDIR)$(INCDIR)/$(LIBNAME)
|
|
||||||
install -d $(DESTDIR)$(PKGCFGDIR)
|
|
||||||
$(INSTALL_DATA) $(PKGCFGF) $(DESTDIR)$(PKGCFGDIR)/
|
|
||||||
|
|
||||||
|
|
||||||
TAG ?= HEAD
|
|
||||||
ifeq ($(TAG), HEAD)
|
|
||||||
DIST_VERSION = latest
|
|
||||||
else
|
|
||||||
DIST_VERSION = $(TAG)
|
|
||||||
endif
|
|
||||||
|
|
||||||
bindings: all
|
|
||||||
$(MAKE) -C bindings build
|
|
||||||
$(MAKE) -C bindings samples
|
|
||||||
|
|
||||||
dist:
|
|
||||||
git archive --format=tar.gz --prefix=unicorn-$(DIST_VERSION)/ $(TAG) > unicorn-$(DIST_VERSION).tgz
|
|
||||||
git archive --format=zip --prefix=unicorn-$(DIST_VERSION)/ $(TAG) > unicorn-$(DIST_VERSION).zip
|
|
||||||
|
|
||||||
|
|
||||||
# run "make header" whenever qemu/header_gen.py is modified
|
|
||||||
header:
|
|
||||||
$(eval TARGETS := m68k arm armeb aarch64 aarch64eb mips mipsel mips64 mips64el\
|
|
||||||
sparc sparc64 x86_64)
|
|
||||||
$(foreach var,$(TARGETS),\
|
|
||||||
$(shell python qemu/header_gen.py $(var) > qemu/$(var).h;))
|
|
||||||
@echo "Generated headers for $(TARGETS)."
|
|
||||||
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -rf $(INCDIR)/$(LIBNAME)
|
|
||||||
rm -f $(LIBDIR)/lib$(LIBNAME).*
|
|
||||||
rm -f $(BINDIR)/cyg$(LIBNAME).*
|
|
||||||
rm -f $(PKGCFGDIR)/$(LIBNAME).pc
|
|
||||||
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(MAKE) -C qemu distclean
|
|
||||||
rm -rf *.d *.o
|
|
||||||
rm -rf lib$(LIBNAME)* $(LIBNAME)*.lib $(LIBNAME)*.dll $(LIBNAME)*.a $(LIBNAME)*.def $(LIBNAME)*.exp cyg$(LIBNAME)*.dll
|
|
||||||
$(MAKE) -C samples clean
|
|
||||||
$(MAKE) -C tests/unit clean
|
|
||||||
|
|
||||||
|
|
||||||
define generate-pkgcfg
|
|
||||||
echo 'Name: unicorn' > $(PKGCFGF)
|
|
||||||
echo 'Description: Unicorn emulator engine' >> $(PKGCFGF)
|
|
||||||
echo 'Version: $(PKG_VERSION)' >> $(PKGCFGF)
|
|
||||||
echo 'libdir=$(LIBDIR)' >> $(PKGCFGF)
|
|
||||||
echo 'includedir=$(INCDIR)' >> $(PKGCFGF)
|
|
||||||
echo 'archive=$${libdir}/libunicorn.a' >> $(PKGCFGF)
|
|
||||||
echo 'Libs: -L$${libdir} -lunicorn' >> $(PKGCFGF)
|
|
||||||
echo 'Cflags: -I$${includedir}' >> $(PKGCFGF)
|
|
||||||
endef
|
|
||||||
|
|
||||||
|
|
||||||
define log
|
|
||||||
@printf " %-7s %s\n" "$(1)" "$(2)"
|
|
||||||
endef
|
|
|
@ -1,8 +1,6 @@
|
||||||
Unicorn Engine
|
Unicorn Engine
|
||||||
==============
|
==============
|
||||||
|
|
||||||
[![Join the chat at https://gitter.im/unicorn-engine/chat](https://badges.gitter.im/unicorn-engine/unicorn.svg)](https://gitter.im/unicorn-engine/chat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
||||||
[![Build Status](https://travis-ci.org/unicorn-engine/unicorn.svg?branch=master)](https://travis-ci.org/unicorn-engine/unicorn)
|
|
||||||
[![pypi downloads](https://pepy.tech/badge/unicorn)](https://pepy.tech/project/unicorn)
|
[![pypi downloads](https://pepy.tech/badge/unicorn)](https://pepy.tech/project/unicorn)
|
||||||
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/unicorn.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unicorn)
|
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/unicorn.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unicorn)
|
||||||
|
|
||||||
|
@ -11,7 +9,7 @@ based on [QEMU](http://qemu.org).
|
||||||
|
|
||||||
Unicorn offers some unparalleled features:
|
Unicorn offers some unparalleled features:
|
||||||
|
|
||||||
- Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, SPARC, and X86 (16, 32, 64-bit)
|
- Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, PowerPC, RISCV, SPARC, and X86 (16, 32, 64-bit)
|
||||||
- Clean/simple/lightweight/intuitive architecture-neutral API
|
- Clean/simple/lightweight/intuitive architecture-neutral API
|
||||||
- Implemented in pure C language, with bindings for Crystal, Clojure, Visual Basic, Perl, Rust, Ruby, Python, Java, .NET, Go, Delphi/Free Pascal, Haskell, Pharo, and Lua.
|
- Implemented in pure C language, with bindings for Crystal, Clojure, Visual Basic, Perl, Rust, Ruby, Python, Java, .NET, Go, Delphi/Free Pascal, Haskell, Pharo, and Lua.
|
||||||
- Native support for Windows & *nix (with Mac OSX, Linux, *BSD & Solaris confirmed)
|
- Native support for Windows & *nix (with Mac OSX, Linux, *BSD & Solaris confirmed)
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
* Version 1.0.2 - October 21st, 2020
|
|
||||||
|
|
||||||
Release 1.0.2 was sponsored by the following companies (in no particular order).
|
|
||||||
|
|
||||||
- Catena Cyber: https://catenacyber.fr
|
|
||||||
- Grayshift: https://grayshift.com
|
|
||||||
- Google: https://google.com
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
Optimization:
|
||||||
|
- avoid checking BB exit after every instruction. this need new OPT option?
|
||||||
|
|
||||||
|
----
|
||||||
|
- cleanup code
|
||||||
|
|
||||||
|
----
|
||||||
|
when we hook both BB & instruction, we insert 2 consecuritve calls to uc_tracecode.
|
||||||
|
optimize it by removing one
|
||||||
|
|
||||||
|
support Makefile, not just cmake?
|
|
@ -1,4 +1,4 @@
|
||||||
This directory contains bindings & test code for Python, Java, Go, .NET and Rust.
|
This directory contains bindings & test code for Python, Java, Go and .NET.
|
||||||
See <language>/README or <language>/README.TXT or <language>/README.md for how to install each binding.
|
See <language>/README or <language>/README.TXT or <language>/README.md for how to install each binding.
|
||||||
|
|
||||||
The following bindings are contributed by community.
|
The following bindings are contributed by community.
|
||||||
|
@ -10,14 +10,13 @@ The following bindings are contributed by community.
|
||||||
- Haskell binding: by Adrian Herrera.
|
- Haskell binding: by Adrian Herrera.
|
||||||
- VB6 binding: David Zimmer.
|
- VB6 binding: David Zimmer.
|
||||||
- FreePascal/Delphi binding: Mohamed Osama.
|
- FreePascal/Delphi binding: Mohamed Osama.
|
||||||
- Rust binding: Lukas Seidel.
|
|
||||||
|
|
||||||
More bindings created & maintained externally by community are available as follows.
|
More bindings created & maintained externally by community are available as follows.
|
||||||
|
|
||||||
- UnicornPascal: Delphi/Free Pascal binding (by Stievie).
|
- UnicornPascal: Delphi/Free Pascal binding (by Stievie).
|
||||||
https://github.com/stievie/UnicornPascal
|
https://github.com/stievie/UnicornPascal
|
||||||
|
|
||||||
- Unicorn-Rs: Rust binding (by Sébastien Duquette, unmaintained)
|
- Unicorn-Rs: Rust binding (by Sébastien Duquette)
|
||||||
https://github.com/ekse/unicorn-rs
|
https://github.com/ekse/unicorn-rs
|
||||||
|
|
||||||
- UnicornEngine: Perl binding (by Vikas Naresh Kumar)
|
- UnicornEngine: Perl binding (by Vikas Naresh Kumar)
|
||||||
|
@ -34,6 +33,3 @@ More bindings created & maintained externally by community are available as foll
|
||||||
|
|
||||||
- pharo-unicorn: Pharo binding (by Guille Polito)
|
- pharo-unicorn: Pharo binding (by Guille Polito)
|
||||||
https://github.com/guillep/pharo-unicorn
|
https://github.com/guillep/pharo-unicorn
|
||||||
|
|
||||||
- Unicorn.js: JavaScript binding (by Alexandro Sanchez)
|
|
||||||
https://github.com/AlexAltea/unicorn.js
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import sys, re, os
|
||||||
|
|
||||||
INCL_DIR = os.path.join('..', 'include', 'unicorn')
|
INCL_DIR = os.path.join('..', 'include', 'unicorn')
|
||||||
|
|
||||||
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h', 'unicorn.h' ]
|
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h', 'ppc.h', 'riscv.h', 'unicorn.h' ]
|
||||||
|
|
||||||
template = {
|
template = {
|
||||||
'python': {
|
'python': {
|
||||||
|
@ -21,6 +21,8 @@ template = {
|
||||||
'x86.h': 'x86',
|
'x86.h': 'x86',
|
||||||
'sparc.h': 'sparc',
|
'sparc.h': 'sparc',
|
||||||
'm68k.h': 'm68k',
|
'm68k.h': 'm68k',
|
||||||
|
'ppc.h': 'ppc',
|
||||||
|
'riscv.h': 'riscv',
|
||||||
'unicorn.h': 'unicorn',
|
'unicorn.h': 'unicorn',
|
||||||
'comment_open': '#',
|
'comment_open': '#',
|
||||||
'comment_close': '',
|
'comment_close': '',
|
||||||
|
@ -37,6 +39,8 @@ template = {
|
||||||
'x86.h': 'x86',
|
'x86.h': 'x86',
|
||||||
'sparc.h': 'sparc',
|
'sparc.h': 'sparc',
|
||||||
'm68k.h': 'm68k',
|
'm68k.h': 'm68k',
|
||||||
|
'ppc.h': 'ppc',
|
||||||
|
'riscv.h': 'riscv',
|
||||||
'unicorn.h': 'unicorn',
|
'unicorn.h': 'unicorn',
|
||||||
'comment_open': '#',
|
'comment_open': '#',
|
||||||
'comment_close': '',
|
'comment_close': '',
|
||||||
|
@ -53,6 +57,8 @@ template = {
|
||||||
'x86.h': 'x86',
|
'x86.h': 'x86',
|
||||||
'sparc.h': 'sparc',
|
'sparc.h': 'sparc',
|
||||||
'm68k.h': 'm68k',
|
'm68k.h': 'm68k',
|
||||||
|
'ppc.h': 'ppc',
|
||||||
|
'riscv.h': 'riscv',
|
||||||
'unicorn.h': 'unicorn',
|
'unicorn.h': 'unicorn',
|
||||||
'comment_open': '//',
|
'comment_open': '//',
|
||||||
'comment_close': '',
|
'comment_close': '',
|
||||||
|
@ -69,6 +75,8 @@ template = {
|
||||||
'x86.h': 'X86',
|
'x86.h': 'X86',
|
||||||
'sparc.h': 'Sparc',
|
'sparc.h': 'Sparc',
|
||||||
'm68k.h': 'M68k',
|
'm68k.h': 'M68k',
|
||||||
|
'ppc.h': 'Ppc',
|
||||||
|
'riscv.h': 'Riscv',
|
||||||
'unicorn.h': 'Unicorn',
|
'unicorn.h': 'Unicorn',
|
||||||
'comment_open': '//',
|
'comment_open': '//',
|
||||||
'comment_close': '',
|
'comment_close': '',
|
||||||
|
@ -85,6 +93,8 @@ template = {
|
||||||
'x86.h': 'X86',
|
'x86.h': 'X86',
|
||||||
'sparc.h': 'Sparc',
|
'sparc.h': 'Sparc',
|
||||||
'm68k.h': 'M68k',
|
'm68k.h': 'M68k',
|
||||||
|
'ppc.h': 'Ppc',
|
||||||
|
'riscv.h': 'Riscv',
|
||||||
'unicorn.h': 'Common',
|
'unicorn.h': 'Common',
|
||||||
'comment_open': ' //',
|
'comment_open': ' //',
|
||||||
'comment_close': '',
|
'comment_close': '',
|
||||||
|
@ -101,6 +111,8 @@ template = {
|
||||||
'x86.h': 'X86',
|
'x86.h': 'X86',
|
||||||
'sparc.h': 'Sparc',
|
'sparc.h': 'Sparc',
|
||||||
'm68k.h': 'M68k',
|
'm68k.h': 'M68k',
|
||||||
|
'ppc.h': 'Ppc',
|
||||||
|
'riscv.h': 'Riscv',
|
||||||
'unicorn.h': 'Unicorn',
|
'unicorn.h': 'Unicorn',
|
||||||
'comment_open': '//',
|
'comment_open': '//',
|
||||||
'comment_close': '',
|
'comment_close': '',
|
||||||
|
|
|
@ -6,13 +6,14 @@ open System
|
||||||
|
|
||||||
[<AutoOpen>]
|
[<AutoOpen>]
|
||||||
module Common =
|
module Common =
|
||||||
let UC_API_MAJOR = 1
|
let UC_API_MAJOR = 2
|
||||||
|
|
||||||
let UC_API_MINOR = 0
|
let UC_API_MINOR = 0
|
||||||
let UC_VERSION_MAJOR = 1
|
let UC_VERSION_MAJOR = 2
|
||||||
|
|
||||||
let UC_VERSION_MINOR = 0
|
let UC_VERSION_MINOR = 0
|
||||||
let UC_VERSION_EXTRA = 3
|
|
||||||
|
let UC_VERSION_EXTRA = 0
|
||||||
let UC_SECOND_SCALE = 1000000
|
let UC_SECOND_SCALE = 1000000
|
||||||
let UC_MILISECOND_SCALE = 1000
|
let UC_MILISECOND_SCALE = 1000
|
||||||
let UC_ARCH_ARM = 1
|
let UC_ARCH_ARM = 1
|
||||||
|
@ -22,7 +23,8 @@ module Common =
|
||||||
let UC_ARCH_PPC = 5
|
let UC_ARCH_PPC = 5
|
||||||
let UC_ARCH_SPARC = 6
|
let UC_ARCH_SPARC = 6
|
||||||
let UC_ARCH_M68K = 7
|
let UC_ARCH_M68K = 7
|
||||||
let UC_ARCH_MAX = 8
|
let UC_ARCH_RISCV = 8
|
||||||
|
let UC_ARCH_MAX = 9
|
||||||
|
|
||||||
let UC_MODE_LITTLE_ENDIAN = 0
|
let UC_MODE_LITTLE_ENDIAN = 0
|
||||||
let UC_MODE_BIG_ENDIAN = 1073741824
|
let UC_MODE_BIG_ENDIAN = 1073741824
|
||||||
|
@ -34,7 +36,6 @@ module Common =
|
||||||
let UC_MODE_ARM926 = 128
|
let UC_MODE_ARM926 = 128
|
||||||
let UC_MODE_ARM946 = 256
|
let UC_MODE_ARM946 = 256
|
||||||
let UC_MODE_ARM1176 = 512
|
let UC_MODE_ARM1176 = 512
|
||||||
let UC_MODE_ARMBE8 = 1024
|
|
||||||
let UC_MODE_MICRO = 16
|
let UC_MODE_MICRO = 16
|
||||||
let UC_MODE_MIPS3 = 32
|
let UC_MODE_MIPS3 = 32
|
||||||
let UC_MODE_MIPS32R6 = 64
|
let UC_MODE_MIPS32R6 = 64
|
||||||
|
@ -49,6 +50,8 @@ module Common =
|
||||||
let UC_MODE_SPARC32 = 4
|
let UC_MODE_SPARC32 = 4
|
||||||
let UC_MODE_SPARC64 = 8
|
let UC_MODE_SPARC64 = 8
|
||||||
let UC_MODE_V9 = 16
|
let UC_MODE_V9 = 16
|
||||||
|
let UC_MODE_RISCV32 = 4
|
||||||
|
let UC_MODE_RISCV64 = 8
|
||||||
|
|
||||||
let UC_ERR_OK = 0
|
let UC_ERR_OK = 0
|
||||||
let UC_ERR_NOMEM = 1
|
let UC_ERR_NOMEM = 1
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
|
namespace UnicornManaged.Const
|
||||||
|
|
||||||
|
open System
|
||||||
|
|
||||||
|
[<AutoOpen>]
|
||||||
|
module Ppc =
|
||||||
|
|
||||||
|
// PPC registers
|
||||||
|
|
||||||
|
let UC_PPC_REG_INVALID = 0
|
||||||
|
|
||||||
|
// General purpose registers
|
||||||
|
let UC_PPC_REG_PC = 1
|
||||||
|
let UC_PPC_REG_0 = 2
|
||||||
|
let UC_PPC_REG_1 = 3
|
||||||
|
let UC_PPC_REG_2 = 4
|
||||||
|
let UC_PPC_REG_3 = 5
|
||||||
|
let UC_PPC_REG_4 = 6
|
||||||
|
let UC_PPC_REG_5 = 7
|
||||||
|
let UC_PPC_REG_6 = 8
|
||||||
|
let UC_PPC_REG_7 = 9
|
||||||
|
let UC_PPC_REG_8 = 10
|
||||||
|
let UC_PPC_REG_9 = 11
|
||||||
|
let UC_PPC_REG_10 = 12
|
||||||
|
let UC_PPC_REG_11 = 13
|
||||||
|
let UC_PPC_REG_12 = 14
|
||||||
|
let UC_PPC_REG_13 = 15
|
||||||
|
let UC_PPC_REG_14 = 16
|
||||||
|
let UC_PPC_REG_15 = 17
|
||||||
|
let UC_PPC_REG_16 = 18
|
||||||
|
let UC_PPC_REG_17 = 19
|
||||||
|
let UC_PPC_REG_18 = 20
|
||||||
|
let UC_PPC_REG_19 = 21
|
||||||
|
let UC_PPC_REG_20 = 22
|
||||||
|
let UC_PPC_REG_21 = 23
|
||||||
|
let UC_PPC_REG_22 = 24
|
||||||
|
let UC_PPC_REG_23 = 25
|
||||||
|
let UC_PPC_REG_24 = 26
|
||||||
|
let UC_PPC_REG_25 = 27
|
||||||
|
let UC_PPC_REG_26 = 28
|
||||||
|
let UC_PPC_REG_27 = 29
|
||||||
|
let UC_PPC_REG_28 = 30
|
||||||
|
let UC_PPC_REG_29 = 31
|
||||||
|
let UC_PPC_REG_30 = 32
|
||||||
|
let UC_PPC_REG_31 = 33
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
|
namespace UnicornManaged.Const
|
||||||
|
|
||||||
|
open System
|
||||||
|
|
||||||
|
[<AutoOpen>]
|
||||||
|
module Riscv =
|
||||||
|
|
||||||
|
// RISCV registers
|
||||||
|
|
||||||
|
let UC_RISCV_REG_INVALID = 0
|
||||||
|
|
||||||
|
// General purpose registers
|
||||||
|
let UC_RISCV_REG_X0 = 1
|
||||||
|
let UC_RISCV_REG_X1 = 2
|
||||||
|
let UC_RISCV_REG_X2 = 3
|
||||||
|
let UC_RISCV_REG_X3 = 4
|
||||||
|
let UC_RISCV_REG_X4 = 5
|
||||||
|
let UC_RISCV_REG_X5 = 6
|
||||||
|
let UC_RISCV_REG_X6 = 7
|
||||||
|
let UC_RISCV_REG_X7 = 8
|
||||||
|
let UC_RISCV_REG_X8 = 9
|
||||||
|
let UC_RISCV_REG_X9 = 10
|
||||||
|
let UC_RISCV_REG_X10 = 11
|
||||||
|
let UC_RISCV_REG_X11 = 12
|
||||||
|
let UC_RISCV_REG_X12 = 13
|
||||||
|
let UC_RISCV_REG_X13 = 14
|
||||||
|
let UC_RISCV_REG_X14 = 15
|
||||||
|
let UC_RISCV_REG_X15 = 16
|
||||||
|
let UC_RISCV_REG_X16 = 17
|
||||||
|
let UC_RISCV_REG_X17 = 18
|
||||||
|
let UC_RISCV_REG_X18 = 19
|
||||||
|
let UC_RISCV_REG_X19 = 20
|
||||||
|
let UC_RISCV_REG_X20 = 21
|
||||||
|
let UC_RISCV_REG_X21 = 22
|
||||||
|
let UC_RISCV_REG_X22 = 23
|
||||||
|
let UC_RISCV_REG_X23 = 24
|
||||||
|
let UC_RISCV_REG_X24 = 25
|
||||||
|
let UC_RISCV_REG_X25 = 26
|
||||||
|
let UC_RISCV_REG_X26 = 27
|
||||||
|
let UC_RISCV_REG_X27 = 28
|
||||||
|
let UC_RISCV_REG_X28 = 29
|
||||||
|
let UC_RISCV_REG_X29 = 30
|
||||||
|
let UC_RISCV_REG_X30 = 31
|
||||||
|
let UC_RISCV_REG_X31 = 32
|
||||||
|
|
||||||
|
// Floating-point registers
|
||||||
|
let UC_RISCV_REG_F0 = 33
|
||||||
|
let UC_RISCV_REG_F1 = 34
|
||||||
|
let UC_RISCV_REG_F2 = 35
|
||||||
|
let UC_RISCV_REG_F3 = 36
|
||||||
|
let UC_RISCV_REG_F4 = 37
|
||||||
|
let UC_RISCV_REG_F5 = 38
|
||||||
|
let UC_RISCV_REG_F6 = 39
|
||||||
|
let UC_RISCV_REG_F7 = 40
|
||||||
|
let UC_RISCV_REG_F8 = 41
|
||||||
|
let UC_RISCV_REG_F9 = 42
|
||||||
|
let UC_RISCV_REG_F10 = 43
|
||||||
|
let UC_RISCV_REG_F11 = 44
|
||||||
|
let UC_RISCV_REG_F12 = 45
|
||||||
|
let UC_RISCV_REG_F13 = 46
|
||||||
|
let UC_RISCV_REG_F14 = 47
|
||||||
|
let UC_RISCV_REG_F15 = 48
|
||||||
|
let UC_RISCV_REG_F16 = 49
|
||||||
|
let UC_RISCV_REG_F17 = 50
|
||||||
|
let UC_RISCV_REG_F18 = 51
|
||||||
|
let UC_RISCV_REG_F19 = 52
|
||||||
|
let UC_RISCV_REG_F20 = 53
|
||||||
|
let UC_RISCV_REG_F21 = 54
|
||||||
|
let UC_RISCV_REG_F22 = 55
|
||||||
|
let UC_RISCV_REG_F23 = 56
|
||||||
|
let UC_RISCV_REG_F24 = 57
|
||||||
|
let UC_RISCV_REG_F25 = 58
|
||||||
|
let UC_RISCV_REG_F26 = 59
|
||||||
|
let UC_RISCV_REG_F27 = 60
|
||||||
|
let UC_RISCV_REG_F28 = 61
|
||||||
|
let UC_RISCV_REG_F29 = 62
|
||||||
|
let UC_RISCV_REG_F30 = 63
|
||||||
|
let UC_RISCV_REG_F31 = 64
|
||||||
|
let UC_RISCV_REG_PC = 65
|
||||||
|
let UC_RISCV_REG_ENDING = 66
|
||||||
|
|
||||||
|
// Alias registers
|
||||||
|
let UC_RISCV_REG_ZERO = 1
|
||||||
|
let UC_RISCV_REG_RA = 2
|
||||||
|
let UC_RISCV_REG_SP = 3
|
||||||
|
let UC_RISCV_REG_GP = 4
|
||||||
|
let UC_RISCV_REG_TP = 5
|
||||||
|
let UC_RISCV_REG_T0 = 6
|
||||||
|
let UC_RISCV_REG_T1 = 7
|
||||||
|
let UC_RISCV_REG_T2 = 8
|
||||||
|
let UC_RISCV_REG_S0 = 9
|
||||||
|
let UC_RISCV_REG_FP = 9
|
||||||
|
let UC_RISCV_REG_S1 = 10
|
||||||
|
let UC_RISCV_REG_A0 = 11
|
||||||
|
let UC_RISCV_REG_A1 = 12
|
||||||
|
let UC_RISCV_REG_A2 = 13
|
||||||
|
let UC_RISCV_REG_A3 = 14
|
||||||
|
let UC_RISCV_REG_A4 = 15
|
||||||
|
let UC_RISCV_REG_A5 = 16
|
||||||
|
let UC_RISCV_REG_A6 = 17
|
||||||
|
let UC_RISCV_REG_A7 = 18
|
||||||
|
let UC_RISCV_REG_S2 = 19
|
||||||
|
let UC_RISCV_REG_S3 = 20
|
||||||
|
let UC_RISCV_REG_S4 = 21
|
||||||
|
let UC_RISCV_REG_S5 = 22
|
||||||
|
let UC_RISCV_REG_S6 = 23
|
||||||
|
let UC_RISCV_REG_S7 = 24
|
||||||
|
let UC_RISCV_REG_S8 = 25
|
||||||
|
let UC_RISCV_REG_S9 = 26
|
||||||
|
let UC_RISCV_REG_S10 = 27
|
||||||
|
let UC_RISCV_REG_S11 = 28
|
||||||
|
let UC_RISCV_REG_T3 = 29
|
||||||
|
let UC_RISCV_REG_T4 = 30
|
||||||
|
let UC_RISCV_REG_T5 = 31
|
||||||
|
let UC_RISCV_REG_T6 = 32
|
||||||
|
let UC_RISCV_REG_FT0 = 33
|
||||||
|
let UC_RISCV_REG_FT1 = 34
|
||||||
|
let UC_RISCV_REG_FT2 = 35
|
||||||
|
let UC_RISCV_REG_FT3 = 36
|
||||||
|
let UC_RISCV_REG_FT4 = 37
|
||||||
|
let UC_RISCV_REG_FT5 = 38
|
||||||
|
let UC_RISCV_REG_FT6 = 39
|
||||||
|
let UC_RISCV_REG_FT7 = 40
|
||||||
|
let UC_RISCV_REG_FS0 = 41
|
||||||
|
let UC_RISCV_REG_FS1 = 42
|
||||||
|
let UC_RISCV_REG_FA0 = 43
|
||||||
|
let UC_RISCV_REG_FA1 = 44
|
||||||
|
let UC_RISCV_REG_FA2 = 45
|
||||||
|
let UC_RISCV_REG_FA3 = 46
|
||||||
|
let UC_RISCV_REG_FA4 = 47
|
||||||
|
let UC_RISCV_REG_FA5 = 48
|
||||||
|
let UC_RISCV_REG_FA6 = 49
|
||||||
|
let UC_RISCV_REG_FA7 = 50
|
||||||
|
let UC_RISCV_REG_FS2 = 51
|
||||||
|
let UC_RISCV_REG_FS3 = 52
|
||||||
|
let UC_RISCV_REG_FS4 = 53
|
||||||
|
let UC_RISCV_REG_FS5 = 54
|
||||||
|
let UC_RISCV_REG_FS6 = 55
|
||||||
|
let UC_RISCV_REG_FS7 = 56
|
||||||
|
let UC_RISCV_REG_FS8 = 57
|
||||||
|
let UC_RISCV_REG_FS9 = 58
|
||||||
|
let UC_RISCV_REG_FS10 = 59
|
||||||
|
let UC_RISCV_REG_FS11 = 60
|
||||||
|
let UC_RISCV_REG_FT8 = 61
|
||||||
|
let UC_RISCV_REG_FT9 = 62
|
||||||
|
let UC_RISCV_REG_FT10 = 63
|
||||||
|
let UC_RISCV_REG_FT11 = 64
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
package unicorn
|
||||||
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.go]
|
||||||
|
const (
|
||||||
|
|
||||||
|
// PPC registers
|
||||||
|
|
||||||
|
PPC_REG_INVALID = 0
|
||||||
|
|
||||||
|
// General purpose registers
|
||||||
|
PPC_REG_PC = 1
|
||||||
|
PPC_REG_0 = 2
|
||||||
|
PPC_REG_1 = 3
|
||||||
|
PPC_REG_2 = 4
|
||||||
|
PPC_REG_3 = 5
|
||||||
|
PPC_REG_4 = 6
|
||||||
|
PPC_REG_5 = 7
|
||||||
|
PPC_REG_6 = 8
|
||||||
|
PPC_REG_7 = 9
|
||||||
|
PPC_REG_8 = 10
|
||||||
|
PPC_REG_9 = 11
|
||||||
|
PPC_REG_10 = 12
|
||||||
|
PPC_REG_11 = 13
|
||||||
|
PPC_REG_12 = 14
|
||||||
|
PPC_REG_13 = 15
|
||||||
|
PPC_REG_14 = 16
|
||||||
|
PPC_REG_15 = 17
|
||||||
|
PPC_REG_16 = 18
|
||||||
|
PPC_REG_17 = 19
|
||||||
|
PPC_REG_18 = 20
|
||||||
|
PPC_REG_19 = 21
|
||||||
|
PPC_REG_20 = 22
|
||||||
|
PPC_REG_21 = 23
|
||||||
|
PPC_REG_22 = 24
|
||||||
|
PPC_REG_23 = 25
|
||||||
|
PPC_REG_24 = 26
|
||||||
|
PPC_REG_25 = 27
|
||||||
|
PPC_REG_26 = 28
|
||||||
|
PPC_REG_27 = 29
|
||||||
|
PPC_REG_28 = 30
|
||||||
|
PPC_REG_29 = 31
|
||||||
|
PPC_REG_30 = 32
|
||||||
|
PPC_REG_31 = 33
|
||||||
|
)
|
|
@ -0,0 +1,145 @@
|
||||||
|
package unicorn
|
||||||
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.go]
|
||||||
|
const (
|
||||||
|
|
||||||
|
// RISCV registers
|
||||||
|
|
||||||
|
RISCV_REG_INVALID = 0
|
||||||
|
|
||||||
|
// General purpose registers
|
||||||
|
RISCV_REG_X0 = 1
|
||||||
|
RISCV_REG_X1 = 2
|
||||||
|
RISCV_REG_X2 = 3
|
||||||
|
RISCV_REG_X3 = 4
|
||||||
|
RISCV_REG_X4 = 5
|
||||||
|
RISCV_REG_X5 = 6
|
||||||
|
RISCV_REG_X6 = 7
|
||||||
|
RISCV_REG_X7 = 8
|
||||||
|
RISCV_REG_X8 = 9
|
||||||
|
RISCV_REG_X9 = 10
|
||||||
|
RISCV_REG_X10 = 11
|
||||||
|
RISCV_REG_X11 = 12
|
||||||
|
RISCV_REG_X12 = 13
|
||||||
|
RISCV_REG_X13 = 14
|
||||||
|
RISCV_REG_X14 = 15
|
||||||
|
RISCV_REG_X15 = 16
|
||||||
|
RISCV_REG_X16 = 17
|
||||||
|
RISCV_REG_X17 = 18
|
||||||
|
RISCV_REG_X18 = 19
|
||||||
|
RISCV_REG_X19 = 20
|
||||||
|
RISCV_REG_X20 = 21
|
||||||
|
RISCV_REG_X21 = 22
|
||||||
|
RISCV_REG_X22 = 23
|
||||||
|
RISCV_REG_X23 = 24
|
||||||
|
RISCV_REG_X24 = 25
|
||||||
|
RISCV_REG_X25 = 26
|
||||||
|
RISCV_REG_X26 = 27
|
||||||
|
RISCV_REG_X27 = 28
|
||||||
|
RISCV_REG_X28 = 29
|
||||||
|
RISCV_REG_X29 = 30
|
||||||
|
RISCV_REG_X30 = 31
|
||||||
|
RISCV_REG_X31 = 32
|
||||||
|
|
||||||
|
// Floating-point registers
|
||||||
|
RISCV_REG_F0 = 33
|
||||||
|
RISCV_REG_F1 = 34
|
||||||
|
RISCV_REG_F2 = 35
|
||||||
|
RISCV_REG_F3 = 36
|
||||||
|
RISCV_REG_F4 = 37
|
||||||
|
RISCV_REG_F5 = 38
|
||||||
|
RISCV_REG_F6 = 39
|
||||||
|
RISCV_REG_F7 = 40
|
||||||
|
RISCV_REG_F8 = 41
|
||||||
|
RISCV_REG_F9 = 42
|
||||||
|
RISCV_REG_F10 = 43
|
||||||
|
RISCV_REG_F11 = 44
|
||||||
|
RISCV_REG_F12 = 45
|
||||||
|
RISCV_REG_F13 = 46
|
||||||
|
RISCV_REG_F14 = 47
|
||||||
|
RISCV_REG_F15 = 48
|
||||||
|
RISCV_REG_F16 = 49
|
||||||
|
RISCV_REG_F17 = 50
|
||||||
|
RISCV_REG_F18 = 51
|
||||||
|
RISCV_REG_F19 = 52
|
||||||
|
RISCV_REG_F20 = 53
|
||||||
|
RISCV_REG_F21 = 54
|
||||||
|
RISCV_REG_F22 = 55
|
||||||
|
RISCV_REG_F23 = 56
|
||||||
|
RISCV_REG_F24 = 57
|
||||||
|
RISCV_REG_F25 = 58
|
||||||
|
RISCV_REG_F26 = 59
|
||||||
|
RISCV_REG_F27 = 60
|
||||||
|
RISCV_REG_F28 = 61
|
||||||
|
RISCV_REG_F29 = 62
|
||||||
|
RISCV_REG_F30 = 63
|
||||||
|
RISCV_REG_F31 = 64
|
||||||
|
RISCV_REG_PC = 65
|
||||||
|
RISCV_REG_ENDING = 66
|
||||||
|
|
||||||
|
// Alias registers
|
||||||
|
RISCV_REG_ZERO = 1
|
||||||
|
RISCV_REG_RA = 2
|
||||||
|
RISCV_REG_SP = 3
|
||||||
|
RISCV_REG_GP = 4
|
||||||
|
RISCV_REG_TP = 5
|
||||||
|
RISCV_REG_T0 = 6
|
||||||
|
RISCV_REG_T1 = 7
|
||||||
|
RISCV_REG_T2 = 8
|
||||||
|
RISCV_REG_S0 = 9
|
||||||
|
RISCV_REG_FP = 9
|
||||||
|
RISCV_REG_S1 = 10
|
||||||
|
RISCV_REG_A0 = 11
|
||||||
|
RISCV_REG_A1 = 12
|
||||||
|
RISCV_REG_A2 = 13
|
||||||
|
RISCV_REG_A3 = 14
|
||||||
|
RISCV_REG_A4 = 15
|
||||||
|
RISCV_REG_A5 = 16
|
||||||
|
RISCV_REG_A6 = 17
|
||||||
|
RISCV_REG_A7 = 18
|
||||||
|
RISCV_REG_S2 = 19
|
||||||
|
RISCV_REG_S3 = 20
|
||||||
|
RISCV_REG_S4 = 21
|
||||||
|
RISCV_REG_S5 = 22
|
||||||
|
RISCV_REG_S6 = 23
|
||||||
|
RISCV_REG_S7 = 24
|
||||||
|
RISCV_REG_S8 = 25
|
||||||
|
RISCV_REG_S9 = 26
|
||||||
|
RISCV_REG_S10 = 27
|
||||||
|
RISCV_REG_S11 = 28
|
||||||
|
RISCV_REG_T3 = 29
|
||||||
|
RISCV_REG_T4 = 30
|
||||||
|
RISCV_REG_T5 = 31
|
||||||
|
RISCV_REG_T6 = 32
|
||||||
|
RISCV_REG_FT0 = 33
|
||||||
|
RISCV_REG_FT1 = 34
|
||||||
|
RISCV_REG_FT2 = 35
|
||||||
|
RISCV_REG_FT3 = 36
|
||||||
|
RISCV_REG_FT4 = 37
|
||||||
|
RISCV_REG_FT5 = 38
|
||||||
|
RISCV_REG_FT6 = 39
|
||||||
|
RISCV_REG_FT7 = 40
|
||||||
|
RISCV_REG_FS0 = 41
|
||||||
|
RISCV_REG_FS1 = 42
|
||||||
|
RISCV_REG_FA0 = 43
|
||||||
|
RISCV_REG_FA1 = 44
|
||||||
|
RISCV_REG_FA2 = 45
|
||||||
|
RISCV_REG_FA3 = 46
|
||||||
|
RISCV_REG_FA4 = 47
|
||||||
|
RISCV_REG_FA5 = 48
|
||||||
|
RISCV_REG_FA6 = 49
|
||||||
|
RISCV_REG_FA7 = 50
|
||||||
|
RISCV_REG_FS2 = 51
|
||||||
|
RISCV_REG_FS3 = 52
|
||||||
|
RISCV_REG_FS4 = 53
|
||||||
|
RISCV_REG_FS5 = 54
|
||||||
|
RISCV_REG_FS6 = 55
|
||||||
|
RISCV_REG_FS7 = 56
|
||||||
|
RISCV_REG_FS8 = 57
|
||||||
|
RISCV_REG_FS9 = 58
|
||||||
|
RISCV_REG_FS10 = 59
|
||||||
|
RISCV_REG_FS11 = 60
|
||||||
|
RISCV_REG_FT8 = 61
|
||||||
|
RISCV_REG_FT9 = 62
|
||||||
|
RISCV_REG_FT10 = 63
|
||||||
|
RISCV_REG_FT11 = 64
|
||||||
|
)
|
|
@ -1,13 +1,14 @@
|
||||||
package unicorn
|
package unicorn
|
||||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go]
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go]
|
||||||
const (
|
const (
|
||||||
API_MAJOR = 1
|
API_MAJOR = 2
|
||||||
|
|
||||||
API_MINOR = 0
|
API_MINOR = 0
|
||||||
VERSION_MAJOR = 1
|
VERSION_MAJOR = 2
|
||||||
|
|
||||||
VERSION_MINOR = 0
|
VERSION_MINOR = 0
|
||||||
VERSION_EXTRA = 3
|
|
||||||
|
VERSION_EXTRA = 0
|
||||||
SECOND_SCALE = 1000000
|
SECOND_SCALE = 1000000
|
||||||
MILISECOND_SCALE = 1000
|
MILISECOND_SCALE = 1000
|
||||||
ARCH_ARM = 1
|
ARCH_ARM = 1
|
||||||
|
@ -17,7 +18,8 @@ const (
|
||||||
ARCH_PPC = 5
|
ARCH_PPC = 5
|
||||||
ARCH_SPARC = 6
|
ARCH_SPARC = 6
|
||||||
ARCH_M68K = 7
|
ARCH_M68K = 7
|
||||||
ARCH_MAX = 8
|
ARCH_RISCV = 8
|
||||||
|
ARCH_MAX = 9
|
||||||
|
|
||||||
MODE_LITTLE_ENDIAN = 0
|
MODE_LITTLE_ENDIAN = 0
|
||||||
MODE_BIG_ENDIAN = 1073741824
|
MODE_BIG_ENDIAN = 1073741824
|
||||||
|
@ -29,7 +31,6 @@ const (
|
||||||
MODE_ARM926 = 128
|
MODE_ARM926 = 128
|
||||||
MODE_ARM946 = 256
|
MODE_ARM946 = 256
|
||||||
MODE_ARM1176 = 512
|
MODE_ARM1176 = 512
|
||||||
MODE_ARMBE8 = 1024
|
|
||||||
MODE_MICRO = 16
|
MODE_MICRO = 16
|
||||||
MODE_MIPS3 = 32
|
MODE_MIPS3 = 32
|
||||||
MODE_MIPS32R6 = 64
|
MODE_MIPS32R6 = 64
|
||||||
|
@ -44,6 +45,8 @@ const (
|
||||||
MODE_SPARC32 = 4
|
MODE_SPARC32 = 4
|
||||||
MODE_SPARC64 = 8
|
MODE_SPARC64 = 8
|
||||||
MODE_V9 = 16
|
MODE_V9 = 16
|
||||||
|
MODE_RISCV32 = 4
|
||||||
|
MODE_RISCV64 = 8
|
||||||
|
|
||||||
ERR_OK = 0
|
ERR_OK = 0
|
||||||
ERR_NOMEM = 1
|
ERR_NOMEM = 1
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
JAVA_HOME := $(shell jrunscript -e 'java.lang.System.out.println(java.lang.System.getProperty("java.home"));')
|
JAVA_HOME := $(shell jrunscript -e 'java.lang.System.out.println(java.lang.System.getProperty("java.home"));')
|
||||||
|
|
||||||
JAVA_INC := $(shell realpath $(JAVA_HOME)/include)
|
JAVA_INC := $(shell realpath $(JAVA_HOME)/../include)
|
||||||
|
|
||||||
JAVA_PLATFORM_INC := $(shell dirname `find $(JAVA_INC) -name jni_md.h`)
|
JAVA_PLATFORM_INC := $(shell dirname `find $(JAVA_INC) -name jni_md.h`)
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ all: lib jar samples
|
||||||
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
|
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
|
||||||
|
|
||||||
unicorn_Unicorn.h: unicorn/Unicorn.java
|
unicorn_Unicorn.h: unicorn/Unicorn.java
|
||||||
javac -h unicorn/ unicorn/*.java
|
javah unicorn.Unicorn
|
||||||
|
|
||||||
unicorn_Unicorn.o: unicorn_Unicorn.c unicorn_Unicorn.h
|
unicorn_Unicorn.o: unicorn_Unicorn.c unicorn_Unicorn.h
|
||||||
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
|
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
|
package unicorn;
|
||||||
|
|
||||||
|
public interface PpcConst {
|
||||||
|
|
||||||
|
// PPC registers
|
||||||
|
|
||||||
|
public static final int UC_PPC_REG_INVALID = 0;
|
||||||
|
|
||||||
|
// General purpose registers
|
||||||
|
public static final int UC_PPC_REG_PC = 1;
|
||||||
|
public static final int UC_PPC_REG_0 = 2;
|
||||||
|
public static final int UC_PPC_REG_1 = 3;
|
||||||
|
public static final int UC_PPC_REG_2 = 4;
|
||||||
|
public static final int UC_PPC_REG_3 = 5;
|
||||||
|
public static final int UC_PPC_REG_4 = 6;
|
||||||
|
public static final int UC_PPC_REG_5 = 7;
|
||||||
|
public static final int UC_PPC_REG_6 = 8;
|
||||||
|
public static final int UC_PPC_REG_7 = 9;
|
||||||
|
public static final int UC_PPC_REG_8 = 10;
|
||||||
|
public static final int UC_PPC_REG_9 = 11;
|
||||||
|
public static final int UC_PPC_REG_10 = 12;
|
||||||
|
public static final int UC_PPC_REG_11 = 13;
|
||||||
|
public static final int UC_PPC_REG_12 = 14;
|
||||||
|
public static final int UC_PPC_REG_13 = 15;
|
||||||
|
public static final int UC_PPC_REG_14 = 16;
|
||||||
|
public static final int UC_PPC_REG_15 = 17;
|
||||||
|
public static final int UC_PPC_REG_16 = 18;
|
||||||
|
public static final int UC_PPC_REG_17 = 19;
|
||||||
|
public static final int UC_PPC_REG_18 = 20;
|
||||||
|
public static final int UC_PPC_REG_19 = 21;
|
||||||
|
public static final int UC_PPC_REG_20 = 22;
|
||||||
|
public static final int UC_PPC_REG_21 = 23;
|
||||||
|
public static final int UC_PPC_REG_22 = 24;
|
||||||
|
public static final int UC_PPC_REG_23 = 25;
|
||||||
|
public static final int UC_PPC_REG_24 = 26;
|
||||||
|
public static final int UC_PPC_REG_25 = 27;
|
||||||
|
public static final int UC_PPC_REG_26 = 28;
|
||||||
|
public static final int UC_PPC_REG_27 = 29;
|
||||||
|
public static final int UC_PPC_REG_28 = 30;
|
||||||
|
public static final int UC_PPC_REG_29 = 31;
|
||||||
|
public static final int UC_PPC_REG_30 = 32;
|
||||||
|
public static final int UC_PPC_REG_31 = 33;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
|
package unicorn;
|
||||||
|
|
||||||
|
public interface RiscvConst {
|
||||||
|
|
||||||
|
// RISCV registers
|
||||||
|
|
||||||
|
public static final int UC_RISCV_REG_INVALID = 0;
|
||||||
|
|
||||||
|
// General purpose registers
|
||||||
|
public static final int UC_RISCV_REG_X0 = 1;
|
||||||
|
public static final int UC_RISCV_REG_X1 = 2;
|
||||||
|
public static final int UC_RISCV_REG_X2 = 3;
|
||||||
|
public static final int UC_RISCV_REG_X3 = 4;
|
||||||
|
public static final int UC_RISCV_REG_X4 = 5;
|
||||||
|
public static final int UC_RISCV_REG_X5 = 6;
|
||||||
|
public static final int UC_RISCV_REG_X6 = 7;
|
||||||
|
public static final int UC_RISCV_REG_X7 = 8;
|
||||||
|
public static final int UC_RISCV_REG_X8 = 9;
|
||||||
|
public static final int UC_RISCV_REG_X9 = 10;
|
||||||
|
public static final int UC_RISCV_REG_X10 = 11;
|
||||||
|
public static final int UC_RISCV_REG_X11 = 12;
|
||||||
|
public static final int UC_RISCV_REG_X12 = 13;
|
||||||
|
public static final int UC_RISCV_REG_X13 = 14;
|
||||||
|
public static final int UC_RISCV_REG_X14 = 15;
|
||||||
|
public static final int UC_RISCV_REG_X15 = 16;
|
||||||
|
public static final int UC_RISCV_REG_X16 = 17;
|
||||||
|
public static final int UC_RISCV_REG_X17 = 18;
|
||||||
|
public static final int UC_RISCV_REG_X18 = 19;
|
||||||
|
public static final int UC_RISCV_REG_X19 = 20;
|
||||||
|
public static final int UC_RISCV_REG_X20 = 21;
|
||||||
|
public static final int UC_RISCV_REG_X21 = 22;
|
||||||
|
public static final int UC_RISCV_REG_X22 = 23;
|
||||||
|
public static final int UC_RISCV_REG_X23 = 24;
|
||||||
|
public static final int UC_RISCV_REG_X24 = 25;
|
||||||
|
public static final int UC_RISCV_REG_X25 = 26;
|
||||||
|
public static final int UC_RISCV_REG_X26 = 27;
|
||||||
|
public static final int UC_RISCV_REG_X27 = 28;
|
||||||
|
public static final int UC_RISCV_REG_X28 = 29;
|
||||||
|
public static final int UC_RISCV_REG_X29 = 30;
|
||||||
|
public static final int UC_RISCV_REG_X30 = 31;
|
||||||
|
public static final int UC_RISCV_REG_X31 = 32;
|
||||||
|
|
||||||
|
// Floating-point registers
|
||||||
|
public static final int UC_RISCV_REG_F0 = 33;
|
||||||
|
public static final int UC_RISCV_REG_F1 = 34;
|
||||||
|
public static final int UC_RISCV_REG_F2 = 35;
|
||||||
|
public static final int UC_RISCV_REG_F3 = 36;
|
||||||
|
public static final int UC_RISCV_REG_F4 = 37;
|
||||||
|
public static final int UC_RISCV_REG_F5 = 38;
|
||||||
|
public static final int UC_RISCV_REG_F6 = 39;
|
||||||
|
public static final int UC_RISCV_REG_F7 = 40;
|
||||||
|
public static final int UC_RISCV_REG_F8 = 41;
|
||||||
|
public static final int UC_RISCV_REG_F9 = 42;
|
||||||
|
public static final int UC_RISCV_REG_F10 = 43;
|
||||||
|
public static final int UC_RISCV_REG_F11 = 44;
|
||||||
|
public static final int UC_RISCV_REG_F12 = 45;
|
||||||
|
public static final int UC_RISCV_REG_F13 = 46;
|
||||||
|
public static final int UC_RISCV_REG_F14 = 47;
|
||||||
|
public static final int UC_RISCV_REG_F15 = 48;
|
||||||
|
public static final int UC_RISCV_REG_F16 = 49;
|
||||||
|
public static final int UC_RISCV_REG_F17 = 50;
|
||||||
|
public static final int UC_RISCV_REG_F18 = 51;
|
||||||
|
public static final int UC_RISCV_REG_F19 = 52;
|
||||||
|
public static final int UC_RISCV_REG_F20 = 53;
|
||||||
|
public static final int UC_RISCV_REG_F21 = 54;
|
||||||
|
public static final int UC_RISCV_REG_F22 = 55;
|
||||||
|
public static final int UC_RISCV_REG_F23 = 56;
|
||||||
|
public static final int UC_RISCV_REG_F24 = 57;
|
||||||
|
public static final int UC_RISCV_REG_F25 = 58;
|
||||||
|
public static final int UC_RISCV_REG_F26 = 59;
|
||||||
|
public static final int UC_RISCV_REG_F27 = 60;
|
||||||
|
public static final int UC_RISCV_REG_F28 = 61;
|
||||||
|
public static final int UC_RISCV_REG_F29 = 62;
|
||||||
|
public static final int UC_RISCV_REG_F30 = 63;
|
||||||
|
public static final int UC_RISCV_REG_F31 = 64;
|
||||||
|
public static final int UC_RISCV_REG_PC = 65;
|
||||||
|
public static final int UC_RISCV_REG_ENDING = 66;
|
||||||
|
|
||||||
|
// Alias registers
|
||||||
|
public static final int UC_RISCV_REG_ZERO = 1;
|
||||||
|
public static final int UC_RISCV_REG_RA = 2;
|
||||||
|
public static final int UC_RISCV_REG_SP = 3;
|
||||||
|
public static final int UC_RISCV_REG_GP = 4;
|
||||||
|
public static final int UC_RISCV_REG_TP = 5;
|
||||||
|
public static final int UC_RISCV_REG_T0 = 6;
|
||||||
|
public static final int UC_RISCV_REG_T1 = 7;
|
||||||
|
public static final int UC_RISCV_REG_T2 = 8;
|
||||||
|
public static final int UC_RISCV_REG_S0 = 9;
|
||||||
|
public static final int UC_RISCV_REG_FP = 9;
|
||||||
|
public static final int UC_RISCV_REG_S1 = 10;
|
||||||
|
public static final int UC_RISCV_REG_A0 = 11;
|
||||||
|
public static final int UC_RISCV_REG_A1 = 12;
|
||||||
|
public static final int UC_RISCV_REG_A2 = 13;
|
||||||
|
public static final int UC_RISCV_REG_A3 = 14;
|
||||||
|
public static final int UC_RISCV_REG_A4 = 15;
|
||||||
|
public static final int UC_RISCV_REG_A5 = 16;
|
||||||
|
public static final int UC_RISCV_REG_A6 = 17;
|
||||||
|
public static final int UC_RISCV_REG_A7 = 18;
|
||||||
|
public static final int UC_RISCV_REG_S2 = 19;
|
||||||
|
public static final int UC_RISCV_REG_S3 = 20;
|
||||||
|
public static final int UC_RISCV_REG_S4 = 21;
|
||||||
|
public static final int UC_RISCV_REG_S5 = 22;
|
||||||
|
public static final int UC_RISCV_REG_S6 = 23;
|
||||||
|
public static final int UC_RISCV_REG_S7 = 24;
|
||||||
|
public static final int UC_RISCV_REG_S8 = 25;
|
||||||
|
public static final int UC_RISCV_REG_S9 = 26;
|
||||||
|
public static final int UC_RISCV_REG_S10 = 27;
|
||||||
|
public static final int UC_RISCV_REG_S11 = 28;
|
||||||
|
public static final int UC_RISCV_REG_T3 = 29;
|
||||||
|
public static final int UC_RISCV_REG_T4 = 30;
|
||||||
|
public static final int UC_RISCV_REG_T5 = 31;
|
||||||
|
public static final int UC_RISCV_REG_T6 = 32;
|
||||||
|
public static final int UC_RISCV_REG_FT0 = 33;
|
||||||
|
public static final int UC_RISCV_REG_FT1 = 34;
|
||||||
|
public static final int UC_RISCV_REG_FT2 = 35;
|
||||||
|
public static final int UC_RISCV_REG_FT3 = 36;
|
||||||
|
public static final int UC_RISCV_REG_FT4 = 37;
|
||||||
|
public static final int UC_RISCV_REG_FT5 = 38;
|
||||||
|
public static final int UC_RISCV_REG_FT6 = 39;
|
||||||
|
public static final int UC_RISCV_REG_FT7 = 40;
|
||||||
|
public static final int UC_RISCV_REG_FS0 = 41;
|
||||||
|
public static final int UC_RISCV_REG_FS1 = 42;
|
||||||
|
public static final int UC_RISCV_REG_FA0 = 43;
|
||||||
|
public static final int UC_RISCV_REG_FA1 = 44;
|
||||||
|
public static final int UC_RISCV_REG_FA2 = 45;
|
||||||
|
public static final int UC_RISCV_REG_FA3 = 46;
|
||||||
|
public static final int UC_RISCV_REG_FA4 = 47;
|
||||||
|
public static final int UC_RISCV_REG_FA5 = 48;
|
||||||
|
public static final int UC_RISCV_REG_FA6 = 49;
|
||||||
|
public static final int UC_RISCV_REG_FA7 = 50;
|
||||||
|
public static final int UC_RISCV_REG_FS2 = 51;
|
||||||
|
public static final int UC_RISCV_REG_FS3 = 52;
|
||||||
|
public static final int UC_RISCV_REG_FS4 = 53;
|
||||||
|
public static final int UC_RISCV_REG_FS5 = 54;
|
||||||
|
public static final int UC_RISCV_REG_FS6 = 55;
|
||||||
|
public static final int UC_RISCV_REG_FS7 = 56;
|
||||||
|
public static final int UC_RISCV_REG_FS8 = 57;
|
||||||
|
public static final int UC_RISCV_REG_FS9 = 58;
|
||||||
|
public static final int UC_RISCV_REG_FS10 = 59;
|
||||||
|
public static final int UC_RISCV_REG_FS11 = 60;
|
||||||
|
public static final int UC_RISCV_REG_FT8 = 61;
|
||||||
|
public static final int UC_RISCV_REG_FT9 = 62;
|
||||||
|
public static final int UC_RISCV_REG_FT10 = 63;
|
||||||
|
public static final int UC_RISCV_REG_FT11 = 64;
|
||||||
|
|
||||||
|
}
|
|
@ -3,13 +3,14 @@
|
||||||
package unicorn;
|
package unicorn;
|
||||||
|
|
||||||
public interface UnicornConst {
|
public interface UnicornConst {
|
||||||
public static final int UC_API_MAJOR = 1;
|
public static final int UC_API_MAJOR = 2;
|
||||||
|
|
||||||
public static final int UC_API_MINOR = 0;
|
public static final int UC_API_MINOR = 0;
|
||||||
public static final int UC_VERSION_MAJOR = 1;
|
public static final int UC_VERSION_MAJOR = 2;
|
||||||
|
|
||||||
public static final int UC_VERSION_MINOR = 0;
|
public static final int UC_VERSION_MINOR = 0;
|
||||||
public static final int UC_VERSION_EXTRA = 3;
|
|
||||||
|
public static final int UC_VERSION_EXTRA = 0;
|
||||||
public static final int UC_SECOND_SCALE = 1000000;
|
public static final int UC_SECOND_SCALE = 1000000;
|
||||||
public static final int UC_MILISECOND_SCALE = 1000;
|
public static final int UC_MILISECOND_SCALE = 1000;
|
||||||
public static final int UC_ARCH_ARM = 1;
|
public static final int UC_ARCH_ARM = 1;
|
||||||
|
@ -19,7 +20,8 @@ public interface UnicornConst {
|
||||||
public static final int UC_ARCH_PPC = 5;
|
public static final int UC_ARCH_PPC = 5;
|
||||||
public static final int UC_ARCH_SPARC = 6;
|
public static final int UC_ARCH_SPARC = 6;
|
||||||
public static final int UC_ARCH_M68K = 7;
|
public static final int UC_ARCH_M68K = 7;
|
||||||
public static final int UC_ARCH_MAX = 8;
|
public static final int UC_ARCH_RISCV = 8;
|
||||||
|
public static final int UC_ARCH_MAX = 9;
|
||||||
|
|
||||||
public static final int UC_MODE_LITTLE_ENDIAN = 0;
|
public static final int UC_MODE_LITTLE_ENDIAN = 0;
|
||||||
public static final int UC_MODE_BIG_ENDIAN = 1073741824;
|
public static final int UC_MODE_BIG_ENDIAN = 1073741824;
|
||||||
|
@ -31,7 +33,6 @@ public interface UnicornConst {
|
||||||
public static final int UC_MODE_ARM926 = 128;
|
public static final int UC_MODE_ARM926 = 128;
|
||||||
public static final int UC_MODE_ARM946 = 256;
|
public static final int UC_MODE_ARM946 = 256;
|
||||||
public static final int UC_MODE_ARM1176 = 512;
|
public static final int UC_MODE_ARM1176 = 512;
|
||||||
public static final int UC_MODE_ARMBE8 = 1024;
|
|
||||||
public static final int UC_MODE_MICRO = 16;
|
public static final int UC_MODE_MICRO = 16;
|
||||||
public static final int UC_MODE_MIPS3 = 32;
|
public static final int UC_MODE_MIPS3 = 32;
|
||||||
public static final int UC_MODE_MIPS32R6 = 64;
|
public static final int UC_MODE_MIPS32R6 = 64;
|
||||||
|
@ -46,6 +47,8 @@ public interface UnicornConst {
|
||||||
public static final int UC_MODE_SPARC32 = 4;
|
public static final int UC_MODE_SPARC32 = 4;
|
||||||
public static final int UC_MODE_SPARC64 = 8;
|
public static final int UC_MODE_SPARC64 = 8;
|
||||||
public static final int UC_MODE_V9 = 16;
|
public static final int UC_MODE_V9 = 16;
|
||||||
|
public static final int UC_MODE_RISCV32 = 4;
|
||||||
|
public static final int UC_MODE_RISCV64 = 8;
|
||||||
|
|
||||||
public static final int UC_ERR_OK = 0;
|
public static final int UC_ERR_OK = 0;
|
||||||
public static final int UC_ERR_NOMEM = 1;
|
public static final int UC_ERR_NOMEM = 1;
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
|
unit PpcConst;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
const
|
||||||
|
// PPC registers
|
||||||
|
|
||||||
|
UC_PPC_REG_INVALID = 0;
|
||||||
|
|
||||||
|
// General purpose registers
|
||||||
|
UC_PPC_REG_PC = 1;
|
||||||
|
UC_PPC_REG_0 = 2;
|
||||||
|
UC_PPC_REG_1 = 3;
|
||||||
|
UC_PPC_REG_2 = 4;
|
||||||
|
UC_PPC_REG_3 = 5;
|
||||||
|
UC_PPC_REG_4 = 6;
|
||||||
|
UC_PPC_REG_5 = 7;
|
||||||
|
UC_PPC_REG_6 = 8;
|
||||||
|
UC_PPC_REG_7 = 9;
|
||||||
|
UC_PPC_REG_8 = 10;
|
||||||
|
UC_PPC_REG_9 = 11;
|
||||||
|
UC_PPC_REG_10 = 12;
|
||||||
|
UC_PPC_REG_11 = 13;
|
||||||
|
UC_PPC_REG_12 = 14;
|
||||||
|
UC_PPC_REG_13 = 15;
|
||||||
|
UC_PPC_REG_14 = 16;
|
||||||
|
UC_PPC_REG_15 = 17;
|
||||||
|
UC_PPC_REG_16 = 18;
|
||||||
|
UC_PPC_REG_17 = 19;
|
||||||
|
UC_PPC_REG_18 = 20;
|
||||||
|
UC_PPC_REG_19 = 21;
|
||||||
|
UC_PPC_REG_20 = 22;
|
||||||
|
UC_PPC_REG_21 = 23;
|
||||||
|
UC_PPC_REG_22 = 24;
|
||||||
|
UC_PPC_REG_23 = 25;
|
||||||
|
UC_PPC_REG_24 = 26;
|
||||||
|
UC_PPC_REG_25 = 27;
|
||||||
|
UC_PPC_REG_26 = 28;
|
||||||
|
UC_PPC_REG_27 = 29;
|
||||||
|
UC_PPC_REG_28 = 30;
|
||||||
|
UC_PPC_REG_29 = 31;
|
||||||
|
UC_PPC_REG_30 = 32;
|
||||||
|
UC_PPC_REG_31 = 33;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
end.
|
|
@ -0,0 +1,150 @@
|
||||||
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
|
unit RiscvConst;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
const
|
||||||
|
// RISCV registers
|
||||||
|
|
||||||
|
UC_RISCV_REG_INVALID = 0;
|
||||||
|
|
||||||
|
// General purpose registers
|
||||||
|
UC_RISCV_REG_X0 = 1;
|
||||||
|
UC_RISCV_REG_X1 = 2;
|
||||||
|
UC_RISCV_REG_X2 = 3;
|
||||||
|
UC_RISCV_REG_X3 = 4;
|
||||||
|
UC_RISCV_REG_X4 = 5;
|
||||||
|
UC_RISCV_REG_X5 = 6;
|
||||||
|
UC_RISCV_REG_X6 = 7;
|
||||||
|
UC_RISCV_REG_X7 = 8;
|
||||||
|
UC_RISCV_REG_X8 = 9;
|
||||||
|
UC_RISCV_REG_X9 = 10;
|
||||||
|
UC_RISCV_REG_X10 = 11;
|
||||||
|
UC_RISCV_REG_X11 = 12;
|
||||||
|
UC_RISCV_REG_X12 = 13;
|
||||||
|
UC_RISCV_REG_X13 = 14;
|
||||||
|
UC_RISCV_REG_X14 = 15;
|
||||||
|
UC_RISCV_REG_X15 = 16;
|
||||||
|
UC_RISCV_REG_X16 = 17;
|
||||||
|
UC_RISCV_REG_X17 = 18;
|
||||||
|
UC_RISCV_REG_X18 = 19;
|
||||||
|
UC_RISCV_REG_X19 = 20;
|
||||||
|
UC_RISCV_REG_X20 = 21;
|
||||||
|
UC_RISCV_REG_X21 = 22;
|
||||||
|
UC_RISCV_REG_X22 = 23;
|
||||||
|
UC_RISCV_REG_X23 = 24;
|
||||||
|
UC_RISCV_REG_X24 = 25;
|
||||||
|
UC_RISCV_REG_X25 = 26;
|
||||||
|
UC_RISCV_REG_X26 = 27;
|
||||||
|
UC_RISCV_REG_X27 = 28;
|
||||||
|
UC_RISCV_REG_X28 = 29;
|
||||||
|
UC_RISCV_REG_X29 = 30;
|
||||||
|
UC_RISCV_REG_X30 = 31;
|
||||||
|
UC_RISCV_REG_X31 = 32;
|
||||||
|
|
||||||
|
// Floating-point registers
|
||||||
|
UC_RISCV_REG_F0 = 33;
|
||||||
|
UC_RISCV_REG_F1 = 34;
|
||||||
|
UC_RISCV_REG_F2 = 35;
|
||||||
|
UC_RISCV_REG_F3 = 36;
|
||||||
|
UC_RISCV_REG_F4 = 37;
|
||||||
|
UC_RISCV_REG_F5 = 38;
|
||||||
|
UC_RISCV_REG_F6 = 39;
|
||||||
|
UC_RISCV_REG_F7 = 40;
|
||||||
|
UC_RISCV_REG_F8 = 41;
|
||||||
|
UC_RISCV_REG_F9 = 42;
|
||||||
|
UC_RISCV_REG_F10 = 43;
|
||||||
|
UC_RISCV_REG_F11 = 44;
|
||||||
|
UC_RISCV_REG_F12 = 45;
|
||||||
|
UC_RISCV_REG_F13 = 46;
|
||||||
|
UC_RISCV_REG_F14 = 47;
|
||||||
|
UC_RISCV_REG_F15 = 48;
|
||||||
|
UC_RISCV_REG_F16 = 49;
|
||||||
|
UC_RISCV_REG_F17 = 50;
|
||||||
|
UC_RISCV_REG_F18 = 51;
|
||||||
|
UC_RISCV_REG_F19 = 52;
|
||||||
|
UC_RISCV_REG_F20 = 53;
|
||||||
|
UC_RISCV_REG_F21 = 54;
|
||||||
|
UC_RISCV_REG_F22 = 55;
|
||||||
|
UC_RISCV_REG_F23 = 56;
|
||||||
|
UC_RISCV_REG_F24 = 57;
|
||||||
|
UC_RISCV_REG_F25 = 58;
|
||||||
|
UC_RISCV_REG_F26 = 59;
|
||||||
|
UC_RISCV_REG_F27 = 60;
|
||||||
|
UC_RISCV_REG_F28 = 61;
|
||||||
|
UC_RISCV_REG_F29 = 62;
|
||||||
|
UC_RISCV_REG_F30 = 63;
|
||||||
|
UC_RISCV_REG_F31 = 64;
|
||||||
|
UC_RISCV_REG_PC = 65;
|
||||||
|
UC_RISCV_REG_ENDING = 66;
|
||||||
|
|
||||||
|
// Alias registers
|
||||||
|
UC_RISCV_REG_ZERO = 1;
|
||||||
|
UC_RISCV_REG_RA = 2;
|
||||||
|
UC_RISCV_REG_SP = 3;
|
||||||
|
UC_RISCV_REG_GP = 4;
|
||||||
|
UC_RISCV_REG_TP = 5;
|
||||||
|
UC_RISCV_REG_T0 = 6;
|
||||||
|
UC_RISCV_REG_T1 = 7;
|
||||||
|
UC_RISCV_REG_T2 = 8;
|
||||||
|
UC_RISCV_REG_S0 = 9;
|
||||||
|
UC_RISCV_REG_FP = 9;
|
||||||
|
UC_RISCV_REG_S1 = 10;
|
||||||
|
UC_RISCV_REG_A0 = 11;
|
||||||
|
UC_RISCV_REG_A1 = 12;
|
||||||
|
UC_RISCV_REG_A2 = 13;
|
||||||
|
UC_RISCV_REG_A3 = 14;
|
||||||
|
UC_RISCV_REG_A4 = 15;
|
||||||
|
UC_RISCV_REG_A5 = 16;
|
||||||
|
UC_RISCV_REG_A6 = 17;
|
||||||
|
UC_RISCV_REG_A7 = 18;
|
||||||
|
UC_RISCV_REG_S2 = 19;
|
||||||
|
UC_RISCV_REG_S3 = 20;
|
||||||
|
UC_RISCV_REG_S4 = 21;
|
||||||
|
UC_RISCV_REG_S5 = 22;
|
||||||
|
UC_RISCV_REG_S6 = 23;
|
||||||
|
UC_RISCV_REG_S7 = 24;
|
||||||
|
UC_RISCV_REG_S8 = 25;
|
||||||
|
UC_RISCV_REG_S9 = 26;
|
||||||
|
UC_RISCV_REG_S10 = 27;
|
||||||
|
UC_RISCV_REG_S11 = 28;
|
||||||
|
UC_RISCV_REG_T3 = 29;
|
||||||
|
UC_RISCV_REG_T4 = 30;
|
||||||
|
UC_RISCV_REG_T5 = 31;
|
||||||
|
UC_RISCV_REG_T6 = 32;
|
||||||
|
UC_RISCV_REG_FT0 = 33;
|
||||||
|
UC_RISCV_REG_FT1 = 34;
|
||||||
|
UC_RISCV_REG_FT2 = 35;
|
||||||
|
UC_RISCV_REG_FT3 = 36;
|
||||||
|
UC_RISCV_REG_FT4 = 37;
|
||||||
|
UC_RISCV_REG_FT5 = 38;
|
||||||
|
UC_RISCV_REG_FT6 = 39;
|
||||||
|
UC_RISCV_REG_FT7 = 40;
|
||||||
|
UC_RISCV_REG_FS0 = 41;
|
||||||
|
UC_RISCV_REG_FS1 = 42;
|
||||||
|
UC_RISCV_REG_FA0 = 43;
|
||||||
|
UC_RISCV_REG_FA1 = 44;
|
||||||
|
UC_RISCV_REG_FA2 = 45;
|
||||||
|
UC_RISCV_REG_FA3 = 46;
|
||||||
|
UC_RISCV_REG_FA4 = 47;
|
||||||
|
UC_RISCV_REG_FA5 = 48;
|
||||||
|
UC_RISCV_REG_FA6 = 49;
|
||||||
|
UC_RISCV_REG_FA7 = 50;
|
||||||
|
UC_RISCV_REG_FS2 = 51;
|
||||||
|
UC_RISCV_REG_FS3 = 52;
|
||||||
|
UC_RISCV_REG_FS4 = 53;
|
||||||
|
UC_RISCV_REG_FS5 = 54;
|
||||||
|
UC_RISCV_REG_FS6 = 55;
|
||||||
|
UC_RISCV_REG_FS7 = 56;
|
||||||
|
UC_RISCV_REG_FS8 = 57;
|
||||||
|
UC_RISCV_REG_FS9 = 58;
|
||||||
|
UC_RISCV_REG_FS10 = 59;
|
||||||
|
UC_RISCV_REG_FS11 = 60;
|
||||||
|
UC_RISCV_REG_FT8 = 61;
|
||||||
|
UC_RISCV_REG_FT9 = 62;
|
||||||
|
UC_RISCV_REG_FT10 = 63;
|
||||||
|
UC_RISCV_REG_FT11 = 64;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
end.
|
|
@ -4,13 +4,14 @@ unit UnicornConst;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
const UC_API_MAJOR = 1;
|
const UC_API_MAJOR = 2;
|
||||||
|
|
||||||
UC_API_MINOR = 0;
|
UC_API_MINOR = 0;
|
||||||
UC_VERSION_MAJOR = 1;
|
UC_VERSION_MAJOR = 2;
|
||||||
|
|
||||||
UC_VERSION_MINOR = 0;
|
UC_VERSION_MINOR = 0;
|
||||||
UC_VERSION_EXTRA = 3;
|
|
||||||
|
UC_VERSION_EXTRA = 0;
|
||||||
UC_SECOND_SCALE = 1000000;
|
UC_SECOND_SCALE = 1000000;
|
||||||
UC_MILISECOND_SCALE = 1000;
|
UC_MILISECOND_SCALE = 1000;
|
||||||
UC_ARCH_ARM = 1;
|
UC_ARCH_ARM = 1;
|
||||||
|
@ -20,7 +21,8 @@ const UC_API_MAJOR = 1;
|
||||||
UC_ARCH_PPC = 5;
|
UC_ARCH_PPC = 5;
|
||||||
UC_ARCH_SPARC = 6;
|
UC_ARCH_SPARC = 6;
|
||||||
UC_ARCH_M68K = 7;
|
UC_ARCH_M68K = 7;
|
||||||
UC_ARCH_MAX = 8;
|
UC_ARCH_RISCV = 8;
|
||||||
|
UC_ARCH_MAX = 9;
|
||||||
|
|
||||||
UC_MODE_LITTLE_ENDIAN = 0;
|
UC_MODE_LITTLE_ENDIAN = 0;
|
||||||
UC_MODE_BIG_ENDIAN = 1073741824;
|
UC_MODE_BIG_ENDIAN = 1073741824;
|
||||||
|
@ -32,7 +34,6 @@ const UC_API_MAJOR = 1;
|
||||||
UC_MODE_ARM926 = 128;
|
UC_MODE_ARM926 = 128;
|
||||||
UC_MODE_ARM946 = 256;
|
UC_MODE_ARM946 = 256;
|
||||||
UC_MODE_ARM1176 = 512;
|
UC_MODE_ARM1176 = 512;
|
||||||
UC_MODE_ARMBE8 = 1024;
|
|
||||||
UC_MODE_MICRO = 16;
|
UC_MODE_MICRO = 16;
|
||||||
UC_MODE_MIPS3 = 32;
|
UC_MODE_MIPS3 = 32;
|
||||||
UC_MODE_MIPS32R6 = 64;
|
UC_MODE_MIPS32R6 = 64;
|
||||||
|
@ -47,6 +48,8 @@ const UC_API_MAJOR = 1;
|
||||||
UC_MODE_SPARC32 = 4;
|
UC_MODE_SPARC32 = 4;
|
||||||
UC_MODE_SPARC64 = 8;
|
UC_MODE_SPARC64 = 8;
|
||||||
UC_MODE_V9 = 16;
|
UC_MODE_V9 = 16;
|
||||||
|
UC_MODE_RISCV32 = 4;
|
||||||
|
UC_MODE_RISCV64 = 8;
|
||||||
|
|
||||||
UC_ERR_OK = 0;
|
UC_ERR_OK = 0;
|
||||||
UC_ERR_NOMEM = 1;
|
UC_ERR_NOMEM = 1;
|
||||||
|
|
|
@ -108,7 +108,7 @@ type
|
||||||
@user_data: user data passed to tracing APIs
|
@user_data: user data passed to tracing APIs
|
||||||
|
|
||||||
@return: return true to continue, or false to stop program (due to invalid memory).
|
@return: return true to continue, or false to stop program (due to invalid memory).
|
||||||
NOTE: returning true to continue execution will only work if the accessed
|
NOTE: returning true to continue execution will only work if if the accessed
|
||||||
memory is made accessible with the correct permissions during the hook.
|
memory is made accessible with the correct permissions during the hook.
|
||||||
|
|
||||||
In the event of a UC_MEM_READ_UNMAPPED or UC_MEM_WRITE_UNMAPPED callback,
|
In the event of a UC_MEM_READ_UNMAPPED or UC_MEM_WRITE_UNMAPPED callback,
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -e -x
|
|
||||||
|
|
||||||
cd bindings/python
|
|
||||||
|
|
||||||
# Compile wheels
|
|
||||||
if [ -f /opt/python/cp36-cp36m/bin/python ];then
|
|
||||||
/opt/python/cp36-cp36m/bin/python setup.py bdist_wheel
|
|
||||||
else
|
|
||||||
python3 setup.py bdist_wheel
|
|
||||||
fi
|
|
||||||
cd dist
|
|
||||||
auditwheel repair *.whl
|
|
||||||
mv -f wheelhouse/*.whl .
|
|
|
@ -45,7 +45,7 @@ def test_arm64():
|
||||||
# tracing all basic blocks with customized callback
|
# tracing all basic blocks with customized callback
|
||||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||||
|
|
||||||
# tracing one instruction at ADDRESS with customized callback
|
# tracing one instruction with customized callback
|
||||||
mu.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS)
|
mu.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS)
|
||||||
|
|
||||||
# emulate machine code in infinite time
|
# emulate machine code in infinite time
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/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 *
|
||||||
|
|
||||||
|
|
||||||
|
# code to be emulated
|
||||||
|
PPC_CODE = b"\x7F\x46\x1A\x14" # add r26, r6, r3
|
||||||
|
# memory address where emulation starts
|
||||||
|
ADDRESS = 0x10000
|
||||||
|
|
||||||
|
|
||||||
|
# callback for tracing basic blocks
|
||||||
|
def hook_block(uc, address, size, user_data):
|
||||||
|
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||||
|
|
||||||
|
|
||||||
|
# callback for tracing instructions
|
||||||
|
def hook_code(uc, address, size, user_data):
|
||||||
|
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
|
||||||
|
|
||||||
|
|
||||||
|
# Test PPC
|
||||||
|
def test_ppc():
|
||||||
|
print("Emulate PPC code")
|
||||||
|
try:
|
||||||
|
# Initialize emulator in PPC EB mode
|
||||||
|
mu = Uc(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN)
|
||||||
|
|
||||||
|
# map 2MB memory for this emulation
|
||||||
|
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||||
|
|
||||||
|
# write machine code to be emulated to memory
|
||||||
|
mu.mem_write(ADDRESS, PPC_CODE)
|
||||||
|
|
||||||
|
# initialize machine registers
|
||||||
|
mu.reg_write(UC_PPC_REG_3, 0x1234)
|
||||||
|
mu.reg_write(UC_PPC_REG_6, 0x6789)
|
||||||
|
mu.reg_write(UC_PPC_REG_26, 0x5555)
|
||||||
|
|
||||||
|
# tracing all basic blocks with customized callback
|
||||||
|
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||||
|
|
||||||
|
# tracing all instructions with customized callback
|
||||||
|
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||||
|
|
||||||
|
# emulate machine code in infinite time
|
||||||
|
mu.emu_start(ADDRESS, ADDRESS + len(PPC_CODE))
|
||||||
|
|
||||||
|
# now print out some registers
|
||||||
|
print(">>> Emulation done. Below is the CPU context")
|
||||||
|
|
||||||
|
r26 = mu.reg_read(UC_PPC_REG_26)
|
||||||
|
print(">>> r26 = 0x%x" % r26)
|
||||||
|
|
||||||
|
except UcError as e:
|
||||||
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_ppc()
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
#!/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 *
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
$ cstool riscv64 1305100093850502
|
||||||
|
0 13 05 10 00 addi a0, zero, 1
|
||||||
|
4 93 85 05 02 addi a1, a1, 0x20
|
||||||
|
'''
|
||||||
|
RISCV_CODE = b"\x13\x05\x10\x00\x93\x85\x05\x02"
|
||||||
|
|
||||||
|
# memory address where emulation starts
|
||||||
|
ADDRESS = 0x10000
|
||||||
|
|
||||||
|
|
||||||
|
# callback for tracing basic blocks
|
||||||
|
def hook_block(uc, address, size, user_data):
|
||||||
|
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||||
|
|
||||||
|
|
||||||
|
# callback for tracing instructions
|
||||||
|
def hook_code(uc, address, size, user_data):
|
||||||
|
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
|
||||||
|
|
||||||
|
|
||||||
|
# Test RISCV
|
||||||
|
def test_riscv():
|
||||||
|
print("Emulate RISCV code")
|
||||||
|
try:
|
||||||
|
# Initialize emulator in RISCV32 mode
|
||||||
|
mu = Uc(UC_ARCH_RISCV, UC_MODE_RISCV32)
|
||||||
|
|
||||||
|
# map 2MB memory for this emulation
|
||||||
|
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||||
|
|
||||||
|
# write machine code to be emulated to memory
|
||||||
|
mu.mem_write(ADDRESS, RISCV_CODE)
|
||||||
|
|
||||||
|
# initialize machine registers
|
||||||
|
mu.reg_write(UC_RISCV_REG_A0, 0x1234)
|
||||||
|
mu.reg_write(UC_RISCV_REG_A1, 0x7890)
|
||||||
|
|
||||||
|
# tracing all basic blocks with customized callback
|
||||||
|
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||||
|
|
||||||
|
# tracing all instructions with customized callback
|
||||||
|
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||||
|
|
||||||
|
# emulate machine code in infinite time
|
||||||
|
mu.emu_start(ADDRESS, ADDRESS + len(RISCV_CODE))
|
||||||
|
|
||||||
|
# now print out some registers
|
||||||
|
print(">>> Emulation done. Below is the CPU context")
|
||||||
|
|
||||||
|
a0 = mu.reg_read(UC_RISCV_REG_A0)
|
||||||
|
a1 = mu.reg_read(UC_RISCV_REG_A1)
|
||||||
|
print(">>> A0 = 0x%x" %a0)
|
||||||
|
print(">>> A1 = 0x%x" %a1)
|
||||||
|
|
||||||
|
except UcError as e:
|
||||||
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_riscv()
|
||||||
|
|
|
@ -16,6 +16,7 @@ X86_CODE64 = b"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\
|
||||||
X86_CODE32_INOUT = b"\x41\xE4\x3F\x4a\xE6\x46\x43" # INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
|
X86_CODE32_INOUT = b"\x41\xE4\x3F\x4a\xE6\x46\x43" # INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
|
||||||
X86_CODE64_SYSCALL = b'\x0f\x05' # SYSCALL
|
X86_CODE64_SYSCALL = b'\x0f\x05' # SYSCALL
|
||||||
X86_CODE16 = b'\x00\x00' # add byte ptr [bx + si], al
|
X86_CODE16 = b'\x00\x00' # add byte ptr [bx + si], al
|
||||||
|
X86_MMIO_CODE = b"\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00" # mov [0x20004], ecx; mov ecx, [0x20004]
|
||||||
|
|
||||||
# memory address where emulation starts
|
# memory address where emulation starts
|
||||||
ADDRESS = 0x1000000
|
ADDRESS = 0x1000000
|
||||||
|
@ -386,7 +387,6 @@ def test_i386_loop():
|
||||||
except UcError as e:
|
except UcError as e:
|
||||||
print("ERROR: %s" % e)
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
# Test X86 32 bit with IN/OUT instruction
|
# Test X86 32 bit with IN/OUT instruction
|
||||||
def test_i386_inout():
|
def test_i386_inout():
|
||||||
print("Emulate i386 code with IN/OUT instructions")
|
print("Emulate i386 code with IN/OUT instructions")
|
||||||
|
@ -464,6 +464,9 @@ def test_i386_context_save():
|
||||||
print(">>> Unpickling CPU context")
|
print(">>> Unpickling CPU context")
|
||||||
saved_context = pickle.loads(pickled_saved_context)
|
saved_context = pickle.loads(pickled_saved_context)
|
||||||
|
|
||||||
|
print(">>> Modifying some register.")
|
||||||
|
saved_context.reg_write(UC_X86_REG_EAX, 0xc8c8)
|
||||||
|
|
||||||
print(">>> CPU context restored. Below is the CPU context")
|
print(">>> CPU context restored. Below is the CPU context")
|
||||||
mu.context_restore(saved_context)
|
mu.context_restore(saved_context)
|
||||||
print(">>> EAX = 0x%x" %(mu.reg_read(UC_X86_REG_EAX)))
|
print(">>> EAX = 0x%x" %(mu.reg_read(UC_X86_REG_EAX)))
|
||||||
|
@ -628,6 +631,38 @@ def test_x86_16():
|
||||||
except UcError as e:
|
except UcError as e:
|
||||||
print("ERROR: %s" % e)
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
|
def mmio_read_cb(uc, offset, size, data):
|
||||||
|
print(f">>> Read IO memory at offset {hex(offset)} with {hex(size)} bytes and return 0x19260817")
|
||||||
|
|
||||||
|
return 0x19260817
|
||||||
|
|
||||||
|
def mmio_write_cb(uc, offset, size, value, data):
|
||||||
|
print(f">>> Write value {hex(value)} to IO memory at offset {hex(offset)} with {hex(size)} bytes")
|
||||||
|
|
||||||
|
def test_i386_mmio():
|
||||||
|
print("Test i386 IO memory")
|
||||||
|
try:
|
||||||
|
# Initialize emulator in X86-32bit mode
|
||||||
|
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||||
|
|
||||||
|
# map 8KB memory for this emulation and write the code
|
||||||
|
mu.mem_map(0x10000, 0x8000)
|
||||||
|
mu.mem_write(0x10000, X86_MMIO_CODE)
|
||||||
|
|
||||||
|
# map the IO memory
|
||||||
|
mu.mmio_map(0x20000, 0x4000, mmio_read_cb, None, mmio_write_cb, None)
|
||||||
|
|
||||||
|
# prepare registers.
|
||||||
|
mu.reg_write(UC_X86_REG_ECX, 0xdeadbeef)
|
||||||
|
|
||||||
|
# emulate machine code in infinite time
|
||||||
|
mu.emu_start(0x10000, 0x10000 + len(X86_MMIO_CODE))
|
||||||
|
|
||||||
|
# now print out some registers
|
||||||
|
print(f">>> Emulation done. ECX={hex(mu.reg_read(UC_X86_REG_ECX))}")
|
||||||
|
|
||||||
|
except UcError as e:
|
||||||
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_x86_16()
|
test_x86_16()
|
||||||
|
@ -651,3 +686,5 @@ if __name__ == '__main__':
|
||||||
test_x86_64()
|
test_x86_64()
|
||||||
print("=" * 35)
|
print("=" * 35)
|
||||||
test_x86_64_syscall()
|
test_x86_64_syscall()
|
||||||
|
print("=" * 35)
|
||||||
|
test_i386_mmio()
|
||||||
|
|
|
@ -15,7 +15,6 @@ from distutils.util import get_platform
|
||||||
from distutils.command.build import build
|
from distutils.command.build import build
|
||||||
from distutils.command.sdist import sdist
|
from distutils.command.sdist import sdist
|
||||||
from setuptools.command.bdist_egg import bdist_egg
|
from setuptools.command.bdist_egg import bdist_egg
|
||||||
from setuptools.command.develop import develop
|
|
||||||
|
|
||||||
SYSTEM = sys.platform
|
SYSTEM = sys.platform
|
||||||
|
|
||||||
|
@ -23,36 +22,18 @@ SYSTEM = sys.platform
|
||||||
IS_64BITS = platform.architecture()[0] == '64bit'
|
IS_64BITS = platform.architecture()[0] == '64bit'
|
||||||
|
|
||||||
# are we building from the repository or from a source distribution?
|
# are we building from the repository or from a source distribution?
|
||||||
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||||
LIBS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'lib')
|
LIBS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'lib')
|
||||||
HEADERS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'include')
|
HEADERS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'include')
|
||||||
SRC_DIR = os.path.join(ROOT_DIR, 'src')
|
SRC_DIR = os.path.join(ROOT_DIR, 'src')
|
||||||
BUILD_DIR = SRC_DIR if os.path.exists(SRC_DIR) else os.path.join(ROOT_DIR, '../..')
|
UC_DIR = os.path.join(ROOT_DIR, '../..')
|
||||||
|
BUILD_DIR = os.path.join(UC_DIR, 'build')
|
||||||
|
|
||||||
# Parse version from pkgconfig.mk
|
|
||||||
VERSION_DATA = {}
|
VERSION_DATA = {}
|
||||||
with open(os.path.join(BUILD_DIR, 'pkgconfig.mk')) as fp:
|
VERSION_DATA['PKG_MAJOR'] = "2"
|
||||||
lines = fp.readlines()
|
VERSION_DATA['PKG_MINOR'] = "0"
|
||||||
for line in lines:
|
VERSION_DATA['PKG_EXTRA'] = "0"
|
||||||
line = line.strip()
|
# VERSION_DATA['PKG_TAG'] = "0"
|
||||||
if len(line) == 0:
|
|
||||||
continue
|
|
||||||
if line.startswith('#'):
|
|
||||||
continue
|
|
||||||
if '=' not in line:
|
|
||||||
continue
|
|
||||||
|
|
||||||
k, v = line.split('=', 1)
|
|
||||||
k = k.strip()
|
|
||||||
v = v.strip()
|
|
||||||
if len(k) == 0 or len(v) == 0:
|
|
||||||
continue
|
|
||||||
VERSION_DATA[k] = v
|
|
||||||
|
|
||||||
if 'PKG_MAJOR' not in VERSION_DATA or \
|
|
||||||
'PKG_MINOR' not in VERSION_DATA or \
|
|
||||||
'PKG_EXTRA' not in VERSION_DATA:
|
|
||||||
raise Exception("Malformed pkgconfig.mk")
|
|
||||||
|
|
||||||
if 'PKG_TAG' in VERSION_DATA:
|
if 'PKG_TAG' in VERSION_DATA:
|
||||||
VERSION = '{PKG_MAJOR}.{PKG_MINOR}.{PKG_EXTRA}.{PKG_TAG}'.format(**VERSION_DATA)
|
VERSION = '{PKG_MAJOR}.{PKG_MINOR}.{PKG_EXTRA}.{PKG_TAG}'.format(**VERSION_DATA)
|
||||||
|
@ -63,12 +44,9 @@ if SYSTEM == 'darwin':
|
||||||
LIBRARY_FILE = "libunicorn.dylib"
|
LIBRARY_FILE = "libunicorn.dylib"
|
||||||
MAC_LIBRARY_FILE = "libunicorn*.dylib"
|
MAC_LIBRARY_FILE = "libunicorn*.dylib"
|
||||||
STATIC_LIBRARY_FILE = None
|
STATIC_LIBRARY_FILE = None
|
||||||
elif SYSTEM == 'win32':
|
elif SYSTEM in ('win32', 'cygwin'):
|
||||||
LIBRARY_FILE = "unicorn.dll"
|
LIBRARY_FILE = "unicorn.dll"
|
||||||
STATIC_LIBRARY_FILE = "unicorn.lib"
|
STATIC_LIBRARY_FILE = "unicorn.lib"
|
||||||
elif SYSTEM == 'cygwin':
|
|
||||||
LIBRARY_FILE = "cygunicorn.dll"
|
|
||||||
STATIC_LIBRARY_FILE = None
|
|
||||||
else:
|
else:
|
||||||
LIBRARY_FILE = "libunicorn.so"
|
LIBRARY_FILE = "libunicorn.so"
|
||||||
STATIC_LIBRARY_FILE = None
|
STATIC_LIBRARY_FILE = None
|
||||||
|
@ -84,7 +62,6 @@ def copy_sources():
|
||||||
"""
|
"""
|
||||||
src = []
|
src = []
|
||||||
|
|
||||||
os.system('make -C %s clean' % os.path.join(ROOT_DIR, '../..'))
|
|
||||||
shutil.rmtree(SRC_DIR, ignore_errors=True)
|
shutil.rmtree(SRC_DIR, ignore_errors=True)
|
||||||
os.mkdir(SRC_DIR)
|
os.mkdir(SRC_DIR)
|
||||||
|
|
||||||
|
@ -108,9 +85,8 @@ def copy_sources():
|
||||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../README.md")))
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../README.md")))
|
||||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.TXT")))
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.TXT")))
|
||||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../RELEASE_NOTES")))
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../RELEASE_NOTES")))
|
||||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../make.sh")))
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../cmake.sh")))
|
||||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../CMakeLists.txt")))
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../CMakeLists.txt")))
|
||||||
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../pkgconfig.mk")))
|
|
||||||
|
|
||||||
for filename in src:
|
for filename in src:
|
||||||
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
|
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
|
||||||
|
@ -130,7 +106,7 @@ def build_libraries():
|
||||||
os.mkdir(LIBS_DIR)
|
os.mkdir(LIBS_DIR)
|
||||||
|
|
||||||
# copy public headers
|
# copy public headers
|
||||||
shutil.copytree(os.path.join(BUILD_DIR, 'include', 'unicorn'), os.path.join(HEADERS_DIR, 'unicorn'))
|
shutil.copytree(os.path.join(UC_DIR, 'include', 'unicorn'), os.path.join(HEADERS_DIR, 'unicorn'))
|
||||||
|
|
||||||
# check if a prebuilt library exists
|
# check if a prebuilt library exists
|
||||||
# if so, use it instead of building
|
# if so, use it instead of building
|
||||||
|
@ -141,35 +117,37 @@ def build_libraries():
|
||||||
return
|
return
|
||||||
|
|
||||||
# otherwise, build!!
|
# otherwise, build!!
|
||||||
os.chdir(BUILD_DIR)
|
os.chdir(UC_DIR)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subprocess.check_call(['msbuild', '-ver'])
|
subprocess.check_call(['msbuild', '/help'])
|
||||||
except:
|
except:
|
||||||
has_msbuild = False
|
has_msbuild = False
|
||||||
else:
|
else:
|
||||||
has_msbuild = True
|
has_msbuild = True
|
||||||
|
|
||||||
if has_msbuild and SYSTEM == 'win32':
|
if has_msbuild and SYSTEM == 'win32':
|
||||||
if platform.architecture()[0] == '32bit':
|
plat = 'Win32' if platform.architecture()[0] == '32bit' else 'x64'
|
||||||
plat = 'Win32'
|
|
||||||
elif 'win32' in sys.argv:
|
|
||||||
plat = 'Win32'
|
|
||||||
else:
|
|
||||||
plat = 'x64'
|
|
||||||
|
|
||||||
conf = 'Debug' if os.getenv('DEBUG', '') else 'Release'
|
conf = 'Debug' if os.getenv('DEBUG', '') else 'Release'
|
||||||
subprocess.call(['msbuild', 'unicorn.sln', '-m', '-p:Platform=' + plat, '-p:Configuration=' + conf], cwd=os.path.join(BUILD_DIR, 'msvc'))
|
subprocess.call(['msbuild', '-m', '-p:Platform=' + plat, '-p:Configuration=' + conf], cwd=os.path.join(UC_DIR, 'msvc'))
|
||||||
|
|
||||||
obj_dir = os.path.join(BUILD_DIR, 'msvc', plat, conf)
|
obj_dir = os.path.join(UC_DIR, 'msvc', plat, conf)
|
||||||
shutil.copy(os.path.join(obj_dir, LIBRARY_FILE), LIBS_DIR)
|
shutil.copy(os.path.join(obj_dir, LIBRARY_FILE), LIBS_DIR)
|
||||||
shutil.copy(os.path.join(obj_dir, STATIC_LIBRARY_FILE), LIBS_DIR)
|
shutil.copy(os.path.join(obj_dir, STATIC_LIBRARY_FILE), LIBS_DIR)
|
||||||
else:
|
else:
|
||||||
# platform description refs at https://docs.python.org/2/library/sys.html#sys.platform
|
# platform description refs at https://docs.python.org/2/library/sys.html#sys.platform
|
||||||
new_env = dict(os.environ)
|
new_env = dict(os.environ)
|
||||||
new_env['UNICORN_BUILD_CORE_ONLY'] = 'yes'
|
new_env['UNICORN_BUILD_CORE_ONLY'] = 'yes'
|
||||||
cmd = ['sh', './make.sh']
|
if not os.path.exists(BUILD_DIR):
|
||||||
if SYSTEM == "win32":
|
os.mkdir(BUILD_DIR)
|
||||||
|
os.chdir(BUILD_DIR)
|
||||||
|
cmd = ['sh', '../cmake.sh']
|
||||||
|
if SYSTEM == "cygwin":
|
||||||
|
if IS_64BITS:
|
||||||
|
cmd.append('cygwin-mingw64')
|
||||||
|
else:
|
||||||
|
cmd.append('cygwin-mingw32')
|
||||||
|
elif SYSTEM == "win32":
|
||||||
if IS_64BITS:
|
if IS_64BITS:
|
||||||
cmd.append('cross-win64')
|
cmd.append('cross-win64')
|
||||||
else:
|
else:
|
||||||
|
@ -196,6 +174,7 @@ def build_libraries():
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
|
||||||
class custom_sdist(sdist):
|
class custom_sdist(sdist):
|
||||||
def run(self):
|
def run(self):
|
||||||
clean_bins()
|
clean_bins()
|
||||||
|
@ -211,12 +190,6 @@ class custom_build(build):
|
||||||
build_libraries()
|
build_libraries()
|
||||||
return build.run(self)
|
return build.run(self)
|
||||||
|
|
||||||
class custom_develop(develop):
|
|
||||||
def run(self):
|
|
||||||
log.info("Building C extensions")
|
|
||||||
build_libraries()
|
|
||||||
return develop.run(self)
|
|
||||||
|
|
||||||
class custom_bdist_egg(bdist_egg):
|
class custom_bdist_egg(bdist_egg):
|
||||||
def run(self):
|
def run(self):
|
||||||
self.run_command('build')
|
self.run_command('build')
|
||||||
|
@ -225,6 +198,10 @@ class custom_bdist_egg(bdist_egg):
|
||||||
def dummy_src():
|
def dummy_src():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
cmdclass = {}
|
||||||
|
cmdclass['build'] = custom_build
|
||||||
|
cmdclass['sdist'] = custom_sdist
|
||||||
|
cmdclass['bdist_egg'] = custom_bdist_egg
|
||||||
|
|
||||||
if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
||||||
idx = sys.argv.index('bdist_wheel') + 1
|
idx = sys.argv.index('bdist_wheel') + 1
|
||||||
|
@ -245,14 +222,28 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
||||||
# https://www.python.org/dev/peps/pep-0425/
|
# https://www.python.org/dev/peps/pep-0425/
|
||||||
sys.argv.insert(idx + 1, name.replace('.', '_').replace('-', '_'))
|
sys.argv.insert(idx + 1, name.replace('.', '_').replace('-', '_'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
from setuptools.command.develop import develop
|
||||||
|
class custom_develop(develop):
|
||||||
|
def run(self):
|
||||||
|
log.info("Building C extensions")
|
||||||
|
build_libraries()
|
||||||
|
return develop.run(self)
|
||||||
|
|
||||||
|
cmdclass['develop'] = custom_develop
|
||||||
|
except ImportError:
|
||||||
|
print("Proper 'develop' support unavailable.")
|
||||||
|
|
||||||
|
def join_all(src, files):
|
||||||
|
return tuple(os.path.join(src, f) for f in files)
|
||||||
|
|
||||||
long_desc = '''
|
long_desc = '''
|
||||||
Unicorn is a lightweight, multi-platform, multi-architecture CPU emulator framework
|
Unicorn is a lightweight, multi-platform, multi-architecture CPU emulator framework
|
||||||
based on [QEMU](https://qemu.org).
|
based on [QEMU](http://qemu.org).
|
||||||
|
|
||||||
Unicorn offers some unparalleled features:
|
Unicorn offers some unparalleled features:
|
||||||
|
|
||||||
- Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, SPARC, and X86 (16, 32, 64-bit)
|
- Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, PowerPC, SPARC and X86 (16, 32, 64-bit)
|
||||||
- Clean/simple/lightweight/intuitive architecture-neutral API
|
- Clean/simple/lightweight/intuitive architecture-neutral API
|
||||||
- Implemented in pure C language, with bindings for Crystal, Clojure, Visual Basic, Perl, Rust, Ruby, Python, Java, .NET, Go, Delphi/Free Pascal, Haskell, Pharo, and Lua.
|
- Implemented in pure C language, with bindings for Crystal, Clojure, Visual Basic, Perl, Rust, Ruby, Python, Java, .NET, Go, Delphi/Free Pascal, Haskell, Pharo, and Lua.
|
||||||
- Native support for Windows & *nix (with Mac OSX, Linux, *BSD & Solaris confirmed)
|
- Native support for Windows & *nix (with Mac OSX, Linux, *BSD & Solaris confirmed)
|
||||||
|
@ -261,7 +252,7 @@ Unicorn offers some unparalleled features:
|
||||||
- Thread-safety by design
|
- Thread-safety by design
|
||||||
- Distributed under free software license GPLv2
|
- Distributed under free software license GPLv2
|
||||||
|
|
||||||
Further information is available at https://www.unicorn-engine.org
|
Further information is available at http://www.unicorn-engine.org
|
||||||
'''
|
'''
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
@ -273,18 +264,18 @@ setup(
|
||||||
author_email='aquynh@gmail.com',
|
author_email='aquynh@gmail.com',
|
||||||
description='Unicorn CPU emulator engine',
|
description='Unicorn CPU emulator engine',
|
||||||
long_description=long_desc,
|
long_description=long_desc,
|
||||||
long_description_content_type="text/markdown",
|
#long_description_content_type="text/markdown",
|
||||||
url='https://www.unicorn-engine.org',
|
url='http://www.unicorn-engine.org',
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'License :: OSI Approved :: BSD License',
|
'License :: OSI Approved :: BSD License',
|
||||||
'Programming Language :: Python :: 2',
|
'Programming Language :: Python :: 2',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
],
|
],
|
||||||
requires=['ctypes'],
|
requires=['ctypes'],
|
||||||
cmdclass={'build': custom_build, 'develop': custom_develop, 'sdist': custom_sdist, 'bdist_egg': custom_bdist_egg},
|
cmdclass=cmdclass,
|
||||||
zip_safe=False,
|
zip_safe=True,
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
is_pure=False,
|
is_pure=True,
|
||||||
package_data={
|
package_data={
|
||||||
'unicorn': ['lib/*', 'include/unicorn/*']
|
'unicorn': ['lib/*', 'include/unicorn/*']
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,28 @@ UC_ARM_REG_IPSR = 114
|
||||||
UC_ARM_REG_MSP = 115
|
UC_ARM_REG_MSP = 115
|
||||||
UC_ARM_REG_PSP = 116
|
UC_ARM_REG_PSP = 116
|
||||||
UC_ARM_REG_CONTROL = 117
|
UC_ARM_REG_CONTROL = 117
|
||||||
UC_ARM_REG_ENDING = 118
|
UC_ARM_REG_IAPSR = 118
|
||||||
|
UC_ARM_REG_EAPSR = 119
|
||||||
|
UC_ARM_REG_XPSR = 120
|
||||||
|
UC_ARM_REG_EPSR = 121
|
||||||
|
UC_ARM_REG_IEPSR = 122
|
||||||
|
UC_ARM_REG_PRIMASK = 123
|
||||||
|
UC_ARM_REG_BASEPRI = 124
|
||||||
|
UC_ARM_REG_BASEPRI_MAX = 125
|
||||||
|
UC_ARM_REG_FAULTMASK = 126
|
||||||
|
UC_ARM_REG_APSR_NZCVQ = 127
|
||||||
|
UC_ARM_REG_APSR_G = 128
|
||||||
|
UC_ARM_REG_APSR_NZCVQG = 129
|
||||||
|
UC_ARM_REG_IAPSR_NZCVQ = 130
|
||||||
|
UC_ARM_REG_IAPSR_G = 131
|
||||||
|
UC_ARM_REG_IAPSR_NZCVQG = 132
|
||||||
|
UC_ARM_REG_EAPSR_NZCVQ = 133
|
||||||
|
UC_ARM_REG_EAPSR_G = 134
|
||||||
|
UC_ARM_REG_EAPSR_NZCVQG = 135
|
||||||
|
UC_ARM_REG_XPSR_NZCVQ = 136
|
||||||
|
UC_ARM_REG_XPSR_G = 137
|
||||||
|
UC_ARM_REG_XPSR_NZCVQG = 138
|
||||||
|
UC_ARM_REG_ENDING = 139
|
||||||
|
|
||||||
# alias registers
|
# alias registers
|
||||||
UC_ARM_REG_R13 = 12
|
UC_ARM_REG_R13 = 12
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.py]
|
||||||
|
|
||||||
|
# PPC registers
|
||||||
|
|
||||||
|
UC_PPC_REG_INVALID = 0
|
||||||
|
|
||||||
|
# General purpose registers
|
||||||
|
UC_PPC_REG_PC = 1
|
||||||
|
UC_PPC_REG_0 = 2
|
||||||
|
UC_PPC_REG_1 = 3
|
||||||
|
UC_PPC_REG_2 = 4
|
||||||
|
UC_PPC_REG_3 = 5
|
||||||
|
UC_PPC_REG_4 = 6
|
||||||
|
UC_PPC_REG_5 = 7
|
||||||
|
UC_PPC_REG_6 = 8
|
||||||
|
UC_PPC_REG_7 = 9
|
||||||
|
UC_PPC_REG_8 = 10
|
||||||
|
UC_PPC_REG_9 = 11
|
||||||
|
UC_PPC_REG_10 = 12
|
||||||
|
UC_PPC_REG_11 = 13
|
||||||
|
UC_PPC_REG_12 = 14
|
||||||
|
UC_PPC_REG_13 = 15
|
||||||
|
UC_PPC_REG_14 = 16
|
||||||
|
UC_PPC_REG_15 = 17
|
||||||
|
UC_PPC_REG_16 = 18
|
||||||
|
UC_PPC_REG_17 = 19
|
||||||
|
UC_PPC_REG_18 = 20
|
||||||
|
UC_PPC_REG_19 = 21
|
||||||
|
UC_PPC_REG_20 = 22
|
||||||
|
UC_PPC_REG_21 = 23
|
||||||
|
UC_PPC_REG_22 = 24
|
||||||
|
UC_PPC_REG_23 = 25
|
||||||
|
UC_PPC_REG_24 = 26
|
||||||
|
UC_PPC_REG_25 = 27
|
||||||
|
UC_PPC_REG_26 = 28
|
||||||
|
UC_PPC_REG_27 = 29
|
||||||
|
UC_PPC_REG_28 = 30
|
||||||
|
UC_PPC_REG_29 = 31
|
||||||
|
UC_PPC_REG_30 = 32
|
||||||
|
UC_PPC_REG_31 = 33
|
|
@ -0,0 +1,142 @@
|
||||||
|
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.py]
|
||||||
|
|
||||||
|
# RISCV registers
|
||||||
|
|
||||||
|
UC_RISCV_REG_INVALID = 0
|
||||||
|
|
||||||
|
# General purpose registers
|
||||||
|
UC_RISCV_REG_X0 = 1
|
||||||
|
UC_RISCV_REG_X1 = 2
|
||||||
|
UC_RISCV_REG_X2 = 3
|
||||||
|
UC_RISCV_REG_X3 = 4
|
||||||
|
UC_RISCV_REG_X4 = 5
|
||||||
|
UC_RISCV_REG_X5 = 6
|
||||||
|
UC_RISCV_REG_X6 = 7
|
||||||
|
UC_RISCV_REG_X7 = 8
|
||||||
|
UC_RISCV_REG_X8 = 9
|
||||||
|
UC_RISCV_REG_X9 = 10
|
||||||
|
UC_RISCV_REG_X10 = 11
|
||||||
|
UC_RISCV_REG_X11 = 12
|
||||||
|
UC_RISCV_REG_X12 = 13
|
||||||
|
UC_RISCV_REG_X13 = 14
|
||||||
|
UC_RISCV_REG_X14 = 15
|
||||||
|
UC_RISCV_REG_X15 = 16
|
||||||
|
UC_RISCV_REG_X16 = 17
|
||||||
|
UC_RISCV_REG_X17 = 18
|
||||||
|
UC_RISCV_REG_X18 = 19
|
||||||
|
UC_RISCV_REG_X19 = 20
|
||||||
|
UC_RISCV_REG_X20 = 21
|
||||||
|
UC_RISCV_REG_X21 = 22
|
||||||
|
UC_RISCV_REG_X22 = 23
|
||||||
|
UC_RISCV_REG_X23 = 24
|
||||||
|
UC_RISCV_REG_X24 = 25
|
||||||
|
UC_RISCV_REG_X25 = 26
|
||||||
|
UC_RISCV_REG_X26 = 27
|
||||||
|
UC_RISCV_REG_X27 = 28
|
||||||
|
UC_RISCV_REG_X28 = 29
|
||||||
|
UC_RISCV_REG_X29 = 30
|
||||||
|
UC_RISCV_REG_X30 = 31
|
||||||
|
UC_RISCV_REG_X31 = 32
|
||||||
|
|
||||||
|
# Floating-point registers
|
||||||
|
UC_RISCV_REG_F0 = 33
|
||||||
|
UC_RISCV_REG_F1 = 34
|
||||||
|
UC_RISCV_REG_F2 = 35
|
||||||
|
UC_RISCV_REG_F3 = 36
|
||||||
|
UC_RISCV_REG_F4 = 37
|
||||||
|
UC_RISCV_REG_F5 = 38
|
||||||
|
UC_RISCV_REG_F6 = 39
|
||||||
|
UC_RISCV_REG_F7 = 40
|
||||||
|
UC_RISCV_REG_F8 = 41
|
||||||
|
UC_RISCV_REG_F9 = 42
|
||||||
|
UC_RISCV_REG_F10 = 43
|
||||||
|
UC_RISCV_REG_F11 = 44
|
||||||
|
UC_RISCV_REG_F12 = 45
|
||||||
|
UC_RISCV_REG_F13 = 46
|
||||||
|
UC_RISCV_REG_F14 = 47
|
||||||
|
UC_RISCV_REG_F15 = 48
|
||||||
|
UC_RISCV_REG_F16 = 49
|
||||||
|
UC_RISCV_REG_F17 = 50
|
||||||
|
UC_RISCV_REG_F18 = 51
|
||||||
|
UC_RISCV_REG_F19 = 52
|
||||||
|
UC_RISCV_REG_F20 = 53
|
||||||
|
UC_RISCV_REG_F21 = 54
|
||||||
|
UC_RISCV_REG_F22 = 55
|
||||||
|
UC_RISCV_REG_F23 = 56
|
||||||
|
UC_RISCV_REG_F24 = 57
|
||||||
|
UC_RISCV_REG_F25 = 58
|
||||||
|
UC_RISCV_REG_F26 = 59
|
||||||
|
UC_RISCV_REG_F27 = 60
|
||||||
|
UC_RISCV_REG_F28 = 61
|
||||||
|
UC_RISCV_REG_F29 = 62
|
||||||
|
UC_RISCV_REG_F30 = 63
|
||||||
|
UC_RISCV_REG_F31 = 64
|
||||||
|
UC_RISCV_REG_PC = 65
|
||||||
|
UC_RISCV_REG_ENDING = 66
|
||||||
|
|
||||||
|
# Alias registers
|
||||||
|
UC_RISCV_REG_ZERO = 1
|
||||||
|
UC_RISCV_REG_RA = 2
|
||||||
|
UC_RISCV_REG_SP = 3
|
||||||
|
UC_RISCV_REG_GP = 4
|
||||||
|
UC_RISCV_REG_TP = 5
|
||||||
|
UC_RISCV_REG_T0 = 6
|
||||||
|
UC_RISCV_REG_T1 = 7
|
||||||
|
UC_RISCV_REG_T2 = 8
|
||||||
|
UC_RISCV_REG_S0 = 9
|
||||||
|
UC_RISCV_REG_FP = 9
|
||||||
|
UC_RISCV_REG_S1 = 10
|
||||||
|
UC_RISCV_REG_A0 = 11
|
||||||
|
UC_RISCV_REG_A1 = 12
|
||||||
|
UC_RISCV_REG_A2 = 13
|
||||||
|
UC_RISCV_REG_A3 = 14
|
||||||
|
UC_RISCV_REG_A4 = 15
|
||||||
|
UC_RISCV_REG_A5 = 16
|
||||||
|
UC_RISCV_REG_A6 = 17
|
||||||
|
UC_RISCV_REG_A7 = 18
|
||||||
|
UC_RISCV_REG_S2 = 19
|
||||||
|
UC_RISCV_REG_S3 = 20
|
||||||
|
UC_RISCV_REG_S4 = 21
|
||||||
|
UC_RISCV_REG_S5 = 22
|
||||||
|
UC_RISCV_REG_S6 = 23
|
||||||
|
UC_RISCV_REG_S7 = 24
|
||||||
|
UC_RISCV_REG_S8 = 25
|
||||||
|
UC_RISCV_REG_S9 = 26
|
||||||
|
UC_RISCV_REG_S10 = 27
|
||||||
|
UC_RISCV_REG_S11 = 28
|
||||||
|
UC_RISCV_REG_T3 = 29
|
||||||
|
UC_RISCV_REG_T4 = 30
|
||||||
|
UC_RISCV_REG_T5 = 31
|
||||||
|
UC_RISCV_REG_T6 = 32
|
||||||
|
UC_RISCV_REG_FT0 = 33
|
||||||
|
UC_RISCV_REG_FT1 = 34
|
||||||
|
UC_RISCV_REG_FT2 = 35
|
||||||
|
UC_RISCV_REG_FT3 = 36
|
||||||
|
UC_RISCV_REG_FT4 = 37
|
||||||
|
UC_RISCV_REG_FT5 = 38
|
||||||
|
UC_RISCV_REG_FT6 = 39
|
||||||
|
UC_RISCV_REG_FT7 = 40
|
||||||
|
UC_RISCV_REG_FS0 = 41
|
||||||
|
UC_RISCV_REG_FS1 = 42
|
||||||
|
UC_RISCV_REG_FA0 = 43
|
||||||
|
UC_RISCV_REG_FA1 = 44
|
||||||
|
UC_RISCV_REG_FA2 = 45
|
||||||
|
UC_RISCV_REG_FA3 = 46
|
||||||
|
UC_RISCV_REG_FA4 = 47
|
||||||
|
UC_RISCV_REG_FA5 = 48
|
||||||
|
UC_RISCV_REG_FA6 = 49
|
||||||
|
UC_RISCV_REG_FA7 = 50
|
||||||
|
UC_RISCV_REG_FS2 = 51
|
||||||
|
UC_RISCV_REG_FS3 = 52
|
||||||
|
UC_RISCV_REG_FS4 = 53
|
||||||
|
UC_RISCV_REG_FS5 = 54
|
||||||
|
UC_RISCV_REG_FS6 = 55
|
||||||
|
UC_RISCV_REG_FS7 = 56
|
||||||
|
UC_RISCV_REG_FS8 = 57
|
||||||
|
UC_RISCV_REG_FS9 = 58
|
||||||
|
UC_RISCV_REG_FS10 = 59
|
||||||
|
UC_RISCV_REG_FS11 = 60
|
||||||
|
UC_RISCV_REG_FT8 = 61
|
||||||
|
UC_RISCV_REG_FT9 = 62
|
||||||
|
UC_RISCV_REG_FT10 = 63
|
||||||
|
UC_RISCV_REG_FT11 = 64
|
|
@ -3,12 +3,12 @@
|
||||||
import ctypes
|
import ctypes
|
||||||
import ctypes.util
|
import ctypes.util
|
||||||
import distutils.sysconfig
|
import distutils.sysconfig
|
||||||
from functools import wraps
|
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
import inspect
|
import inspect
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
import weakref
|
import weakref
|
||||||
|
import functools
|
||||||
|
|
||||||
from . import x86_const, arm64_const, unicorn_const as uc
|
from . import x86_const, arm64_const, unicorn_const as uc
|
||||||
|
|
||||||
|
@ -105,6 +105,8 @@ def _setup_prototype(lib, fname, restype, *argtypes):
|
||||||
getattr(lib, fname).argtypes = argtypes
|
getattr(lib, fname).argtypes = argtypes
|
||||||
|
|
||||||
ucerr = ctypes.c_int
|
ucerr = ctypes.c_int
|
||||||
|
uc_mode = ctypes.c_int
|
||||||
|
uc_arch = ctypes.c_int
|
||||||
uc_engine = ctypes.c_void_p
|
uc_engine = ctypes.c_void_p
|
||||||
uc_context = ctypes.c_void_p
|
uc_context = ctypes.c_void_p
|
||||||
uc_hook_h = ctypes.c_size_t
|
uc_hook_h = ctypes.c_size_t
|
||||||
|
@ -130,6 +132,7 @@ _setup_prototype(_uc, "uc_mem_write", ucerr, uc_engine, ctypes.c_uint64, ctypes.
|
||||||
_setup_prototype(_uc, "uc_emu_start", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t)
|
_setup_prototype(_uc, "uc_emu_start", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t)
|
||||||
_setup_prototype(_uc, "uc_emu_stop", ucerr, uc_engine)
|
_setup_prototype(_uc, "uc_emu_stop", ucerr, uc_engine)
|
||||||
_setup_prototype(_uc, "uc_hook_del", ucerr, uc_engine, uc_hook_h)
|
_setup_prototype(_uc, "uc_hook_del", ucerr, uc_engine, uc_hook_h)
|
||||||
|
_setup_prototype(_uc, "uc_mmio_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
|
||||||
_setup_prototype(_uc, "uc_mem_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32)
|
_setup_prototype(_uc, "uc_mem_map", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32)
|
||||||
_setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p)
|
_setup_prototype(_uc, "uc_mem_map_ptr", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p)
|
||||||
_setup_prototype(_uc, "uc_mem_unmap", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t)
|
_setup_prototype(_uc, "uc_mem_unmap", ucerr, uc_engine, ctypes.c_uint64, ctypes.c_size_t)
|
||||||
|
@ -140,12 +143,12 @@ _setup_prototype(_uc, "uc_free", ucerr, ctypes.c_void_p)
|
||||||
_setup_prototype(_uc, "uc_context_save", ucerr, uc_engine, uc_context)
|
_setup_prototype(_uc, "uc_context_save", ucerr, uc_engine, uc_context)
|
||||||
_setup_prototype(_uc, "uc_context_restore", ucerr, uc_engine, uc_context)
|
_setup_prototype(_uc, "uc_context_restore", ucerr, uc_engine, uc_context)
|
||||||
_setup_prototype(_uc, "uc_context_size", ctypes.c_size_t, uc_engine)
|
_setup_prototype(_uc, "uc_context_size", ctypes.c_size_t, uc_engine)
|
||||||
|
_setup_prototype(_uc, "uc_context_reg_read", ucerr, uc_context, ctypes.c_int, ctypes.c_void_p)
|
||||||
|
_setup_prototype(_uc, "uc_context_reg_write", ucerr, uc_context, ctypes.c_int, ctypes.c_void_p)
|
||||||
_setup_prototype(_uc, "uc_context_free", ucerr, uc_context)
|
_setup_prototype(_uc, "uc_context_free", ucerr, uc_context)
|
||||||
_setup_prototype(_uc, "uc_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes.POINTER(_uc_mem_region)), ctypes.POINTER(ctypes.c_uint32))
|
_setup_prototype(_uc, "uc_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes.POINTER(_uc_mem_region)), ctypes.POINTER(ctypes.c_uint32))
|
||||||
|
# https://bugs.python.org/issue42880
|
||||||
# uc_hook_add is special due to variable number of arguments
|
_setup_prototype(_uc, "uc_hook_add", ucerr, uc_engine, ctypes.POINTER(uc_hook_h), ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64)
|
||||||
_uc.uc_hook_add = _uc.uc_hook_add
|
|
||||||
_uc.uc_hook_add.restype = ucerr
|
|
||||||
|
|
||||||
UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p)
|
UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p)
|
||||||
UC_HOOK_INSN_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.c_void_p)
|
UC_HOOK_INSN_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.c_void_p)
|
||||||
|
@ -168,7 +171,12 @@ UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(
|
||||||
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p
|
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p
|
||||||
)
|
)
|
||||||
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
|
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
|
||||||
|
UC_MMIO_READ_CB = ctypes.CFUNCTYPE(
|
||||||
|
ctypes.c_uint64, uc_engine, ctypes.c_uint64, ctypes.c_int, ctypes.c_void_p
|
||||||
|
)
|
||||||
|
UC_MMIO_WRITE_CB = ctypes.CFUNCTYPE(
|
||||||
|
None, uc_engine, ctypes.c_uint64, ctypes.c_int, ctypes.c_uint64, ctypes.c_void_p
|
||||||
|
)
|
||||||
|
|
||||||
# access to error code via @errno of UcError
|
# access to error code via @errno of UcError
|
||||||
class UcError(Exception):
|
class UcError(Exception):
|
||||||
|
@ -199,27 +207,103 @@ def version_bind():
|
||||||
def uc_arch_supported(query):
|
def uc_arch_supported(query):
|
||||||
return _uc.uc_arch_supported(query)
|
return _uc.uc_arch_supported(query)
|
||||||
|
|
||||||
|
# uc_reg_read/write and uc_context_reg_read/write.
|
||||||
|
def reg_read(reg_read_func, arch, reg_id, opt=None):
|
||||||
|
if arch == uc.UC_ARCH_X86:
|
||||||
|
if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
||||||
|
reg = uc_x86_mmr()
|
||||||
|
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||||
|
if status != uc.UC_ERR_OK:
|
||||||
|
raise UcError(status)
|
||||||
|
return reg.selector, reg.base, reg.limit, reg.flags
|
||||||
|
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
||||||
|
reg = uc_x86_float80()
|
||||||
|
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||||
|
if status != uc.UC_ERR_OK:
|
||||||
|
raise UcError(status)
|
||||||
|
return reg.mantissa, reg.exponent
|
||||||
|
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
||||||
|
reg = uc_x86_xmm()
|
||||||
|
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||||
|
if status != uc.UC_ERR_OK:
|
||||||
|
raise UcError(status)
|
||||||
|
return reg.low_qword | (reg.high_qword << 64)
|
||||||
|
if reg_id in range(x86_const.UC_X86_REG_YMM0, x86_const.UC_X86_REG_YMM0+16):
|
||||||
|
reg = uc_x86_ymm()
|
||||||
|
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||||
|
if status != uc.UC_ERR_OK:
|
||||||
|
raise UcError(status)
|
||||||
|
return reg.first_qword | (reg.second_qword << 64) | (reg.third_qword << 128) | (reg.fourth_qword << 192)
|
||||||
|
if reg_id is x86_const.UC_X86_REG_MSR:
|
||||||
|
if opt is None:
|
||||||
|
raise UcError(uc.UC_ERR_ARG)
|
||||||
|
reg = uc_x86_msr()
|
||||||
|
reg.rid = opt
|
||||||
|
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||||
|
if status != uc.UC_ERR_OK:
|
||||||
|
raise UcError(status)
|
||||||
|
return reg.value
|
||||||
|
|
||||||
def _catch_hook_exception(func):
|
if arch == uc.UC_ARCH_ARM64:
|
||||||
@wraps(func)
|
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||||
def wrapper(self, *args, **kwargs):
|
reg = uc_arm64_neon128()
|
||||||
"""Catches exceptions raised in hook functions.
|
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||||
|
if status != uc.UC_ERR_OK:
|
||||||
|
raise UcError(status)
|
||||||
|
return reg.low_qword | (reg.high_qword << 64)
|
||||||
|
|
||||||
If an exception is raised, it is saved to the Uc object and a call to stop
|
# read to 64bit number to be safe
|
||||||
emulation is issued.
|
reg = ctypes.c_uint64(0)
|
||||||
"""
|
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||||
try:
|
if status != uc.UC_ERR_OK:
|
||||||
return func(self, *args, **kwargs)
|
raise UcError(status)
|
||||||
except Exception as e:
|
return reg.value
|
||||||
# If multiple hooks raise exceptions, just use the first one
|
|
||||||
if self._hook_exception is None:
|
|
||||||
self._hook_exception = e
|
|
||||||
|
|
||||||
self.emu_stop()
|
def reg_write(reg_write_func, arch, reg_id, value):
|
||||||
|
reg = None
|
||||||
|
|
||||||
return wrapper
|
if arch == uc.UC_ARCH_X86:
|
||||||
|
if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
||||||
|
assert isinstance(value, tuple) and len(value) == 4
|
||||||
|
reg = uc_x86_mmr()
|
||||||
|
reg.selector = value[0]
|
||||||
|
reg.base = value[1]
|
||||||
|
reg.limit = value[2]
|
||||||
|
reg.flags = value[3]
|
||||||
|
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
||||||
|
reg = uc_x86_float80()
|
||||||
|
reg.mantissa = value[0]
|
||||||
|
reg.exponent = value[1]
|
||||||
|
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
||||||
|
reg = uc_x86_xmm()
|
||||||
|
reg.low_qword = value & 0xffffffffffffffff
|
||||||
|
reg.high_qword = value >> 64
|
||||||
|
if reg_id in range(x86_const.UC_X86_REG_YMM0, x86_const.UC_X86_REG_YMM0+16):
|
||||||
|
reg = uc_x86_ymm()
|
||||||
|
reg.first_qword = value & 0xffffffffffffffff
|
||||||
|
reg.second_qword = (value >> 64) & 0xffffffffffffffff
|
||||||
|
reg.third_qword = (value >> 128) & 0xffffffffffffffff
|
||||||
|
reg.fourth_qword = value >> 192
|
||||||
|
if reg_id is x86_const.UC_X86_REG_MSR:
|
||||||
|
reg = uc_x86_msr()
|
||||||
|
reg.rid = value[0]
|
||||||
|
reg.value = value[1]
|
||||||
|
|
||||||
|
if arch == uc.UC_ARCH_ARM64:
|
||||||
|
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||||
|
reg = uc_arm64_neon128()
|
||||||
|
reg.low_qword = value & 0xffffffffffffffff
|
||||||
|
reg.high_qword = value >> 64
|
||||||
|
|
||||||
|
if reg is None:
|
||||||
|
# convert to 64bit number to be safe
|
||||||
|
reg = ctypes.c_uint64(value)
|
||||||
|
|
||||||
|
status = reg_write_func(reg_id, ctypes.byref(reg))
|
||||||
|
if status != uc.UC_ERR_OK:
|
||||||
|
raise UcError(status)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
class uc_x86_mmr(ctypes.Structure):
|
class uc_x86_mmr(ctypes.Structure):
|
||||||
"""Memory-Management Register for instructions IDTR, GDTR, LDTR, TR."""
|
"""Memory-Management Register for instructions IDTR, GDTR, LDTR, TR."""
|
||||||
|
@ -306,6 +390,8 @@ class Uc(object):
|
||||||
def __init__(self, arch, mode):
|
def __init__(self, arch, mode):
|
||||||
# verify version compatibility with the core before doing anything
|
# verify version compatibility with the core before doing anything
|
||||||
(major, minor, _combined) = uc_version()
|
(major, minor, _combined) = uc_version()
|
||||||
|
# print("core version =", uc_version())
|
||||||
|
# print("binding version =", uc.UC_API_MAJOR, uc.UC_API_MINOR)
|
||||||
if major != uc.UC_API_MAJOR or minor != uc.UC_API_MINOR:
|
if major != uc.UC_API_MAJOR or minor != uc.UC_API_MINOR:
|
||||||
self._uch = None
|
self._uch = None
|
||||||
# our binding version is different from the core's API version
|
# our binding version is different from the core's API version
|
||||||
|
@ -319,10 +405,9 @@ class Uc(object):
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
# internal mapping table to save callback & userdata
|
# internal mapping table to save callback & userdata
|
||||||
self._callbacks = {}
|
self._callbacks = {}
|
||||||
self._ctype_cbs = {}
|
self._ctype_cbs = []
|
||||||
self._callback_count = 0
|
self._callback_count = 0
|
||||||
self._cleanup.register(self)
|
self._cleanup.register(self)
|
||||||
self._hook_exception = None # The exception raised in a hook
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def release_handle(uch):
|
def release_handle(uch):
|
||||||
|
@ -340,9 +425,6 @@ class Uc(object):
|
||||||
if status != uc.UC_ERR_OK:
|
if status != uc.UC_ERR_OK:
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
|
|
||||||
if self._hook_exception is not None:
|
|
||||||
raise self._hook_exception
|
|
||||||
|
|
||||||
# stop emulation
|
# stop emulation
|
||||||
def emu_stop(self):
|
def emu_stop(self):
|
||||||
status = _uc.uc_emu_stop(self._uch)
|
status = _uc.uc_emu_stop(self._uch)
|
||||||
|
@ -351,100 +433,11 @@ class Uc(object):
|
||||||
|
|
||||||
# return the value of a register
|
# return the value of a register
|
||||||
def reg_read(self, reg_id, opt=None):
|
def reg_read(self, reg_id, opt=None):
|
||||||
if self._arch == uc.UC_ARCH_X86:
|
return reg_read(functools.partial(_uc.uc_reg_read, self._uch), self._arch, reg_id, opt)
|
||||||
if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
|
||||||
reg = uc_x86_mmr()
|
|
||||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
|
||||||
if status != uc.UC_ERR_OK:
|
|
||||||
raise UcError(status)
|
|
||||||
return reg.selector, reg.base, reg.limit, reg.flags
|
|
||||||
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
|
||||||
reg = uc_x86_float80()
|
|
||||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
|
||||||
if status != uc.UC_ERR_OK:
|
|
||||||
raise UcError(status)
|
|
||||||
return reg.mantissa, reg.exponent
|
|
||||||
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
|
||||||
reg = uc_x86_xmm()
|
|
||||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
|
||||||
if status != uc.UC_ERR_OK:
|
|
||||||
raise UcError(status)
|
|
||||||
return reg.low_qword | (reg.high_qword << 64)
|
|
||||||
if reg_id in range(x86_const.UC_X86_REG_YMM0, x86_const.UC_X86_REG_YMM0+16):
|
|
||||||
reg = uc_x86_ymm()
|
|
||||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
|
||||||
if status != uc.UC_ERR_OK:
|
|
||||||
raise UcError(status)
|
|
||||||
return reg.first_qword | (reg.second_qword << 64) | (reg.third_qword << 128) | (reg.fourth_qword << 192)
|
|
||||||
if reg_id is x86_const.UC_X86_REG_MSR:
|
|
||||||
if opt is None:
|
|
||||||
raise UcError(uc.UC_ERR_ARG)
|
|
||||||
reg = uc_x86_msr()
|
|
||||||
reg.rid = opt
|
|
||||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
|
||||||
if status != uc.UC_ERR_OK:
|
|
||||||
raise UcError(status)
|
|
||||||
return reg.value
|
|
||||||
|
|
||||||
if self._arch == uc.UC_ARCH_ARM64:
|
|
||||||
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
|
||||||
reg = uc_arm64_neon128()
|
|
||||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
|
||||||
if status != uc.UC_ERR_OK:
|
|
||||||
raise UcError(status)
|
|
||||||
return reg.low_qword | (reg.high_qword << 64)
|
|
||||||
|
|
||||||
# read to 64bit number to be safe
|
|
||||||
reg = ctypes.c_uint64(0)
|
|
||||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
|
||||||
if status != uc.UC_ERR_OK:
|
|
||||||
raise UcError(status)
|
|
||||||
return reg.value
|
|
||||||
|
|
||||||
# write to a register
|
# write to a register
|
||||||
def reg_write(self, reg_id, value):
|
def reg_write(self, reg_id, value):
|
||||||
reg = None
|
return reg_write(functools.partial(_uc.uc_reg_write, self._uch), self._arch, reg_id, value)
|
||||||
|
|
||||||
if self._arch == uc.UC_ARCH_X86:
|
|
||||||
if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
|
||||||
assert isinstance(value, tuple) and len(value) == 4
|
|
||||||
reg = uc_x86_mmr()
|
|
||||||
reg.selector = value[0]
|
|
||||||
reg.base = value[1]
|
|
||||||
reg.limit = value[2]
|
|
||||||
reg.flags = value[3]
|
|
||||||
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
|
||||||
reg = uc_x86_float80()
|
|
||||||
reg.mantissa = value[0]
|
|
||||||
reg.exponent = value[1]
|
|
||||||
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
|
||||||
reg = uc_x86_xmm()
|
|
||||||
reg.low_qword = value & 0xffffffffffffffff
|
|
||||||
reg.high_qword = value >> 64
|
|
||||||
if reg_id in range(x86_const.UC_X86_REG_YMM0, x86_const.UC_X86_REG_YMM0+16):
|
|
||||||
reg = uc_x86_ymm()
|
|
||||||
reg.first_qword = value & 0xffffffffffffffff
|
|
||||||
reg.second_qword = (value >> 64) & 0xffffffffffffffff
|
|
||||||
reg.third_qword = (value >> 128) & 0xffffffffffffffff
|
|
||||||
reg.fourth_qword = value >> 192
|
|
||||||
if reg_id is x86_const.UC_X86_REG_MSR:
|
|
||||||
reg = uc_x86_msr()
|
|
||||||
reg.rid = value[0]
|
|
||||||
reg.value = value[1]
|
|
||||||
|
|
||||||
if self._arch == uc.UC_ARCH_ARM64:
|
|
||||||
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
|
||||||
reg = uc_arm64_neon128()
|
|
||||||
reg.low_qword = value & 0xffffffffffffffff
|
|
||||||
reg.high_qword = value >> 64
|
|
||||||
|
|
||||||
if reg is None:
|
|
||||||
# convert to 64bit number to be safe
|
|
||||||
reg = ctypes.c_uint64(value)
|
|
||||||
|
|
||||||
status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg))
|
|
||||||
if status != uc.UC_ERR_OK:
|
|
||||||
raise UcError(status)
|
|
||||||
|
|
||||||
# read from MSR - X86 only
|
# read from MSR - X86 only
|
||||||
def msr_read(self, msr_id):
|
def msr_read(self, msr_id):
|
||||||
|
@ -468,6 +461,33 @@ class Uc(object):
|
||||||
if status != uc.UC_ERR_OK:
|
if status != uc.UC_ERR_OK:
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
|
|
||||||
|
def _mmio_map_read_cb(self, handle, offset, size, user_data):
|
||||||
|
(cb, data) = self._callbacks[user_data]
|
||||||
|
return cb(self, offset, size, data)
|
||||||
|
|
||||||
|
def _mmio_map_write_cb(self, handle, offset, size, value, user_data):
|
||||||
|
(cb, data) = self._callbacks[user_data]
|
||||||
|
cb(self, offset, size, value, data)
|
||||||
|
|
||||||
|
def mmio_map(self, address, size, read_cb, user_data_read, write_cb, user_data_write):
|
||||||
|
internal_read_cb = ctypes.cast(UC_MMIO_READ_CB(self._mmio_map_read_cb), UC_MMIO_READ_CB)
|
||||||
|
internal_write_cb = ctypes.cast(UC_MMIO_WRITE_CB(self._mmio_map_write_cb), UC_MMIO_WRITE_CB)
|
||||||
|
|
||||||
|
self._callback_count += 1
|
||||||
|
self._callbacks[self._callback_count] = (read_cb, user_data_read)
|
||||||
|
read_count = self._callback_count
|
||||||
|
self._callback_count += 1
|
||||||
|
self._callbacks[self._callback_count] = (write_cb, user_data_write)
|
||||||
|
write_count = self._callback_count
|
||||||
|
|
||||||
|
status = _uc.uc_mmio_map(self._uch, address, size, internal_read_cb, read_count, internal_write_cb, write_count)
|
||||||
|
if status != uc.UC_ERR_OK:
|
||||||
|
raise UcError(status)
|
||||||
|
|
||||||
|
# https://docs.python.org/3/library/ctypes.html#callback-functions
|
||||||
|
self._ctype_cbs.append(internal_read_cb)
|
||||||
|
self._ctype_cbs.append(internal_write_cb)
|
||||||
|
|
||||||
# map a range of memory
|
# map a range of memory
|
||||||
def mem_map(self, address, size, perms=uc.UC_PROT_ALL):
|
def mem_map(self, address, size, perms=uc.UC_PROT_ALL):
|
||||||
status = _uc.uc_mem_map(self._uch, address, size, perms)
|
status = _uc.uc_mem_map(self._uch, address, size, perms)
|
||||||
|
@ -500,49 +520,41 @@ class Uc(object):
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
return result.value
|
return result.value
|
||||||
|
|
||||||
@_catch_hook_exception
|
|
||||||
def _hookcode_cb(self, handle, address, size, user_data):
|
def _hookcode_cb(self, handle, address, size, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
cb(self, address, size, data)
|
cb(self, address, size, data)
|
||||||
|
|
||||||
@_catch_hook_exception
|
|
||||||
def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data):
|
def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
return cb(self, access, address, size, value, data)
|
return cb(self, access, address, size, value, data)
|
||||||
|
|
||||||
@_catch_hook_exception
|
|
||||||
def _hook_mem_access_cb(self, handle, access, address, size, value, user_data):
|
def _hook_mem_access_cb(self, handle, access, address, size, value, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
cb(self, access, address, size, value, data)
|
cb(self, access, address, size, value, data)
|
||||||
|
|
||||||
@_catch_hook_exception
|
|
||||||
def _hook_intr_cb(self, handle, intno, user_data):
|
def _hook_intr_cb(self, handle, intno, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
cb(self, intno, data)
|
cb(self, intno, data)
|
||||||
|
|
||||||
@_catch_hook_exception
|
|
||||||
def _hook_insn_invalid_cb(self, handle, user_data):
|
def _hook_insn_invalid_cb(self, handle, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
return cb(self, data)
|
return cb(self, data)
|
||||||
|
|
||||||
@_catch_hook_exception
|
|
||||||
def _hook_insn_in_cb(self, handle, port, size, user_data):
|
def _hook_insn_in_cb(self, handle, port, size, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
return cb(self, port, size, data)
|
return cb(self, port, size, data)
|
||||||
|
|
||||||
@_catch_hook_exception
|
|
||||||
def _hook_insn_out_cb(self, handle, port, size, value, user_data):
|
def _hook_insn_out_cb(self, handle, port, size, value, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
cb(self, port, size, value, data)
|
cb(self, port, size, value, data)
|
||||||
|
|
||||||
@_catch_hook_exception
|
|
||||||
def _hook_insn_syscall_cb(self, handle, user_data):
|
def _hook_insn_syscall_cb(self, handle, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
|
@ -615,7 +627,7 @@ class Uc(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
# save the ctype function so gc will leave it alone.
|
# save the ctype function so gc will leave it alone.
|
||||||
self._ctype_cbs[self._callback_count] = cb
|
self._ctype_cbs.append(cb)
|
||||||
|
|
||||||
if status != uc.UC_ERR_OK:
|
if status != uc.UC_ERR_OK:
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
|
@ -631,7 +643,7 @@ class Uc(object):
|
||||||
h = 0
|
h = 0
|
||||||
|
|
||||||
def context_save(self):
|
def context_save(self):
|
||||||
context = UcContext(self._uch)
|
context = UcContext(self._uch, self._arch, self._mode)
|
||||||
status = _uc.uc_context_save(self._uch, context.context)
|
status = _uc.uc_context_save(self._uch, context.context)
|
||||||
if status != uc.UC_ERR_OK:
|
if status != uc.UC_ERR_OK:
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
|
@ -664,14 +676,16 @@ class Uc(object):
|
||||||
|
|
||||||
|
|
||||||
class UcContext:
|
class UcContext:
|
||||||
def __init__(self, h):
|
def __init__(self, h, arch, mode):
|
||||||
self._context = uc_context()
|
self._context = uc_context()
|
||||||
self._size = _uc.uc_context_size(h)
|
self._size = _uc.uc_context_size(h)
|
||||||
self._to_free = True
|
self._to_free = True
|
||||||
status = _uc.uc_context_alloc(h, ctypes.byref(self._context))
|
status = _uc.uc_context_alloc(h, ctypes.byref(self._context))
|
||||||
if status != uc.UC_ERR_OK:
|
if status != uc.UC_ERR_OK:
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
|
self._arch = arch
|
||||||
|
self._mode = mode
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def context(self):
|
def context(self):
|
||||||
return self._context
|
return self._context
|
||||||
|
@ -680,16 +694,34 @@ class UcContext:
|
||||||
def size(self):
|
def size(self):
|
||||||
return self._size
|
return self._size
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arch(self):
|
||||||
|
return self._arch
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mode(self):
|
||||||
|
return self._mode
|
||||||
|
|
||||||
|
# return the value of a register
|
||||||
|
def reg_read(self, reg_id, opt=None):
|
||||||
|
return reg_read(functools.partial(_uc.uc_context_reg_read, self._context), self.arch, reg_id, opt)
|
||||||
|
|
||||||
|
# write to a register
|
||||||
|
def reg_write(self, reg_id, value):
|
||||||
|
return reg_write(functools.partial(_uc.uc_context_reg_write, self._context), self.arch, reg_id, value)
|
||||||
|
|
||||||
# Make UcContext picklable
|
# Make UcContext picklable
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
return (bytes(self), self.size)
|
return (bytes(self), self.size, self.arch, self.mode)
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state):
|
||||||
self._size = state[1]
|
self._size = state[1]
|
||||||
self._context = ctypes.cast(ctypes.create_string_buffer(state[0], self._size), uc_context)
|
self._context = ctypes.cast(ctypes.create_string_buffer(state[0], self._size), uc_context)
|
||||||
# __init__ won'e be invoked, so we are safe to set it here.
|
# __init__ won'e be invoked, so we are safe to set it here.
|
||||||
self._to_free = False
|
self._to_free = False
|
||||||
|
self._arch = state[2]
|
||||||
|
self._mode = state[3]
|
||||||
|
|
||||||
def __bytes__(self):
|
def __bytes__(self):
|
||||||
return ctypes.string_at(self.context, self.size)
|
return ctypes.string_at(self.context, self.size)
|
||||||
|
|
||||||
|
@ -708,6 +740,8 @@ def debug():
|
||||||
"sparc": uc.UC_ARCH_SPARC,
|
"sparc": uc.UC_ARCH_SPARC,
|
||||||
"m68k": uc.UC_ARCH_M68K,
|
"m68k": uc.UC_ARCH_M68K,
|
||||||
"x86": uc.UC_ARCH_X86,
|
"x86": uc.UC_ARCH_X86,
|
||||||
|
"riscv": uc.UC_ARCH_RISCV,
|
||||||
|
"ppc": uc.UC_ARCH_PPC,
|
||||||
}
|
}
|
||||||
|
|
||||||
all_archs = ""
|
all_archs = ""
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py]
|
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py]
|
||||||
UC_API_MAJOR = 1
|
UC_API_MAJOR = 2
|
||||||
|
|
||||||
UC_API_MINOR = 0
|
UC_API_MINOR = 0
|
||||||
UC_VERSION_MAJOR = 1
|
UC_VERSION_MAJOR = 2
|
||||||
|
|
||||||
UC_VERSION_MINOR = 0
|
UC_VERSION_MINOR = 0
|
||||||
UC_VERSION_EXTRA = 3
|
|
||||||
|
UC_VERSION_EXTRA = 0
|
||||||
UC_SECOND_SCALE = 1000000
|
UC_SECOND_SCALE = 1000000
|
||||||
UC_MILISECOND_SCALE = 1000
|
UC_MILISECOND_SCALE = 1000
|
||||||
UC_ARCH_ARM = 1
|
UC_ARCH_ARM = 1
|
||||||
|
@ -15,7 +16,8 @@ UC_ARCH_X86 = 4
|
||||||
UC_ARCH_PPC = 5
|
UC_ARCH_PPC = 5
|
||||||
UC_ARCH_SPARC = 6
|
UC_ARCH_SPARC = 6
|
||||||
UC_ARCH_M68K = 7
|
UC_ARCH_M68K = 7
|
||||||
UC_ARCH_MAX = 8
|
UC_ARCH_RISCV = 8
|
||||||
|
UC_ARCH_MAX = 9
|
||||||
|
|
||||||
UC_MODE_LITTLE_ENDIAN = 0
|
UC_MODE_LITTLE_ENDIAN = 0
|
||||||
UC_MODE_BIG_ENDIAN = 1073741824
|
UC_MODE_BIG_ENDIAN = 1073741824
|
||||||
|
@ -27,7 +29,6 @@ UC_MODE_V8 = 64
|
||||||
UC_MODE_ARM926 = 128
|
UC_MODE_ARM926 = 128
|
||||||
UC_MODE_ARM946 = 256
|
UC_MODE_ARM946 = 256
|
||||||
UC_MODE_ARM1176 = 512
|
UC_MODE_ARM1176 = 512
|
||||||
UC_MODE_ARMBE8 = 1024
|
|
||||||
UC_MODE_MICRO = 16
|
UC_MODE_MICRO = 16
|
||||||
UC_MODE_MIPS3 = 32
|
UC_MODE_MIPS3 = 32
|
||||||
UC_MODE_MIPS32R6 = 64
|
UC_MODE_MIPS32R6 = 64
|
||||||
|
@ -42,6 +43,8 @@ UC_MODE_QPX = 16
|
||||||
UC_MODE_SPARC32 = 4
|
UC_MODE_SPARC32 = 4
|
||||||
UC_MODE_SPARC64 = 8
|
UC_MODE_SPARC64 = 8
|
||||||
UC_MODE_V9 = 16
|
UC_MODE_V9 = 16
|
||||||
|
UC_MODE_RISCV32 = 4
|
||||||
|
UC_MODE_RISCV64 = 8
|
||||||
|
|
||||||
UC_ERR_OK = 0
|
UC_ERR_OK = 0
|
||||||
UC_ERR_NOMEM = 1
|
UC_ERR_NOMEM = 1
|
||||||
|
|
|
@ -254,7 +254,9 @@ UC_X86_REG_MSR = 248
|
||||||
UC_X86_REG_MXCSR = 249
|
UC_X86_REG_MXCSR = 249
|
||||||
UC_X86_REG_FS_BASE = 250
|
UC_X86_REG_FS_BASE = 250
|
||||||
UC_X86_REG_GS_BASE = 251
|
UC_X86_REG_GS_BASE = 251
|
||||||
UC_X86_REG_ENDING = 252
|
UC_X86_REG_FLAGS = 252
|
||||||
|
UC_X86_REG_RFLAGS = 253
|
||||||
|
UC_X86_REG_ENDING = 254
|
||||||
|
|
||||||
# X86 instructions
|
# X86 instructions
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.rb]
|
||||||
|
|
||||||
|
module UnicornEngine
|
||||||
|
|
||||||
|
# PPC registers
|
||||||
|
|
||||||
|
UC_PPC_REG_INVALID = 0
|
||||||
|
|
||||||
|
# General purpose registers
|
||||||
|
UC_PPC_REG_PC = 1
|
||||||
|
UC_PPC_REG_0 = 2
|
||||||
|
UC_PPC_REG_1 = 3
|
||||||
|
UC_PPC_REG_2 = 4
|
||||||
|
UC_PPC_REG_3 = 5
|
||||||
|
UC_PPC_REG_4 = 6
|
||||||
|
UC_PPC_REG_5 = 7
|
||||||
|
UC_PPC_REG_6 = 8
|
||||||
|
UC_PPC_REG_7 = 9
|
||||||
|
UC_PPC_REG_8 = 10
|
||||||
|
UC_PPC_REG_9 = 11
|
||||||
|
UC_PPC_REG_10 = 12
|
||||||
|
UC_PPC_REG_11 = 13
|
||||||
|
UC_PPC_REG_12 = 14
|
||||||
|
UC_PPC_REG_13 = 15
|
||||||
|
UC_PPC_REG_14 = 16
|
||||||
|
UC_PPC_REG_15 = 17
|
||||||
|
UC_PPC_REG_16 = 18
|
||||||
|
UC_PPC_REG_17 = 19
|
||||||
|
UC_PPC_REG_18 = 20
|
||||||
|
UC_PPC_REG_19 = 21
|
||||||
|
UC_PPC_REG_20 = 22
|
||||||
|
UC_PPC_REG_21 = 23
|
||||||
|
UC_PPC_REG_22 = 24
|
||||||
|
UC_PPC_REG_23 = 25
|
||||||
|
UC_PPC_REG_24 = 26
|
||||||
|
UC_PPC_REG_25 = 27
|
||||||
|
UC_PPC_REG_26 = 28
|
||||||
|
UC_PPC_REG_27 = 29
|
||||||
|
UC_PPC_REG_28 = 30
|
||||||
|
UC_PPC_REG_29 = 31
|
||||||
|
UC_PPC_REG_30 = 32
|
||||||
|
UC_PPC_REG_31 = 33
|
||||||
|
end
|
|
@ -0,0 +1,145 @@
|
||||||
|
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.rb]
|
||||||
|
|
||||||
|
module UnicornEngine
|
||||||
|
|
||||||
|
# RISCV registers
|
||||||
|
|
||||||
|
UC_RISCV_REG_INVALID = 0
|
||||||
|
|
||||||
|
# General purpose registers
|
||||||
|
UC_RISCV_REG_X0 = 1
|
||||||
|
UC_RISCV_REG_X1 = 2
|
||||||
|
UC_RISCV_REG_X2 = 3
|
||||||
|
UC_RISCV_REG_X3 = 4
|
||||||
|
UC_RISCV_REG_X4 = 5
|
||||||
|
UC_RISCV_REG_X5 = 6
|
||||||
|
UC_RISCV_REG_X6 = 7
|
||||||
|
UC_RISCV_REG_X7 = 8
|
||||||
|
UC_RISCV_REG_X8 = 9
|
||||||
|
UC_RISCV_REG_X9 = 10
|
||||||
|
UC_RISCV_REG_X10 = 11
|
||||||
|
UC_RISCV_REG_X11 = 12
|
||||||
|
UC_RISCV_REG_X12 = 13
|
||||||
|
UC_RISCV_REG_X13 = 14
|
||||||
|
UC_RISCV_REG_X14 = 15
|
||||||
|
UC_RISCV_REG_X15 = 16
|
||||||
|
UC_RISCV_REG_X16 = 17
|
||||||
|
UC_RISCV_REG_X17 = 18
|
||||||
|
UC_RISCV_REG_X18 = 19
|
||||||
|
UC_RISCV_REG_X19 = 20
|
||||||
|
UC_RISCV_REG_X20 = 21
|
||||||
|
UC_RISCV_REG_X21 = 22
|
||||||
|
UC_RISCV_REG_X22 = 23
|
||||||
|
UC_RISCV_REG_X23 = 24
|
||||||
|
UC_RISCV_REG_X24 = 25
|
||||||
|
UC_RISCV_REG_X25 = 26
|
||||||
|
UC_RISCV_REG_X26 = 27
|
||||||
|
UC_RISCV_REG_X27 = 28
|
||||||
|
UC_RISCV_REG_X28 = 29
|
||||||
|
UC_RISCV_REG_X29 = 30
|
||||||
|
UC_RISCV_REG_X30 = 31
|
||||||
|
UC_RISCV_REG_X31 = 32
|
||||||
|
|
||||||
|
# Floating-point registers
|
||||||
|
UC_RISCV_REG_F0 = 33
|
||||||
|
UC_RISCV_REG_F1 = 34
|
||||||
|
UC_RISCV_REG_F2 = 35
|
||||||
|
UC_RISCV_REG_F3 = 36
|
||||||
|
UC_RISCV_REG_F4 = 37
|
||||||
|
UC_RISCV_REG_F5 = 38
|
||||||
|
UC_RISCV_REG_F6 = 39
|
||||||
|
UC_RISCV_REG_F7 = 40
|
||||||
|
UC_RISCV_REG_F8 = 41
|
||||||
|
UC_RISCV_REG_F9 = 42
|
||||||
|
UC_RISCV_REG_F10 = 43
|
||||||
|
UC_RISCV_REG_F11 = 44
|
||||||
|
UC_RISCV_REG_F12 = 45
|
||||||
|
UC_RISCV_REG_F13 = 46
|
||||||
|
UC_RISCV_REG_F14 = 47
|
||||||
|
UC_RISCV_REG_F15 = 48
|
||||||
|
UC_RISCV_REG_F16 = 49
|
||||||
|
UC_RISCV_REG_F17 = 50
|
||||||
|
UC_RISCV_REG_F18 = 51
|
||||||
|
UC_RISCV_REG_F19 = 52
|
||||||
|
UC_RISCV_REG_F20 = 53
|
||||||
|
UC_RISCV_REG_F21 = 54
|
||||||
|
UC_RISCV_REG_F22 = 55
|
||||||
|
UC_RISCV_REG_F23 = 56
|
||||||
|
UC_RISCV_REG_F24 = 57
|
||||||
|
UC_RISCV_REG_F25 = 58
|
||||||
|
UC_RISCV_REG_F26 = 59
|
||||||
|
UC_RISCV_REG_F27 = 60
|
||||||
|
UC_RISCV_REG_F28 = 61
|
||||||
|
UC_RISCV_REG_F29 = 62
|
||||||
|
UC_RISCV_REG_F30 = 63
|
||||||
|
UC_RISCV_REG_F31 = 64
|
||||||
|
UC_RISCV_REG_PC = 65
|
||||||
|
UC_RISCV_REG_ENDING = 66
|
||||||
|
|
||||||
|
# Alias registers
|
||||||
|
UC_RISCV_REG_ZERO = 1
|
||||||
|
UC_RISCV_REG_RA = 2
|
||||||
|
UC_RISCV_REG_SP = 3
|
||||||
|
UC_RISCV_REG_GP = 4
|
||||||
|
UC_RISCV_REG_TP = 5
|
||||||
|
UC_RISCV_REG_T0 = 6
|
||||||
|
UC_RISCV_REG_T1 = 7
|
||||||
|
UC_RISCV_REG_T2 = 8
|
||||||
|
UC_RISCV_REG_S0 = 9
|
||||||
|
UC_RISCV_REG_FP = 9
|
||||||
|
UC_RISCV_REG_S1 = 10
|
||||||
|
UC_RISCV_REG_A0 = 11
|
||||||
|
UC_RISCV_REG_A1 = 12
|
||||||
|
UC_RISCV_REG_A2 = 13
|
||||||
|
UC_RISCV_REG_A3 = 14
|
||||||
|
UC_RISCV_REG_A4 = 15
|
||||||
|
UC_RISCV_REG_A5 = 16
|
||||||
|
UC_RISCV_REG_A6 = 17
|
||||||
|
UC_RISCV_REG_A7 = 18
|
||||||
|
UC_RISCV_REG_S2 = 19
|
||||||
|
UC_RISCV_REG_S3 = 20
|
||||||
|
UC_RISCV_REG_S4 = 21
|
||||||
|
UC_RISCV_REG_S5 = 22
|
||||||
|
UC_RISCV_REG_S6 = 23
|
||||||
|
UC_RISCV_REG_S7 = 24
|
||||||
|
UC_RISCV_REG_S8 = 25
|
||||||
|
UC_RISCV_REG_S9 = 26
|
||||||
|
UC_RISCV_REG_S10 = 27
|
||||||
|
UC_RISCV_REG_S11 = 28
|
||||||
|
UC_RISCV_REG_T3 = 29
|
||||||
|
UC_RISCV_REG_T4 = 30
|
||||||
|
UC_RISCV_REG_T5 = 31
|
||||||
|
UC_RISCV_REG_T6 = 32
|
||||||
|
UC_RISCV_REG_FT0 = 33
|
||||||
|
UC_RISCV_REG_FT1 = 34
|
||||||
|
UC_RISCV_REG_FT2 = 35
|
||||||
|
UC_RISCV_REG_FT3 = 36
|
||||||
|
UC_RISCV_REG_FT4 = 37
|
||||||
|
UC_RISCV_REG_FT5 = 38
|
||||||
|
UC_RISCV_REG_FT6 = 39
|
||||||
|
UC_RISCV_REG_FT7 = 40
|
||||||
|
UC_RISCV_REG_FS0 = 41
|
||||||
|
UC_RISCV_REG_FS1 = 42
|
||||||
|
UC_RISCV_REG_FA0 = 43
|
||||||
|
UC_RISCV_REG_FA1 = 44
|
||||||
|
UC_RISCV_REG_FA2 = 45
|
||||||
|
UC_RISCV_REG_FA3 = 46
|
||||||
|
UC_RISCV_REG_FA4 = 47
|
||||||
|
UC_RISCV_REG_FA5 = 48
|
||||||
|
UC_RISCV_REG_FA6 = 49
|
||||||
|
UC_RISCV_REG_FA7 = 50
|
||||||
|
UC_RISCV_REG_FS2 = 51
|
||||||
|
UC_RISCV_REG_FS3 = 52
|
||||||
|
UC_RISCV_REG_FS4 = 53
|
||||||
|
UC_RISCV_REG_FS5 = 54
|
||||||
|
UC_RISCV_REG_FS6 = 55
|
||||||
|
UC_RISCV_REG_FS7 = 56
|
||||||
|
UC_RISCV_REG_FS8 = 57
|
||||||
|
UC_RISCV_REG_FS9 = 58
|
||||||
|
UC_RISCV_REG_FS10 = 59
|
||||||
|
UC_RISCV_REG_FS11 = 60
|
||||||
|
UC_RISCV_REG_FT8 = 61
|
||||||
|
UC_RISCV_REG_FT9 = 62
|
||||||
|
UC_RISCV_REG_FT10 = 63
|
||||||
|
UC_RISCV_REG_FT11 = 64
|
||||||
|
end
|
|
@ -1,13 +1,14 @@
|
||||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.rb]
|
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.rb]
|
||||||
|
|
||||||
module UnicornEngine
|
module UnicornEngine
|
||||||
UC_API_MAJOR = 1
|
UC_API_MAJOR = 2
|
||||||
|
|
||||||
UC_API_MINOR = 0
|
UC_API_MINOR = 0
|
||||||
UC_VERSION_MAJOR = 1
|
UC_VERSION_MAJOR = 2
|
||||||
|
|
||||||
UC_VERSION_MINOR = 0
|
UC_VERSION_MINOR = 0
|
||||||
UC_VERSION_EXTRA = 3
|
|
||||||
|
UC_VERSION_EXTRA = 0
|
||||||
UC_SECOND_SCALE = 1000000
|
UC_SECOND_SCALE = 1000000
|
||||||
UC_MILISECOND_SCALE = 1000
|
UC_MILISECOND_SCALE = 1000
|
||||||
UC_ARCH_ARM = 1
|
UC_ARCH_ARM = 1
|
||||||
|
@ -17,7 +18,8 @@ module UnicornEngine
|
||||||
UC_ARCH_PPC = 5
|
UC_ARCH_PPC = 5
|
||||||
UC_ARCH_SPARC = 6
|
UC_ARCH_SPARC = 6
|
||||||
UC_ARCH_M68K = 7
|
UC_ARCH_M68K = 7
|
||||||
UC_ARCH_MAX = 8
|
UC_ARCH_RISCV = 8
|
||||||
|
UC_ARCH_MAX = 9
|
||||||
|
|
||||||
UC_MODE_LITTLE_ENDIAN = 0
|
UC_MODE_LITTLE_ENDIAN = 0
|
||||||
UC_MODE_BIG_ENDIAN = 1073741824
|
UC_MODE_BIG_ENDIAN = 1073741824
|
||||||
|
@ -29,7 +31,6 @@ module UnicornEngine
|
||||||
UC_MODE_ARM926 = 128
|
UC_MODE_ARM926 = 128
|
||||||
UC_MODE_ARM946 = 256
|
UC_MODE_ARM946 = 256
|
||||||
UC_MODE_ARM1176 = 512
|
UC_MODE_ARM1176 = 512
|
||||||
UC_MODE_ARMBE8 = 1024
|
|
||||||
UC_MODE_MICRO = 16
|
UC_MODE_MICRO = 16
|
||||||
UC_MODE_MIPS3 = 32
|
UC_MODE_MIPS3 = 32
|
||||||
UC_MODE_MIPS32R6 = 64
|
UC_MODE_MIPS32R6 = 64
|
||||||
|
@ -44,6 +45,8 @@ module UnicornEngine
|
||||||
UC_MODE_SPARC32 = 4
|
UC_MODE_SPARC32 = 4
|
||||||
UC_MODE_SPARC64 = 8
|
UC_MODE_SPARC64 = 8
|
||||||
UC_MODE_V9 = 16
|
UC_MODE_V9 = 16
|
||||||
|
UC_MODE_RISCV32 = 4
|
||||||
|
UC_MODE_RISCV64 = 8
|
||||||
|
|
||||||
UC_ERR_OK = 0
|
UC_ERR_OK = 0
|
||||||
UC_ERR_NOMEM = 1
|
UC_ERR_NOMEM = 1
|
||||||
|
|
|
@ -1,339 +0,0 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License.
|
|
|
@ -1,27 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "unicorn"
|
|
||||||
version = "1.0.0"
|
|
||||||
authors = ["Lukas Seidel"]
|
|
||||||
documentation = ""
|
|
||||||
edition = "2018"
|
|
||||||
include = [
|
|
||||||
"/.gitmodules",
|
|
||||||
"/COPYING",
|
|
||||||
"/Cargo.toml",
|
|
||||||
"/README.md",
|
|
||||||
"/src/*",
|
|
||||||
]
|
|
||||||
license = "GPL-2.0"
|
|
||||||
readme = "README.md"
|
|
||||||
repository = "https://github.com/unicorn-engine/unicorn/"
|
|
||||||
description = "Rust bindings for the Unicorn emulator with utility functions"
|
|
||||||
build = "build.rs"
|
|
||||||
links = "unicorn"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
bitflags = "1.0"
|
|
||||||
libc = "0.2"
|
|
||||||
capstone="0.6.0"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
build-helper = "0.1"
|
|
|
@ -1,45 +0,0 @@
|
||||||
# unicorn-rs
|
|
||||||
|
|
||||||
Rust bindings for the [Unicorn](http://www.unicorn-engine.org/) emulator with utility functions.
|
|
||||||
|
|
||||||
An extended version for fuzzing with AFL++ support can be found in https://github.com/aflplusplus/unicornafl.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use unicorn::RegisterARM;
|
|
||||||
use unicorn::unicorn_const::{Arch, Mode, Permission, SECOND_SCALE};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let arm_code32: Vec<u8> = vec![0x17, 0x00, 0x40, 0xe2]; // sub r0, #23
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::ARM, Mode::LITTLE_ENDIAN).expect("failed to initialize Unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
emu.mem_map(0x1000, 0x4000, Permission::ALL).expect("failed to map code page");
|
|
||||||
emu.mem_write(0x1000, &arm_code32).expect("failed to write instructions");
|
|
||||||
|
|
||||||
emu.reg_write(RegisterARM::R0 as i32, 123).expect("failed write R0");
|
|
||||||
emu.reg_write(RegisterARM::R5 as i32, 1337).expect("failed write R5");
|
|
||||||
|
|
||||||
let _ = emu.emu_start(0x1000, (0x1000 + arm_code32.len()) as u64, 10 * SECOND_SCALE, 1000);
|
|
||||||
assert_eq!(emu.reg_read(RegisterARM::R0 as i32), Ok(100));
|
|
||||||
assert_eq!(emu.reg_read(RegisterARM::R5 as i32), Ok(1337));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Further sample code can be found in ```tests/unicorn.rs```.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
This project has been tested on Linux, OS X and Windows.
|
|
||||||
|
|
||||||
To use unicorn-rs, simply add it as a dependency to the Cargo.toml of your program.
|
|
||||||
|
|
||||||
```
|
|
||||||
[dependencies]
|
|
||||||
unicorn = { path = "/path/to/bindings/rust", version="1.0.0" }
|
|
||||||
```
|
|
||||||
|
|
||||||
## Acknowledgements
|
|
||||||
|
|
||||||
These bindings are based on Sébastien Duquette's (@ekse) [unicorn-rs](https://github.com/unicorn-rs/unicorn-rs).
|
|
||||||
We picked up the project, as it is no longer maintained.
|
|
||||||
Thanks to all contributers.
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
use std::{env, process::Command};
|
|
||||||
|
|
||||||
use build_helper::rustc::{link_lib, link_search};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("cargo:rerun-if-changed=unicorn");
|
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
|
||||||
let unicorn = "libunicorn.a";
|
|
||||||
let _ = Command::new("cp")
|
|
||||||
.current_dir("../..")
|
|
||||||
.arg(&unicorn)
|
|
||||||
.arg(&out_dir)
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
link_search(
|
|
||||||
Some(build_helper::SearchKind::Native),
|
|
||||||
build_helper::out_dir(),
|
|
||||||
);
|
|
||||||
link_lib(Some(build_helper::LibKind::Static), "unicorn");
|
|
||||||
}
|
|
|
@ -1,146 +0,0 @@
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum RegisterARM {
|
|
||||||
// ARM registers
|
|
||||||
INVALID = 0,
|
|
||||||
APSR = 1,
|
|
||||||
APSR_NZCV = 2,
|
|
||||||
CPSR = 3,
|
|
||||||
FPEXC = 4,
|
|
||||||
FPINST = 5,
|
|
||||||
FPSCR = 6,
|
|
||||||
FPSCR_NZCV = 7,
|
|
||||||
FPSID = 8,
|
|
||||||
ITSTATE = 9,
|
|
||||||
LR = 10,
|
|
||||||
PC = 11,
|
|
||||||
SP = 12,
|
|
||||||
SPSR = 13,
|
|
||||||
D0 = 14,
|
|
||||||
D1 = 15,
|
|
||||||
D2 = 16,
|
|
||||||
D3 = 17,
|
|
||||||
D4 = 18,
|
|
||||||
D5 = 19,
|
|
||||||
D6 = 20,
|
|
||||||
D7 = 21,
|
|
||||||
D8 = 22,
|
|
||||||
D9 = 23,
|
|
||||||
D10 = 24,
|
|
||||||
D11 = 25,
|
|
||||||
D12 = 26,
|
|
||||||
D13 = 27,
|
|
||||||
D14 = 28,
|
|
||||||
D15 = 29,
|
|
||||||
D16 = 30,
|
|
||||||
D17 = 31,
|
|
||||||
D18 = 32,
|
|
||||||
D19 = 33,
|
|
||||||
D20 = 34,
|
|
||||||
D21 = 35,
|
|
||||||
D22 = 36,
|
|
||||||
D23 = 37,
|
|
||||||
D24 = 38,
|
|
||||||
D25 = 39,
|
|
||||||
D26 = 40,
|
|
||||||
D27 = 41,
|
|
||||||
D28 = 42,
|
|
||||||
D29 = 43,
|
|
||||||
D30 = 44,
|
|
||||||
D31 = 45,
|
|
||||||
FPINST2 = 46,
|
|
||||||
MVFR0 = 47,
|
|
||||||
MVFR1 = 48,
|
|
||||||
MVFR2 = 49,
|
|
||||||
Q0 = 50,
|
|
||||||
Q1 = 51,
|
|
||||||
Q2 = 52,
|
|
||||||
Q3 = 53,
|
|
||||||
Q4 = 54,
|
|
||||||
Q5 = 55,
|
|
||||||
Q6 = 56,
|
|
||||||
Q7 = 57,
|
|
||||||
Q8 = 58,
|
|
||||||
Q9 = 59,
|
|
||||||
Q10 = 60,
|
|
||||||
Q11 = 61,
|
|
||||||
Q12 = 62,
|
|
||||||
Q13 = 63,
|
|
||||||
Q14 = 64,
|
|
||||||
Q15 = 65,
|
|
||||||
R0 = 66,
|
|
||||||
R1 = 67,
|
|
||||||
R2 = 68,
|
|
||||||
R3 = 69,
|
|
||||||
R4 = 70,
|
|
||||||
R5 = 71,
|
|
||||||
R6 = 72,
|
|
||||||
R7 = 73,
|
|
||||||
R8 = 74,
|
|
||||||
R9 = 75,
|
|
||||||
R10 = 76,
|
|
||||||
R11 = 77,
|
|
||||||
R12 = 78,
|
|
||||||
S0 = 79,
|
|
||||||
S1 = 80,
|
|
||||||
S2 = 81,
|
|
||||||
S3 = 82,
|
|
||||||
S4 = 83,
|
|
||||||
S5 = 84,
|
|
||||||
S6 = 85,
|
|
||||||
S7 = 86,
|
|
||||||
S8 = 87,
|
|
||||||
S9 = 88,
|
|
||||||
S10 = 89,
|
|
||||||
S11 = 90,
|
|
||||||
S12 = 91,
|
|
||||||
S13 = 92,
|
|
||||||
S14 = 93,
|
|
||||||
S15 = 94,
|
|
||||||
S16 = 95,
|
|
||||||
S17 = 96,
|
|
||||||
S18 = 97,
|
|
||||||
S19 = 98,
|
|
||||||
S20 = 99,
|
|
||||||
S21 = 100,
|
|
||||||
S22 = 101,
|
|
||||||
S23 = 102,
|
|
||||||
S24 = 103,
|
|
||||||
S25 = 104,
|
|
||||||
S26 = 105,
|
|
||||||
S27 = 106,
|
|
||||||
S28 = 107,
|
|
||||||
S29 = 108,
|
|
||||||
S30 = 109,
|
|
||||||
S31 = 110,
|
|
||||||
C1_C0_2 = 111,
|
|
||||||
C13_C0_2 = 112,
|
|
||||||
C13_C0_3 = 113,
|
|
||||||
IPSR = 114,
|
|
||||||
MSP = 115,
|
|
||||||
PSP = 116,
|
|
||||||
CONTROL = 117,
|
|
||||||
XPSR = 118,
|
|
||||||
ENDING = 119,
|
|
||||||
// alias registers
|
|
||||||
// (assoc) R13 = 12,
|
|
||||||
// (assoc) R14 = 10,
|
|
||||||
// (assoc) R15 = 11,
|
|
||||||
// (assoc) SB = 75,
|
|
||||||
// (assoc) SL = 76,
|
|
||||||
// (assoc) FP = 77,
|
|
||||||
// (assoc) IP = 78,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RegisterARM {
|
|
||||||
pub const R13: RegisterARM = RegisterARM::SP;
|
|
||||||
pub const R14: RegisterARM = RegisterARM::LR;
|
|
||||||
pub const R15: RegisterARM = RegisterARM::PC;
|
|
||||||
pub const SB: RegisterARM = RegisterARM::R9;
|
|
||||||
pub const SL: RegisterARM = RegisterARM::R10;
|
|
||||||
pub const FP: RegisterARM = RegisterARM::R11;
|
|
||||||
pub const IP: RegisterARM = RegisterARM::R12;
|
|
||||||
}
|
|
|
@ -1,321 +0,0 @@
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
|
|
||||||
// ARM64 registers
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum RegisterARM64 {
|
|
||||||
INVALID = 0,
|
|
||||||
X29 = 1,
|
|
||||||
X30 = 2,
|
|
||||||
NZCV = 3,
|
|
||||||
SP = 4,
|
|
||||||
WSP = 5,
|
|
||||||
WZR = 6,
|
|
||||||
XZR = 7,
|
|
||||||
B0 = 8,
|
|
||||||
B1 = 9,
|
|
||||||
B2 = 10,
|
|
||||||
B3 = 11,
|
|
||||||
B4 = 12,
|
|
||||||
B5 = 13,
|
|
||||||
B6 = 14,
|
|
||||||
B7 = 15,
|
|
||||||
B8 = 16,
|
|
||||||
B9 = 17,
|
|
||||||
B10 = 18,
|
|
||||||
B11 = 19,
|
|
||||||
B12 = 20,
|
|
||||||
B13 = 21,
|
|
||||||
B14 = 22,
|
|
||||||
B15 = 23,
|
|
||||||
B16 = 24,
|
|
||||||
B17 = 25,
|
|
||||||
B18 = 26,
|
|
||||||
B19 = 27,
|
|
||||||
B20 = 28,
|
|
||||||
B21 = 29,
|
|
||||||
B22 = 30,
|
|
||||||
B23 = 31,
|
|
||||||
B24 = 32,
|
|
||||||
B25 = 33,
|
|
||||||
B26 = 34,
|
|
||||||
B27 = 35,
|
|
||||||
B28 = 36,
|
|
||||||
B29 = 37,
|
|
||||||
B30 = 38,
|
|
||||||
B31 = 39,
|
|
||||||
D0 = 40,
|
|
||||||
D1 = 41,
|
|
||||||
D2 = 42,
|
|
||||||
D3 = 43,
|
|
||||||
D4 = 44,
|
|
||||||
D5 = 45,
|
|
||||||
D6 = 46,
|
|
||||||
D7 = 47,
|
|
||||||
D8 = 48,
|
|
||||||
D9 = 49,
|
|
||||||
D10 = 50,
|
|
||||||
D11 = 51,
|
|
||||||
D12 = 52,
|
|
||||||
D13 = 53,
|
|
||||||
D14 = 54,
|
|
||||||
D15 = 55,
|
|
||||||
D16 = 56,
|
|
||||||
D17 = 57,
|
|
||||||
D18 = 58,
|
|
||||||
D19 = 59,
|
|
||||||
D20 = 60,
|
|
||||||
D21 = 61,
|
|
||||||
D22 = 62,
|
|
||||||
D23 = 63,
|
|
||||||
D24 = 64,
|
|
||||||
D25 = 65,
|
|
||||||
D26 = 66,
|
|
||||||
D27 = 67,
|
|
||||||
D28 = 68,
|
|
||||||
D29 = 69,
|
|
||||||
D30 = 70,
|
|
||||||
D31 = 71,
|
|
||||||
H0 = 72,
|
|
||||||
H1 = 73,
|
|
||||||
H2 = 74,
|
|
||||||
H3 = 75,
|
|
||||||
H4 = 76,
|
|
||||||
H5 = 77,
|
|
||||||
H6 = 78,
|
|
||||||
H7 = 79,
|
|
||||||
H8 = 80,
|
|
||||||
H9 = 81,
|
|
||||||
H10 = 82,
|
|
||||||
H11 = 83,
|
|
||||||
H12 = 84,
|
|
||||||
H13 = 85,
|
|
||||||
H14 = 86,
|
|
||||||
H15 = 87,
|
|
||||||
H16 = 88,
|
|
||||||
H17 = 89,
|
|
||||||
H18 = 90,
|
|
||||||
H19 = 91,
|
|
||||||
H20 = 92,
|
|
||||||
H21 = 93,
|
|
||||||
H22 = 94,
|
|
||||||
H23 = 95,
|
|
||||||
H24 = 96,
|
|
||||||
H25 = 97,
|
|
||||||
H26 = 98,
|
|
||||||
H27 = 99,
|
|
||||||
H28 = 100,
|
|
||||||
H29 = 101,
|
|
||||||
H30 = 102,
|
|
||||||
H31 = 103,
|
|
||||||
Q0 = 104,
|
|
||||||
Q1 = 105,
|
|
||||||
Q2 = 106,
|
|
||||||
Q3 = 107,
|
|
||||||
Q4 = 108,
|
|
||||||
Q5 = 109,
|
|
||||||
Q6 = 110,
|
|
||||||
Q7 = 111,
|
|
||||||
Q8 = 112,
|
|
||||||
Q9 = 113,
|
|
||||||
Q10 = 114,
|
|
||||||
Q11 = 115,
|
|
||||||
Q12 = 116,
|
|
||||||
Q13 = 117,
|
|
||||||
Q14 = 118,
|
|
||||||
Q15 = 119,
|
|
||||||
Q16 = 120,
|
|
||||||
Q17 = 121,
|
|
||||||
Q18 = 122,
|
|
||||||
Q19 = 123,
|
|
||||||
Q20 = 124,
|
|
||||||
Q21 = 125,
|
|
||||||
Q22 = 126,
|
|
||||||
Q23 = 127,
|
|
||||||
Q24 = 128,
|
|
||||||
Q25 = 129,
|
|
||||||
Q26 = 130,
|
|
||||||
Q27 = 131,
|
|
||||||
Q28 = 132,
|
|
||||||
Q29 = 133,
|
|
||||||
Q30 = 134,
|
|
||||||
Q31 = 135,
|
|
||||||
S0 = 136,
|
|
||||||
S1 = 137,
|
|
||||||
S2 = 138,
|
|
||||||
S3 = 139,
|
|
||||||
S4 = 140,
|
|
||||||
S5 = 141,
|
|
||||||
S6 = 142,
|
|
||||||
S7 = 143,
|
|
||||||
S8 = 144,
|
|
||||||
S9 = 145,
|
|
||||||
S10 = 146,
|
|
||||||
S11 = 147,
|
|
||||||
S12 = 148,
|
|
||||||
S13 = 149,
|
|
||||||
S14 = 150,
|
|
||||||
S15 = 151,
|
|
||||||
S16 = 152,
|
|
||||||
S17 = 153,
|
|
||||||
S18 = 154,
|
|
||||||
S19 = 155,
|
|
||||||
S20 = 156,
|
|
||||||
S21 = 157,
|
|
||||||
S22 = 158,
|
|
||||||
S23 = 159,
|
|
||||||
S24 = 160,
|
|
||||||
S25 = 161,
|
|
||||||
S26 = 162,
|
|
||||||
S27 = 163,
|
|
||||||
S28 = 164,
|
|
||||||
S29 = 165,
|
|
||||||
S30 = 166,
|
|
||||||
S31 = 167,
|
|
||||||
W0 = 168,
|
|
||||||
W1 = 169,
|
|
||||||
W2 = 170,
|
|
||||||
W3 = 171,
|
|
||||||
W4 = 172,
|
|
||||||
W5 = 173,
|
|
||||||
W6 = 174,
|
|
||||||
W7 = 175,
|
|
||||||
W8 = 176,
|
|
||||||
W9 = 177,
|
|
||||||
W10 = 178,
|
|
||||||
W11 = 179,
|
|
||||||
W12 = 180,
|
|
||||||
W13 = 181,
|
|
||||||
W14 = 182,
|
|
||||||
W15 = 183,
|
|
||||||
W16 = 184,
|
|
||||||
W17 = 185,
|
|
||||||
W18 = 186,
|
|
||||||
W19 = 187,
|
|
||||||
W20 = 188,
|
|
||||||
W21 = 189,
|
|
||||||
W22 = 190,
|
|
||||||
W23 = 191,
|
|
||||||
W24 = 192,
|
|
||||||
W25 = 193,
|
|
||||||
W26 = 194,
|
|
||||||
W27 = 195,
|
|
||||||
W28 = 196,
|
|
||||||
W29 = 197,
|
|
||||||
W30 = 198,
|
|
||||||
X0 = 199,
|
|
||||||
X1 = 200,
|
|
||||||
X2 = 201,
|
|
||||||
X3 = 202,
|
|
||||||
X4 = 203,
|
|
||||||
X5 = 204,
|
|
||||||
X6 = 205,
|
|
||||||
X7 = 206,
|
|
||||||
X8 = 207,
|
|
||||||
X9 = 208,
|
|
||||||
X10 = 209,
|
|
||||||
X11 = 210,
|
|
||||||
X12 = 211,
|
|
||||||
X13 = 212,
|
|
||||||
X14 = 213,
|
|
||||||
X15 = 214,
|
|
||||||
X16 = 215,
|
|
||||||
X17 = 216,
|
|
||||||
X18 = 217,
|
|
||||||
X19 = 218,
|
|
||||||
X20 = 219,
|
|
||||||
X21 = 220,
|
|
||||||
X22 = 221,
|
|
||||||
X23 = 222,
|
|
||||||
X24 = 223,
|
|
||||||
X25 = 224,
|
|
||||||
X26 = 225,
|
|
||||||
X27 = 226,
|
|
||||||
X28 = 227,
|
|
||||||
V0 = 228,
|
|
||||||
V1 = 229,
|
|
||||||
V2 = 230,
|
|
||||||
V3 = 231,
|
|
||||||
V4 = 232,
|
|
||||||
V5 = 233,
|
|
||||||
V6 = 234,
|
|
||||||
V7 = 235,
|
|
||||||
V8 = 236,
|
|
||||||
V9 = 237,
|
|
||||||
V10 = 238,
|
|
||||||
V11 = 239,
|
|
||||||
V12 = 240,
|
|
||||||
V13 = 241,
|
|
||||||
V14 = 242,
|
|
||||||
V15 = 243,
|
|
||||||
V16 = 244,
|
|
||||||
V17 = 245,
|
|
||||||
V18 = 246,
|
|
||||||
V19 = 247,
|
|
||||||
V20 = 248,
|
|
||||||
V21 = 249,
|
|
||||||
V22 = 250,
|
|
||||||
V23 = 251,
|
|
||||||
V24 = 252,
|
|
||||||
V25 = 253,
|
|
||||||
V26 = 254,
|
|
||||||
V27 = 255,
|
|
||||||
V28 = 256,
|
|
||||||
V29 = 257,
|
|
||||||
V30 = 258,
|
|
||||||
V31 = 259,
|
|
||||||
|
|
||||||
// pseudo registers
|
|
||||||
PC = 260,
|
|
||||||
CPACR_EL1 = 261,
|
|
||||||
|
|
||||||
// thread registers
|
|
||||||
TPIDR_EL0 = 262,
|
|
||||||
TPIDRRO_EL0 = 263,
|
|
||||||
TPIDR_EL1 = 264,
|
|
||||||
PSTATE = 265,
|
|
||||||
|
|
||||||
// exception link registers
|
|
||||||
ELR_EL0 = 266,
|
|
||||||
ELR_EL1 = 267,
|
|
||||||
ELR_EL2 = 268,
|
|
||||||
ELR_EL3 = 269,
|
|
||||||
|
|
||||||
// stack pointers registers
|
|
||||||
SP_EL0 = 270,
|
|
||||||
SP_EL1 = 271,
|
|
||||||
SP_EL2 = 272,
|
|
||||||
SP_EL3 = 273,
|
|
||||||
|
|
||||||
// other CP15 registers
|
|
||||||
TTBR0_EL1 = 274,
|
|
||||||
TTBR1_EL1 = 275,
|
|
||||||
ESR_EL0 = 276,
|
|
||||||
ESR_EL1 = 277,
|
|
||||||
ESR_EL2 = 278,
|
|
||||||
ESR_EL3 = 279,
|
|
||||||
FAR_EL0 = 280,
|
|
||||||
FAR_EL1 = 281,
|
|
||||||
FAR_EL2 = 282,
|
|
||||||
FAR_EL3 = 283,
|
|
||||||
PAR_EL1 = 284,
|
|
||||||
MAIR_EL1 = 285,
|
|
||||||
VBAR_EL0 = 286,
|
|
||||||
VBAR_EL1 = 287,
|
|
||||||
VBAR_EL2 = 288,
|
|
||||||
VBAR_EL3 = 289,
|
|
||||||
ENDING = 290,
|
|
||||||
|
|
||||||
// alias registers
|
|
||||||
// (assoc) IP0 = 215,
|
|
||||||
// (assoc) IP1 = 216,
|
|
||||||
// (assoc) FP = 1,
|
|
||||||
// (assoc) LR = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RegisterARM64 {
|
|
||||||
pub const IP0: RegisterARM64 = RegisterARM64::X16;
|
|
||||||
pub const IP1: RegisterARM64 = RegisterARM64::X17;
|
|
||||||
pub const FP: RegisterARM64 = RegisterARM64::X29;
|
|
||||||
pub const LR: RegisterARM64 = RegisterARM64::X30;
|
|
||||||
}
|
|
|
@ -1,230 +0,0 @@
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
use super::unicorn_const::*;
|
|
||||||
use libc::{c_char, c_int};
|
|
||||||
use std::ffi::c_void;
|
|
||||||
use std::pin::Pin;
|
|
||||||
|
|
||||||
pub type uc_handle = *mut c_void;
|
|
||||||
pub type uc_hook = *mut c_void;
|
|
||||||
pub type uc_context = libc::size_t;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
pub fn uc_version(major: *mut u32, minor: *mut u32) -> u32;
|
|
||||||
pub fn uc_arch_supported(arch: Arch) -> bool;
|
|
||||||
pub fn uc_open(arch: Arch, mode: Mode, engine: *mut uc_handle) -> uc_error;
|
|
||||||
pub fn uc_close(engine: uc_handle) -> uc_error;
|
|
||||||
pub fn uc_context_free(mem: uc_context) -> uc_error;
|
|
||||||
pub fn uc_errno(engine: uc_handle) -> uc_error;
|
|
||||||
pub fn uc_strerror(error_code: uc_error) -> *const c_char;
|
|
||||||
pub fn uc_reg_write(engine: uc_handle, regid: c_int, value: *const c_void) -> uc_error;
|
|
||||||
pub fn uc_reg_read(engine: uc_handle, regid: c_int, value: *mut c_void) -> uc_error;
|
|
||||||
pub fn uc_mem_write(
|
|
||||||
engine: uc_handle,
|
|
||||||
address: u64,
|
|
||||||
bytes: *const u8,
|
|
||||||
size: libc::size_t,
|
|
||||||
) -> uc_error;
|
|
||||||
pub fn uc_mem_read(
|
|
||||||
engine: uc_handle,
|
|
||||||
address: u64,
|
|
||||||
bytes: *mut u8,
|
|
||||||
size: libc::size_t,
|
|
||||||
) -> uc_error;
|
|
||||||
pub fn uc_mem_map(engine: uc_handle, address: u64, size: libc::size_t, perms: u32) -> uc_error;
|
|
||||||
pub fn uc_mem_map_ptr(
|
|
||||||
engine: uc_handle,
|
|
||||||
address: u64,
|
|
||||||
size: libc::size_t,
|
|
||||||
perms: u32,
|
|
||||||
ptr: *mut c_void,
|
|
||||||
) -> uc_error;
|
|
||||||
pub fn uc_mem_unmap(engine: uc_handle, address: u64, size: libc::size_t) -> uc_error;
|
|
||||||
pub fn uc_mem_protect(
|
|
||||||
engine: uc_handle,
|
|
||||||
address: u64,
|
|
||||||
size: libc::size_t,
|
|
||||||
perms: u32,
|
|
||||||
) -> uc_error;
|
|
||||||
pub fn uc_mem_regions(
|
|
||||||
engine: uc_handle,
|
|
||||||
regions: *const *const MemRegion,
|
|
||||||
count: *mut u32,
|
|
||||||
) -> uc_error;
|
|
||||||
pub fn uc_emu_start(
|
|
||||||
engine: uc_handle,
|
|
||||||
begin: u64,
|
|
||||||
until: u64,
|
|
||||||
timeout: u64,
|
|
||||||
count: libc::size_t,
|
|
||||||
) -> uc_error;
|
|
||||||
pub fn uc_emu_stop(engine: uc_handle) -> uc_error;
|
|
||||||
pub fn uc_hook_add(
|
|
||||||
engine: uc_handle,
|
|
||||||
hook: *mut uc_hook,
|
|
||||||
hook_type: HookType,
|
|
||||||
callback: *mut c_void,
|
|
||||||
user_data: *mut c_void,
|
|
||||||
begin: u64,
|
|
||||||
end: u64,
|
|
||||||
...
|
|
||||||
) -> uc_error;
|
|
||||||
pub fn uc_hook_del(engine: uc_handle, hook: uc_hook) -> uc_error;
|
|
||||||
pub fn uc_query(engine: uc_handle, query_type: Query, result: *mut libc::size_t) -> uc_error;
|
|
||||||
pub fn uc_context_alloc(engine: uc_handle, context: *mut uc_context) -> uc_error;
|
|
||||||
pub fn uc_context_save(engine: uc_handle, context: uc_context) -> uc_error;
|
|
||||||
pub fn uc_context_restore(engine: uc_handle, context: uc_context) -> uc_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CodeHook {
|
|
||||||
pub unicorn: *mut crate::UnicornInner,
|
|
||||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u64, u32)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct BlockHook {
|
|
||||||
pub unicorn: *mut crate::UnicornInner,
|
|
||||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u64, u32)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MemHook {
|
|
||||||
pub unicorn: *mut crate::UnicornInner,
|
|
||||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, MemType, u64, usize, i64)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InterruptHook {
|
|
||||||
pub unicorn: *mut crate::UnicornInner,
|
|
||||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u32)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InstructionInHook {
|
|
||||||
pub unicorn: *mut crate::UnicornInner,
|
|
||||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u32, usize)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InstructionOutHook {
|
|
||||||
pub unicorn: *mut crate::UnicornInner,
|
|
||||||
pub callback: Box<dyn FnMut(crate::UnicornHandle, u32, usize, u32)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InstructionSysHook {
|
|
||||||
pub unicorn: *mut crate::UnicornInner,
|
|
||||||
pub callback: Box<dyn FnMut(crate::UnicornHandle)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern "C" fn code_hook_proxy(
|
|
||||||
uc: uc_handle,
|
|
||||||
address: u64,
|
|
||||||
size: u32,
|
|
||||||
user_data: *mut CodeHook,
|
|
||||||
) {
|
|
||||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
|
||||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
|
||||||
assert_eq!(uc, unicorn.uc);
|
|
||||||
callback(
|
|
||||||
crate::UnicornHandle {
|
|
||||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
|
||||||
},
|
|
||||||
address,
|
|
||||||
size,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern "C" fn block_hook_proxy(
|
|
||||||
uc: uc_handle,
|
|
||||||
address: u64,
|
|
||||||
size: u32,
|
|
||||||
user_data: *mut BlockHook,
|
|
||||||
) {
|
|
||||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
|
||||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
|
||||||
assert_eq!(uc, unicorn.uc);
|
|
||||||
callback(
|
|
||||||
crate::UnicornHandle {
|
|
||||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
|
||||||
},
|
|
||||||
address,
|
|
||||||
size,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern "C" fn mem_hook_proxy(
|
|
||||||
uc: uc_handle,
|
|
||||||
mem_type: MemType,
|
|
||||||
address: u64,
|
|
||||||
size: u32,
|
|
||||||
value: i64,
|
|
||||||
user_data: *mut MemHook,
|
|
||||||
) {
|
|
||||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
|
||||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
|
||||||
assert_eq!(uc, unicorn.uc);
|
|
||||||
callback(
|
|
||||||
crate::UnicornHandle {
|
|
||||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
|
||||||
},
|
|
||||||
mem_type,
|
|
||||||
address,
|
|
||||||
size as usize,
|
|
||||||
value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern "C" fn intr_hook_proxy(uc: uc_handle, value: u32, user_data: *mut InterruptHook) {
|
|
||||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
|
||||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
|
||||||
assert_eq!(uc, unicorn.uc);
|
|
||||||
callback(
|
|
||||||
crate::UnicornHandle {
|
|
||||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
|
||||||
},
|
|
||||||
value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern "C" fn insn_in_hook_proxy(
|
|
||||||
uc: uc_handle,
|
|
||||||
port: u32,
|
|
||||||
size: usize,
|
|
||||||
user_data: *mut InstructionInHook,
|
|
||||||
) {
|
|
||||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
|
||||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
|
||||||
assert_eq!(uc, unicorn.uc);
|
|
||||||
callback(
|
|
||||||
crate::UnicornHandle {
|
|
||||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
|
||||||
},
|
|
||||||
port,
|
|
||||||
size,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern "C" fn insn_out_hook_proxy(
|
|
||||||
uc: uc_handle,
|
|
||||||
port: u32,
|
|
||||||
size: usize,
|
|
||||||
value: u32,
|
|
||||||
user_data: *mut InstructionOutHook,
|
|
||||||
) {
|
|
||||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
|
||||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
|
||||||
assert_eq!(uc, unicorn.uc);
|
|
||||||
callback(
|
|
||||||
crate::UnicornHandle {
|
|
||||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
|
||||||
},
|
|
||||||
port,
|
|
||||||
size,
|
|
||||||
value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern "C" fn insn_sys_hook_proxy(uc: uc_handle, user_data: *mut InstructionSysHook) {
|
|
||||||
let unicorn = unsafe { &mut *(*user_data).unicorn };
|
|
||||||
let callback = &mut unsafe { &mut *(*user_data).callback };
|
|
||||||
assert_eq!(uc, unicorn.uc);
|
|
||||||
callback(crate::UnicornHandle {
|
|
||||||
inner: unsafe { Pin::new_unchecked(unicorn) },
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,784 +0,0 @@
|
||||||
//! Bindings for the Unicorn emulator.
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
//! # Example use
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//!
|
|
||||||
//! use unicorn::RegisterARM;
|
|
||||||
//! use unicorn::unicorn_const::{Arch, Mode, Permission, SECOND_SCALE};
|
|
||||||
//!
|
|
||||||
//! fn main() {
|
|
||||||
//! let arm_code32: Vec<u8> = vec![0x17, 0x00, 0x40, 0xe2]; // sub r0, #23
|
|
||||||
//!
|
|
||||||
//! let mut unicorn = unicorn::Unicorn::new(Arch::ARM, Mode::LITTLE_ENDIAN).expect("failed to initialize Unicorn instance");
|
|
||||||
//! let mut emu = unicorn.borrow();
|
|
||||||
//! emu.mem_map(0x1000, 0x4000, Permission::ALL).expect("failed to map code page");
|
|
||||||
//! emu.mem_write(0x1000, &arm_code32).expect("failed to write instructions");
|
|
||||||
//!
|
|
||||||
//! emu.reg_write(RegisterARM::R0 as i32, 123).expect("failed write R0");
|
|
||||||
//! emu.reg_write(RegisterARM::R5 as i32, 1337).expect("failed write R5");
|
|
||||||
//!
|
|
||||||
//! let _ = emu.emu_start(0x1000, (0x1000 + arm_code32.len()) as u64, 10 * SECOND_SCALE, 1000);
|
|
||||||
//! assert_eq!(emu.reg_read(RegisterARM::R0 as i32), Ok(100));
|
|
||||||
//! assert_eq!(emu.reg_read(RegisterARM::R5 as i32), Ok(1337));
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
|
|
||||||
mod ffi;
|
|
||||||
pub mod unicorn_const;
|
|
||||||
|
|
||||||
mod arm;
|
|
||||||
mod arm64;
|
|
||||||
mod m68k;
|
|
||||||
mod mips;
|
|
||||||
mod ppc;
|
|
||||||
mod sparc;
|
|
||||||
mod x86;
|
|
||||||
pub use crate::{arm::*, arm64::*, m68k::*, mips::*, ppc::*, sparc::*, x86::*};
|
|
||||||
|
|
||||||
use ffi::uc_handle;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::ffi::c_void;
|
|
||||||
use std::marker::PhantomPinned;
|
|
||||||
use std::pin::Pin;
|
|
||||||
use unicorn_const::*;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Context {
|
|
||||||
context: ffi::uc_context,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Context {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Context { context: 0 }
|
|
||||||
}
|
|
||||||
pub fn is_initialized(&self) -> bool {
|
|
||||||
self.context != 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Context {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { ffi::uc_context_free(self.context) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// A Unicorn emulator instance.
|
|
||||||
pub struct Unicorn {
|
|
||||||
inner: Pin<Box<UnicornInner>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Handle used to safely access exposed functions and data of a Unicorn instance.
|
|
||||||
pub struct UnicornHandle<'a> {
|
|
||||||
inner: Pin<&'a mut UnicornInner>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Internal Management struct
|
|
||||||
pub struct UnicornInner {
|
|
||||||
pub uc: uc_handle,
|
|
||||||
pub arch: Arch,
|
|
||||||
pub code_hooks: HashMap<*mut libc::c_void, Box<ffi::CodeHook>>,
|
|
||||||
pub block_hooks: HashMap<*mut libc::c_void, Box<ffi::BlockHook>>,
|
|
||||||
pub mem_hooks: HashMap<*mut libc::c_void, Box<ffi::MemHook>>,
|
|
||||||
pub intr_hooks: HashMap<*mut libc::c_void, Box<ffi::InterruptHook>>,
|
|
||||||
pub insn_in_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionInHook>>,
|
|
||||||
pub insn_out_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionOutHook>>,
|
|
||||||
pub insn_sys_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionSysHook>>,
|
|
||||||
_pin: PhantomPinned,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Unicorn {
|
|
||||||
/// Create a new instance of the unicorn engine for the specified architecture
|
|
||||||
/// and hardware mode.
|
|
||||||
pub fn new(arch: Arch, mode: Mode) -> Result<Unicorn, uc_error> {
|
|
||||||
let mut handle = std::ptr::null_mut();
|
|
||||||
let err = unsafe { ffi::uc_open(arch, mode, &mut handle) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(Unicorn {
|
|
||||||
inner: Box::pin(UnicornInner {
|
|
||||||
uc: handle,
|
|
||||||
arch: arch,
|
|
||||||
code_hooks: HashMap::new(),
|
|
||||||
block_hooks: HashMap::new(),
|
|
||||||
mem_hooks: HashMap::new(),
|
|
||||||
intr_hooks: HashMap::new(),
|
|
||||||
insn_in_hooks: HashMap::new(),
|
|
||||||
insn_out_hooks: HashMap::new(),
|
|
||||||
insn_sys_hooks: HashMap::new(),
|
|
||||||
_pin: std::marker::PhantomPinned,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn borrow<'a>(&'a mut self) -> UnicornHandle<'a> {
|
|
||||||
UnicornHandle {
|
|
||||||
inner: self.inner.as_mut(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Unicorn {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { ffi::uc_close(self.inner.uc) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for UnicornInner {
|
|
||||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(formatter, "Unicorn {{ uc: {:p} }}", self.uc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> UnicornHandle<'a> {
|
|
||||||
|
|
||||||
/// Return the architecture of the current emulator.
|
|
||||||
pub fn get_arch(&self) -> Arch {
|
|
||||||
self.inner.arch
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a vector with the memory regions that are mapped in the emulator.
|
|
||||||
pub fn mem_regions(&self) -> Result<Vec<MemRegion>, uc_error> {
|
|
||||||
let mut nb_regions: u32 = 0;
|
|
||||||
let mut p_regions: *const MemRegion = std::ptr::null_mut();
|
|
||||||
let err = unsafe { ffi::uc_mem_regions(self.inner.uc, &mut p_regions, &mut nb_regions) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
let mut regions = Vec::new();
|
|
||||||
for i in 0..nb_regions {
|
|
||||||
regions.push(unsafe { std::mem::transmute_copy(&*p_regions.offset(i as isize)) });
|
|
||||||
}
|
|
||||||
unsafe { libc::free(p_regions as _) };
|
|
||||||
Ok(regions)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read a range of bytes from memory at the specified address.
|
|
||||||
pub fn mem_read(&self, address: u64, buf: &mut [u8]) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_mem_read(self.inner.uc, address, buf.as_mut_ptr(), buf.len()) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a range of bytes from memory at the specified address as vector.
|
|
||||||
pub fn mem_read_as_vec(&self, address: u64, size: usize) -> Result<Vec<u8>, uc_error> {
|
|
||||||
let mut buf = vec![0; size];
|
|
||||||
let err = unsafe { ffi::uc_mem_read(self.inner.uc, address, buf.as_mut_ptr(), size) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(buf)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mem_write(&mut self, address: u64, bytes: &[u8]) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_mem_write(self.inner.uc, address, bytes.as_ptr(), bytes.len()) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Map an existing memory region in the emulator at the specified address.
|
|
||||||
///
|
|
||||||
/// This function is marked unsafe because it is the responsibility of the caller to
|
|
||||||
/// ensure that `size` matches the size of the passed buffer, an invalid `size` value will
|
|
||||||
/// likely cause a crash in unicorn.
|
|
||||||
///
|
|
||||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
|
||||||
///
|
|
||||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
|
||||||
///
|
|
||||||
/// `ptr` is a pointer to the provided memory region that will be used by the emulator.
|
|
||||||
pub fn mem_map_ptr(
|
|
||||||
&mut self,
|
|
||||||
address: u64,
|
|
||||||
size: usize,
|
|
||||||
perms: Permission,
|
|
||||||
ptr: *mut c_void,
|
|
||||||
) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_mem_map_ptr(self.inner.uc, address, size, perms.bits(), ptr) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Map a memory region in the emulator at the specified address.
|
|
||||||
///
|
|
||||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
|
||||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
|
||||||
pub fn mem_map(
|
|
||||||
&mut self,
|
|
||||||
address: u64,
|
|
||||||
size: libc::size_t,
|
|
||||||
perms: Permission,
|
|
||||||
) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_mem_map(self.inner.uc, address, size, perms.bits()) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unmap a memory region.
|
|
||||||
///
|
|
||||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
|
||||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
|
||||||
pub fn mem_unmap(&mut self, address: u64, size: libc::size_t) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_mem_unmap(self.inner.uc, address, size) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the memory permissions for an existing memory region.
|
|
||||||
///
|
|
||||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
|
||||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
|
||||||
pub fn mem_protect(
|
|
||||||
&mut self,
|
|
||||||
address: u64,
|
|
||||||
size: libc::size_t,
|
|
||||||
perms: Permission,
|
|
||||||
) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_mem_protect(self.inner.uc, address, size, perms.bits()) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write an unsigned value from a register.
|
|
||||||
pub fn reg_write<T: Into<i32>>(&mut self, regid: T, value: u64) -> Result<(), uc_error> {
|
|
||||||
let err =
|
|
||||||
unsafe { ffi::uc_reg_write(self.inner.uc, regid.into(), &value as *const _ as _) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write variable sized values into registers.
|
|
||||||
///
|
|
||||||
/// The user has to make sure that the buffer length matches the register size.
|
|
||||||
/// This adds support for registers >64 bit (GDTR/IDTR, XMM, YMM, ZMM (x86); Q, V (arm64)).
|
|
||||||
pub fn reg_write_long<T: Into<i32>>(&self, regid: T, value: Box<[u8]>) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_reg_write(self.inner.uc, regid.into(), value.as_ptr() as _) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read an unsigned value from a register.
|
|
||||||
///
|
|
||||||
/// Not to be used with registers larger than 64 bit.
|
|
||||||
pub fn reg_read<T: Into<i32>>(&self, regid: T) -> Result<u64, uc_error> {
|
|
||||||
let mut value: u64 = 0;
|
|
||||||
let err =
|
|
||||||
unsafe { ffi::uc_reg_read(self.inner.uc, regid.into(), &mut value as *mut u64 as _) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(value)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read 128, 256 or 512 bit register value into heap allocated byte array.
|
|
||||||
///
|
|
||||||
/// This adds safe support for registers >64 bit (GDTR/IDTR, XMM, YMM, ZMM (x86); Q, V (arm64)).
|
|
||||||
pub fn reg_read_long<T: Into<i32>>(&self, regid: T) -> Result<Box<[u8]>, uc_error> {
|
|
||||||
let err: uc_error;
|
|
||||||
let boxed: Box<[u8]>;
|
|
||||||
let mut value: Vec<u8>;
|
|
||||||
let curr_reg_id = regid.into();
|
|
||||||
let curr_arch = self.get_arch();
|
|
||||||
|
|
||||||
if curr_arch == Arch::X86 {
|
|
||||||
if curr_reg_id >= x86::RegisterX86::XMM0 as i32
|
|
||||||
&& curr_reg_id <= x86::RegisterX86::XMM31 as i32
|
|
||||||
{
|
|
||||||
value = vec![0; 16];
|
|
||||||
} else if curr_reg_id >= x86::RegisterX86::YMM0 as i32
|
|
||||||
&& curr_reg_id <= x86::RegisterX86::YMM31 as i32
|
|
||||||
{
|
|
||||||
value = vec![0; 32];
|
|
||||||
} else if curr_reg_id >= x86::RegisterX86::ZMM0 as i32
|
|
||||||
&& curr_reg_id <= x86::RegisterX86::ZMM31 as i32
|
|
||||||
{
|
|
||||||
value = vec![0; 64];
|
|
||||||
} else if curr_reg_id == x86::RegisterX86::GDTR as i32
|
|
||||||
|| curr_reg_id == x86::RegisterX86::IDTR as i32
|
|
||||||
{
|
|
||||||
value = vec![0; 10]; // 64 bit base address in IA-32e mode
|
|
||||||
} else {
|
|
||||||
return Err(uc_error::ARG);
|
|
||||||
}
|
|
||||||
} else if curr_arch == Arch::ARM64 {
|
|
||||||
if (curr_reg_id >= arm64::RegisterARM64::Q0 as i32
|
|
||||||
&& curr_reg_id <= arm64::RegisterARM64::Q31 as i32)
|
|
||||||
|| (curr_reg_id >= arm64::RegisterARM64::V0 as i32
|
|
||||||
&& curr_reg_id <= arm64::RegisterARM64::V31 as i32)
|
|
||||||
{
|
|
||||||
value = vec![0; 16];
|
|
||||||
} else {
|
|
||||||
return Err(uc_error::ARG);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(uc_error::ARCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = unsafe { ffi::uc_reg_read(self.inner.uc, curr_reg_id, value.as_mut_ptr() as _) };
|
|
||||||
|
|
||||||
if err == uc_error::OK {
|
|
||||||
boxed = value.into_boxed_slice();
|
|
||||||
Ok(boxed)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read a signed 32-bit value from a register.
|
|
||||||
pub fn reg_read_i32<T: Into<i32>>(&self, regid: T) -> Result<i32, uc_error> {
|
|
||||||
let mut value: i32 = 0;
|
|
||||||
let err =
|
|
||||||
unsafe { ffi::uc_reg_read(self.inner.uc, regid.into(), &mut value as *mut i32 as _) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(value)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a code hook.
|
|
||||||
pub fn add_code_hook<F: 'static>(
|
|
||||||
&mut self,
|
|
||||||
begin: u64,
|
|
||||||
end: u64,
|
|
||||||
callback: F,
|
|
||||||
) -> Result<ffi::uc_hook, uc_error>
|
|
||||||
where
|
|
||||||
F: FnMut(UnicornHandle, u64, u32),
|
|
||||||
{
|
|
||||||
let mut hook_ptr = std::ptr::null_mut();
|
|
||||||
let mut user_data = Box::new(ffi::CodeHook {
|
|
||||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
|
||||||
callback: Box::new(callback),
|
|
||||||
});
|
|
||||||
|
|
||||||
let err = unsafe {
|
|
||||||
ffi::uc_hook_add(
|
|
||||||
self.inner.uc,
|
|
||||||
&mut hook_ptr,
|
|
||||||
HookType::CODE,
|
|
||||||
ffi::code_hook_proxy as _,
|
|
||||||
user_data.as_mut() as *mut _ as _,
|
|
||||||
begin,
|
|
||||||
end,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if err == uc_error::OK {
|
|
||||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
|
||||||
.code_hooks
|
|
||||||
.insert(hook_ptr, user_data);
|
|
||||||
Ok(hook_ptr)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a block hook.
|
|
||||||
pub fn add_block_hook<F: 'static>(&mut self, callback: F) -> Result<ffi::uc_hook, uc_error>
|
|
||||||
where
|
|
||||||
F: FnMut(UnicornHandle, u64, u32),
|
|
||||||
{
|
|
||||||
let mut hook_ptr = std::ptr::null_mut();
|
|
||||||
let mut user_data = Box::new(ffi::BlockHook {
|
|
||||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
|
||||||
callback: Box::new(callback),
|
|
||||||
});
|
|
||||||
|
|
||||||
let err = unsafe {
|
|
||||||
ffi::uc_hook_add(
|
|
||||||
self.inner.uc,
|
|
||||||
&mut hook_ptr,
|
|
||||||
HookType::BLOCK,
|
|
||||||
ffi::block_hook_proxy as _,
|
|
||||||
user_data.as_mut() as *mut _ as _,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if err == uc_error::OK {
|
|
||||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
|
||||||
.block_hooks
|
|
||||||
.insert(hook_ptr, user_data);
|
|
||||||
Ok(hook_ptr)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a memory hook.
|
|
||||||
pub fn add_mem_hook<F: 'static>(
|
|
||||||
&mut self,
|
|
||||||
hook_type: HookType,
|
|
||||||
begin: u64,
|
|
||||||
end: u64,
|
|
||||||
callback: F,
|
|
||||||
) -> Result<ffi::uc_hook, uc_error>
|
|
||||||
where
|
|
||||||
F: FnMut(UnicornHandle, MemType, u64, usize, i64),
|
|
||||||
{
|
|
||||||
if !(HookType::MEM_ALL | HookType::MEM_READ_AFTER).contains(hook_type) {
|
|
||||||
return Err(uc_error::ARG);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut hook_ptr = std::ptr::null_mut();
|
|
||||||
let mut user_data = Box::new(ffi::MemHook {
|
|
||||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
|
||||||
callback: Box::new(callback),
|
|
||||||
});
|
|
||||||
|
|
||||||
let err = unsafe {
|
|
||||||
ffi::uc_hook_add(
|
|
||||||
self.inner.uc,
|
|
||||||
&mut hook_ptr,
|
|
||||||
hook_type,
|
|
||||||
ffi::mem_hook_proxy as _,
|
|
||||||
user_data.as_mut() as *mut _ as _,
|
|
||||||
begin,
|
|
||||||
end,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if err == uc_error::OK {
|
|
||||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
|
||||||
.mem_hooks
|
|
||||||
.insert(hook_ptr, user_data);
|
|
||||||
Ok(hook_ptr)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add an interrupt hook.
|
|
||||||
pub fn add_intr_hook<F: 'static>(&mut self, callback: F) -> Result<ffi::uc_hook, uc_error>
|
|
||||||
where
|
|
||||||
F: FnMut(UnicornHandle, u32),
|
|
||||||
{
|
|
||||||
let mut hook_ptr = std::ptr::null_mut();
|
|
||||||
let mut user_data = Box::new(ffi::InterruptHook {
|
|
||||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
|
||||||
callback: Box::new(callback),
|
|
||||||
});
|
|
||||||
|
|
||||||
let err = unsafe {
|
|
||||||
ffi::uc_hook_add(
|
|
||||||
self.inner.uc,
|
|
||||||
&mut hook_ptr,
|
|
||||||
HookType::INTR,
|
|
||||||
ffi::intr_hook_proxy as _,
|
|
||||||
user_data.as_mut() as *mut _ as _,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if err == uc_error::OK {
|
|
||||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
|
||||||
.intr_hooks
|
|
||||||
.insert(hook_ptr, user_data);
|
|
||||||
Ok(hook_ptr)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add hook for x86 IN instruction.
|
|
||||||
pub fn add_insn_in_hook<F: 'static>(&mut self, callback: F) -> Result<ffi::uc_hook, uc_error>
|
|
||||||
where
|
|
||||||
F: FnMut(UnicornHandle, u32, usize),
|
|
||||||
{
|
|
||||||
let mut hook_ptr = std::ptr::null_mut();
|
|
||||||
let mut user_data = Box::new(ffi::InstructionInHook {
|
|
||||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
|
||||||
callback: Box::new(callback),
|
|
||||||
});
|
|
||||||
|
|
||||||
let err = unsafe {
|
|
||||||
ffi::uc_hook_add(
|
|
||||||
self.inner.uc,
|
|
||||||
&mut hook_ptr,
|
|
||||||
HookType::INSN,
|
|
||||||
ffi::insn_in_hook_proxy as _,
|
|
||||||
user_data.as_mut() as *mut _ as _,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
x86::InsnX86::IN,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if err == uc_error::OK {
|
|
||||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
|
||||||
.insn_in_hooks
|
|
||||||
.insert(hook_ptr, user_data);
|
|
||||||
Ok(hook_ptr)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add hook for x86 OUT instruction.
|
|
||||||
pub fn add_insn_out_hook<F: 'static>(&mut self, callback: F) -> Result<ffi::uc_hook, uc_error>
|
|
||||||
where
|
|
||||||
F: FnMut(UnicornHandle, u32, usize, u32),
|
|
||||||
{
|
|
||||||
let mut hook_ptr = std::ptr::null_mut();
|
|
||||||
let mut user_data = Box::new(ffi::InstructionOutHook {
|
|
||||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
|
||||||
callback: Box::new(callback),
|
|
||||||
});
|
|
||||||
|
|
||||||
let err = unsafe {
|
|
||||||
ffi::uc_hook_add(
|
|
||||||
self.inner.uc,
|
|
||||||
&mut hook_ptr,
|
|
||||||
HookType::INSN,
|
|
||||||
ffi::insn_out_hook_proxy as _,
|
|
||||||
user_data.as_mut() as *mut _ as _,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
x86::InsnX86::OUT,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if err == uc_error::OK {
|
|
||||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
|
||||||
.insn_out_hooks
|
|
||||||
.insert(hook_ptr, user_data);
|
|
||||||
Ok(hook_ptr)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add hook for x86 SYSCALL or SYSENTER.
|
|
||||||
pub fn add_insn_sys_hook<F: 'static>(
|
|
||||||
&mut self,
|
|
||||||
insn_type: x86::InsnSysX86,
|
|
||||||
begin: u64,
|
|
||||||
end: u64,
|
|
||||||
callback: F,
|
|
||||||
) -> Result<ffi::uc_hook, uc_error>
|
|
||||||
where
|
|
||||||
F: FnMut(UnicornHandle),
|
|
||||||
{
|
|
||||||
let mut hook_ptr = std::ptr::null_mut();
|
|
||||||
let mut user_data = Box::new(ffi::InstructionSysHook {
|
|
||||||
unicorn: unsafe { self.inner.as_mut().get_unchecked_mut() } as _,
|
|
||||||
callback: Box::new(callback),
|
|
||||||
});
|
|
||||||
|
|
||||||
let err = unsafe {
|
|
||||||
ffi::uc_hook_add(
|
|
||||||
self.inner.uc,
|
|
||||||
&mut hook_ptr,
|
|
||||||
HookType::INSN,
|
|
||||||
ffi::insn_sys_hook_proxy as _,
|
|
||||||
user_data.as_mut() as *mut _ as _,
|
|
||||||
begin,
|
|
||||||
end,
|
|
||||||
insn_type,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if err == uc_error::OK {
|
|
||||||
unsafe { self.inner.as_mut().get_unchecked_mut() }
|
|
||||||
.insn_sys_hooks
|
|
||||||
.insert(hook_ptr, user_data);
|
|
||||||
Ok(hook_ptr)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove a hook.
|
|
||||||
///
|
|
||||||
/// `hook` is the value returned by `add_*_hook` functions.
|
|
||||||
pub fn remove_hook(&mut self, hook: ffi::uc_hook) -> Result<(), uc_error> {
|
|
||||||
let handle = unsafe { self.inner.as_mut().get_unchecked_mut() };
|
|
||||||
let err: uc_error;
|
|
||||||
let mut in_one_hashmap = false;
|
|
||||||
|
|
||||||
if handle.code_hooks.contains_key(&hook) {
|
|
||||||
in_one_hashmap = true;
|
|
||||||
handle.code_hooks.remove(&hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
if handle.mem_hooks.contains_key(&hook) {
|
|
||||||
in_one_hashmap = true;
|
|
||||||
handle.mem_hooks.remove(&hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
if handle.block_hooks.contains_key(&hook) {
|
|
||||||
in_one_hashmap = true;
|
|
||||||
handle.block_hooks.remove(&hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
if handle.intr_hooks.contains_key(&hook) {
|
|
||||||
in_one_hashmap = true;
|
|
||||||
handle.intr_hooks.remove(&hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
if handle.insn_in_hooks.contains_key(&hook) {
|
|
||||||
in_one_hashmap = true;
|
|
||||||
handle.insn_in_hooks.remove(&hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
if handle.insn_out_hooks.contains_key(&hook) {
|
|
||||||
in_one_hashmap = true;
|
|
||||||
handle.insn_out_hooks.remove(&hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
if handle.insn_sys_hooks.contains_key(&hook) {
|
|
||||||
in_one_hashmap = true;
|
|
||||||
handle.insn_sys_hooks.remove(&hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
if in_one_hashmap {
|
|
||||||
err = unsafe { ffi::uc_hook_del(handle.uc, hook) };
|
|
||||||
} else {
|
|
||||||
err = uc_error::HOOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allocate and return an empty Unicorn context.
|
|
||||||
///
|
|
||||||
/// To be populated via context_save.
|
|
||||||
pub fn context_alloc(&self) -> Result<Context, uc_error> {
|
|
||||||
let mut empty_context: ffi::uc_context = Default::default();
|
|
||||||
let err = unsafe { ffi::uc_context_alloc(self.inner.uc, &mut empty_context) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(Context {
|
|
||||||
context: empty_context,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Save current Unicorn context to previously allocated Context struct.
|
|
||||||
pub fn context_save(&self, context: &mut Context) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_context_save(self.inner.uc, context.context) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allocate and return a Context struct initialized with the current CPU context.
|
|
||||||
///
|
|
||||||
/// This can be used for fast rollbacks with context_restore.
|
|
||||||
/// In case of many non-concurrent context saves, use context_alloc and *_save
|
|
||||||
/// individually to avoid unnecessary allocations.
|
|
||||||
pub fn context_init(&self) -> Result<Context, uc_error> {
|
|
||||||
let mut new_context: ffi::uc_context = Default::default();
|
|
||||||
let err = unsafe { ffi::uc_context_alloc(self.inner.uc, &mut new_context) };
|
|
||||||
if err != uc_error::OK {
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
let err = unsafe { ffi::uc_context_save(self.inner.uc, new_context) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(Context {
|
|
||||||
context: new_context,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
unsafe { ffi::uc_context_free(new_context) };
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Restore a previously saved Unicorn context.
|
|
||||||
///
|
|
||||||
/// Perform a quick rollback of the CPU context, including registers and some
|
|
||||||
/// internal metadata. Contexts may not be shared across engine instances with
|
|
||||||
/// differing arches or modes. Memory has to be restored manually, if needed.
|
|
||||||
pub fn context_restore(&self, context: &Context) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_context_restore(self.inner.uc, context.context) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Emulate machine code for a specified duration.
|
|
||||||
///
|
|
||||||
/// `begin` is the address where to start the emulation. The emulation stops if `until`
|
|
||||||
/// is hit. `timeout` specifies a duration in microseconds after which the emulation is
|
|
||||||
/// stopped (infinite execution if set to 0). `count` is the maximum number of instructions
|
|
||||||
/// to emulate (emulate all the available instructions if set to 0).
|
|
||||||
pub fn emu_start(
|
|
||||||
&mut self,
|
|
||||||
begin: u64,
|
|
||||||
until: u64,
|
|
||||||
timeout: u64,
|
|
||||||
count: usize,
|
|
||||||
) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_emu_start(self.inner.uc, begin, until, timeout, count as _) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stop the emulation.
|
|
||||||
///
|
|
||||||
/// This is usually called from callback function in hooks.
|
|
||||||
/// NOTE: For now, this will stop the execution only after the current block.
|
|
||||||
pub fn emu_stop(&mut self) -> Result<(), uc_error> {
|
|
||||||
let err = unsafe { ffi::uc_emu_stop(self.inner.uc) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Query the internal status of the engine.
|
|
||||||
///
|
|
||||||
/// supported: MODE, PAGE_SIZE, ARCH
|
|
||||||
pub fn query(&self, query: Query) -> Result<usize, uc_error> {
|
|
||||||
let mut result: libc::size_t = Default::default();
|
|
||||||
let err = unsafe { ffi::uc_query(self.inner.uc, query, &mut result) };
|
|
||||||
if err == uc_error::OK {
|
|
||||||
Ok(result)
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
// M68K registers
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum RegisterM68K {
|
|
||||||
INVALID = 0,
|
|
||||||
A0,
|
|
||||||
A1,
|
|
||||||
A2,
|
|
||||||
A3,
|
|
||||||
A4,
|
|
||||||
A5,
|
|
||||||
A6,
|
|
||||||
A7,
|
|
||||||
D0,
|
|
||||||
D1,
|
|
||||||
D2,
|
|
||||||
D3,
|
|
||||||
D4,
|
|
||||||
D5,
|
|
||||||
D6,
|
|
||||||
D7,
|
|
||||||
SR,
|
|
||||||
PC,
|
|
||||||
}
|
|
|
@ -1,246 +0,0 @@
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
|
|
||||||
// MIPS registers
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum RegisterMIPS {
|
|
||||||
INVALID = 0,
|
|
||||||
|
|
||||||
// General purpose registers
|
|
||||||
PC = 1,
|
|
||||||
GPR0 = 2,
|
|
||||||
GPR1 = 3,
|
|
||||||
GPR2 = 4,
|
|
||||||
GPR3 = 5,
|
|
||||||
GPR4 = 6,
|
|
||||||
GPR5 = 7,
|
|
||||||
GPR6 = 8,
|
|
||||||
GPR7 = 9,
|
|
||||||
GPR8 = 10,
|
|
||||||
GPR9 = 11,
|
|
||||||
GPR10 = 12,
|
|
||||||
GPR11 = 13,
|
|
||||||
GPR12 = 14,
|
|
||||||
GPR13 = 15,
|
|
||||||
GPR14 = 16,
|
|
||||||
GPR15 = 17,
|
|
||||||
GPR16 = 18,
|
|
||||||
GPR17 = 19,
|
|
||||||
GPR18 = 20,
|
|
||||||
GPR19 = 21,
|
|
||||||
GPR20 = 22,
|
|
||||||
GPR21 = 23,
|
|
||||||
GPR22 = 24,
|
|
||||||
GPR23 = 25,
|
|
||||||
GPR24 = 26,
|
|
||||||
GPR25 = 27,
|
|
||||||
GPR26 = 28,
|
|
||||||
GPR27 = 29,
|
|
||||||
GPR28 = 30,
|
|
||||||
GPR29 = 31,
|
|
||||||
GPR30 = 32,
|
|
||||||
GPR31 = 33,
|
|
||||||
|
|
||||||
// DSP registers
|
|
||||||
DSPCCOND = 34,
|
|
||||||
DSPCARRY = 35,
|
|
||||||
DSPEFI = 36,
|
|
||||||
DSPOUTFLAG = 37,
|
|
||||||
DSPOUTFLAG16_19 = 38,
|
|
||||||
DSPOUTFLAG20 = 39,
|
|
||||||
DSPOUTFLAG21 = 40,
|
|
||||||
DSPOUTFLAG22 = 41,
|
|
||||||
DSPOUTFLAG23 = 42,
|
|
||||||
DSPPOS = 43,
|
|
||||||
DSPSCOUNT = 44,
|
|
||||||
|
|
||||||
// ACC registers
|
|
||||||
AC0 = 45,
|
|
||||||
AC1 = 46,
|
|
||||||
AC2 = 47,
|
|
||||||
AC3 = 48,
|
|
||||||
|
|
||||||
// COP registers
|
|
||||||
CC0 = 49,
|
|
||||||
CC1 = 50,
|
|
||||||
CC2 = 51,
|
|
||||||
CC3 = 52,
|
|
||||||
CC4 = 53,
|
|
||||||
CC5 = 54,
|
|
||||||
CC6 = 55,
|
|
||||||
CC7 = 56,
|
|
||||||
|
|
||||||
// FPU registers
|
|
||||||
F0 = 57,
|
|
||||||
F1 = 58,
|
|
||||||
F2 = 59,
|
|
||||||
F3 = 60,
|
|
||||||
F4 = 61,
|
|
||||||
F5 = 62,
|
|
||||||
F6 = 63,
|
|
||||||
F7 = 64,
|
|
||||||
F8 = 65,
|
|
||||||
F9 = 66,
|
|
||||||
F10 = 67,
|
|
||||||
F11 = 68,
|
|
||||||
F12 = 69,
|
|
||||||
F13 = 70,
|
|
||||||
F14 = 71,
|
|
||||||
F15 = 72,
|
|
||||||
F16 = 73,
|
|
||||||
F17 = 74,
|
|
||||||
F18 = 75,
|
|
||||||
F19 = 76,
|
|
||||||
F20 = 77,
|
|
||||||
F21 = 78,
|
|
||||||
F22 = 79,
|
|
||||||
F23 = 80,
|
|
||||||
F24 = 81,
|
|
||||||
F25 = 82,
|
|
||||||
F26 = 83,
|
|
||||||
F27 = 84,
|
|
||||||
F28 = 85,
|
|
||||||
F29 = 86,
|
|
||||||
F30 = 87,
|
|
||||||
F31 = 88,
|
|
||||||
FCC0 = 89,
|
|
||||||
FCC1 = 90,
|
|
||||||
FCC2 = 91,
|
|
||||||
FCC3 = 92,
|
|
||||||
FCC4 = 93,
|
|
||||||
FCC5 = 94,
|
|
||||||
FCC6 = 95,
|
|
||||||
FCC7 = 96,
|
|
||||||
|
|
||||||
// AFPR128
|
|
||||||
W0 = 97,
|
|
||||||
W1 = 98,
|
|
||||||
W2 = 99,
|
|
||||||
W3 = 100,
|
|
||||||
W4 = 101,
|
|
||||||
W5 = 102,
|
|
||||||
W6 = 103,
|
|
||||||
W7 = 104,
|
|
||||||
W8 = 105,
|
|
||||||
W9 = 106,
|
|
||||||
W10 = 107,
|
|
||||||
W11 = 108,
|
|
||||||
W12 = 109,
|
|
||||||
W13 = 110,
|
|
||||||
W14 = 111,
|
|
||||||
W15 = 112,
|
|
||||||
W16 = 113,
|
|
||||||
W17 = 114,
|
|
||||||
W18 = 115,
|
|
||||||
W19 = 116,
|
|
||||||
W20 = 117,
|
|
||||||
W21 = 118,
|
|
||||||
W22 = 119,
|
|
||||||
W23 = 120,
|
|
||||||
W24 = 121,
|
|
||||||
W25 = 122,
|
|
||||||
W26 = 123,
|
|
||||||
W27 = 124,
|
|
||||||
W28 = 125,
|
|
||||||
W29 = 126,
|
|
||||||
W30 = 127,
|
|
||||||
W31 = 128,
|
|
||||||
HI = 129,
|
|
||||||
LO = 130,
|
|
||||||
P0 = 131,
|
|
||||||
P1 = 132,
|
|
||||||
P2 = 133,
|
|
||||||
MPL0 = 134,
|
|
||||||
MPL1 = 135,
|
|
||||||
MPL2 = 136,
|
|
||||||
CP0_CONFIG3 = 137,
|
|
||||||
CP0_USERLOCAL = 138,
|
|
||||||
ENDING = 139,
|
|
||||||
|
|
||||||
// alias registers
|
|
||||||
// (assoc) ZERO = 2,
|
|
||||||
// (assoc) AT = 3,
|
|
||||||
// (assoc) V0 = 4,
|
|
||||||
// (assoc) V1 = 5,
|
|
||||||
// (assoc) A0 = 6,
|
|
||||||
// (assoc) A1 = 7,
|
|
||||||
// (assoc) A2 = 8,
|
|
||||||
// (assoc) A3 = 9,
|
|
||||||
// (assoc) T0 = 10,
|
|
||||||
// (assoc) T1 = 11,
|
|
||||||
// (assoc) T2 = 12,
|
|
||||||
// (assoc) T3 = 13,
|
|
||||||
// (assoc) T4 = 14,
|
|
||||||
// (assoc) T5 = 15,
|
|
||||||
// (assoc) T6 = 16,
|
|
||||||
// (assoc) T7 = 17,
|
|
||||||
// (assoc) S0 = 18,
|
|
||||||
// (assoc) S1 = 19,
|
|
||||||
// (assoc) S2 = 20,
|
|
||||||
// (assoc) S3 = 21,
|
|
||||||
// (assoc) S4 = 22,
|
|
||||||
// (assoc) S5 = 23,
|
|
||||||
// (assoc) S6 = 24,
|
|
||||||
// (assoc) S7 = 25,
|
|
||||||
// (assoc) T8 = 26,
|
|
||||||
// (assoc) T9 = 27,
|
|
||||||
// (assoc) K0 = 28,
|
|
||||||
// (assoc) K1 = 29,
|
|
||||||
// (assoc) GP = 30,
|
|
||||||
// (assoc) SP = 31,
|
|
||||||
// (assoc) FP = 32,
|
|
||||||
// (assoc) S8 = 32,
|
|
||||||
// (assoc) RA = 33,
|
|
||||||
// (assoc) HI0 = 45,
|
|
||||||
// (assoc) HI1 = 46,
|
|
||||||
// (assoc) HI2 = 47,
|
|
||||||
// (assoc) HI3 = 48,
|
|
||||||
// (assoc) LO0 = 45,
|
|
||||||
// (assoc) LO1 = 46,
|
|
||||||
// (assoc) LO2 = 47,
|
|
||||||
// (assoc) LO3 = 48,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RegisterMIPS {
|
|
||||||
pub const ZERO: RegisterMIPS = RegisterMIPS::GPR0;
|
|
||||||
pub const AT: RegisterMIPS = RegisterMIPS::GPR1;
|
|
||||||
pub const V0: RegisterMIPS = RegisterMIPS::GPR2;
|
|
||||||
pub const V1: RegisterMIPS = RegisterMIPS::GPR3;
|
|
||||||
pub const A0: RegisterMIPS = RegisterMIPS::GPR4;
|
|
||||||
pub const A1: RegisterMIPS = RegisterMIPS::GPR5;
|
|
||||||
pub const A2: RegisterMIPS = RegisterMIPS::GPR6;
|
|
||||||
pub const A3: RegisterMIPS = RegisterMIPS::GPR7;
|
|
||||||
pub const T0: RegisterMIPS = RegisterMIPS::GPR8;
|
|
||||||
pub const T1: RegisterMIPS = RegisterMIPS::GPR9;
|
|
||||||
pub const T2: RegisterMIPS = RegisterMIPS::GPR10;
|
|
||||||
pub const T3: RegisterMIPS = RegisterMIPS::GPR11;
|
|
||||||
pub const T4: RegisterMIPS = RegisterMIPS::GPR12;
|
|
||||||
pub const T5: RegisterMIPS = RegisterMIPS::GPR13;
|
|
||||||
pub const T6: RegisterMIPS = RegisterMIPS::GPR14;
|
|
||||||
pub const T7: RegisterMIPS = RegisterMIPS::GPR15;
|
|
||||||
pub const S0: RegisterMIPS = RegisterMIPS::GPR16;
|
|
||||||
pub const S1: RegisterMIPS = RegisterMIPS::GPR17;
|
|
||||||
pub const S2: RegisterMIPS = RegisterMIPS::GPR18;
|
|
||||||
pub const S3: RegisterMIPS = RegisterMIPS::GPR19;
|
|
||||||
pub const S4: RegisterMIPS = RegisterMIPS::GPR20;
|
|
||||||
pub const S5: RegisterMIPS = RegisterMIPS::GPR21;
|
|
||||||
pub const S6: RegisterMIPS = RegisterMIPS::GPR22;
|
|
||||||
pub const S7: RegisterMIPS = RegisterMIPS::GPR23;
|
|
||||||
pub const T8: RegisterMIPS = RegisterMIPS::GPR24;
|
|
||||||
pub const T9: RegisterMIPS = RegisterMIPS::GPR25;
|
|
||||||
pub const K0: RegisterMIPS = RegisterMIPS::GPR26;
|
|
||||||
pub const K1: RegisterMIPS = RegisterMIPS::GPR27;
|
|
||||||
pub const GP: RegisterMIPS = RegisterMIPS::GPR28;
|
|
||||||
pub const SP: RegisterMIPS = RegisterMIPS::GPR29;
|
|
||||||
pub const FP: RegisterMIPS = RegisterMIPS::GPR30;
|
|
||||||
pub const S8: RegisterMIPS = RegisterMIPS::GPR30;
|
|
||||||
pub const RA: RegisterMIPS = RegisterMIPS::GPR31;
|
|
||||||
pub const HI0: RegisterMIPS = RegisterMIPS::AC0;
|
|
||||||
pub const HI1: RegisterMIPS = RegisterMIPS::AC1;
|
|
||||||
pub const HI2: RegisterMIPS = RegisterMIPS::AC2;
|
|
||||||
pub const HI3: RegisterMIPS = RegisterMIPS::AC3;
|
|
||||||
pub const LO0: RegisterMIPS = RegisterMIPS::AC0;
|
|
||||||
pub const LO1: RegisterMIPS = RegisterMIPS::AC1;
|
|
||||||
pub const LO2: RegisterMIPS = RegisterMIPS::AC2;
|
|
||||||
pub const LO3: RegisterMIPS = RegisterMIPS::AC3;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
|
||||||
|
|
||||||
// PowerPC registers
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum RegisterPPC {
|
|
||||||
INVALID = 0,
|
|
||||||
PC = 1,
|
|
||||||
GPR0 = 2,
|
|
||||||
GPR1 = 3,
|
|
||||||
GPR2 = 4,
|
|
||||||
GPR3 = 5,
|
|
||||||
GPR4 = 6,
|
|
||||||
GPR5 = 7,
|
|
||||||
GPR6 = 8,
|
|
||||||
GPR7 = 9,
|
|
||||||
GPR8 = 10,
|
|
||||||
GPR9 = 11,
|
|
||||||
GPR10 = 12,
|
|
||||||
GPR11 = 13,
|
|
||||||
GPR12 = 14,
|
|
||||||
GPR13 = 15,
|
|
||||||
GPR14 = 16,
|
|
||||||
GPR15 = 17,
|
|
||||||
GPR16 = 18,
|
|
||||||
GPR17 = 19,
|
|
||||||
GPR18 = 20,
|
|
||||||
GPR19 = 21,
|
|
||||||
GPR20 = 22,
|
|
||||||
GPR21 = 23,
|
|
||||||
GPR22 = 24,
|
|
||||||
GPR23 = 25,
|
|
||||||
GPR24 = 26,
|
|
||||||
GPR25 = 27,
|
|
||||||
GPR26 = 28,
|
|
||||||
GPR27 = 29,
|
|
||||||
GPR28 = 30,
|
|
||||||
GPR29 = 31,
|
|
||||||
GPR30 = 32,
|
|
||||||
GPR31 = 33,
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
// SPARC registers
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum RegisterSPARC {
|
|
||||||
INVALID = 0,
|
|
||||||
F0 = 1,
|
|
||||||
F1 = 2,
|
|
||||||
F2 = 3,
|
|
||||||
F3 = 4,
|
|
||||||
F4 = 5,
|
|
||||||
F5 = 6,
|
|
||||||
F6 = 7,
|
|
||||||
F7 = 8,
|
|
||||||
F8 = 9,
|
|
||||||
F9 = 10,
|
|
||||||
F10 = 11,
|
|
||||||
F11 = 12,
|
|
||||||
F12 = 13,
|
|
||||||
F13 = 14,
|
|
||||||
F14 = 15,
|
|
||||||
F15 = 16,
|
|
||||||
F16 = 17,
|
|
||||||
F17 = 18,
|
|
||||||
F18 = 19,
|
|
||||||
F19 = 20,
|
|
||||||
F20 = 21,
|
|
||||||
F21 = 22,
|
|
||||||
F22 = 23,
|
|
||||||
F23 = 24,
|
|
||||||
F24 = 25,
|
|
||||||
F25 = 26,
|
|
||||||
F26 = 27,
|
|
||||||
F27 = 28,
|
|
||||||
F28 = 29,
|
|
||||||
F29 = 30,
|
|
||||||
F30 = 31,
|
|
||||||
F31 = 32,
|
|
||||||
F32 = 33,
|
|
||||||
F34 = 34,
|
|
||||||
F36 = 35,
|
|
||||||
F38 = 36,
|
|
||||||
F40 = 37,
|
|
||||||
F42 = 38,
|
|
||||||
F44 = 39,
|
|
||||||
F46 = 40,
|
|
||||||
F48 = 41,
|
|
||||||
F50 = 42,
|
|
||||||
F52 = 43,
|
|
||||||
F54 = 44,
|
|
||||||
F56 = 45,
|
|
||||||
F58 = 46,
|
|
||||||
F60 = 47,
|
|
||||||
F62 = 48,
|
|
||||||
FCC0 = 49,
|
|
||||||
FCC1 = 50,
|
|
||||||
FCC2 = 51,
|
|
||||||
FCC3 = 52,
|
|
||||||
G0 = 53,
|
|
||||||
G1 = 54,
|
|
||||||
G2 = 55,
|
|
||||||
G3 = 56,
|
|
||||||
G4 = 57,
|
|
||||||
G5 = 58,
|
|
||||||
G6 = 59,
|
|
||||||
G7 = 60,
|
|
||||||
I0 = 61,
|
|
||||||
I1 = 62,
|
|
||||||
I2 = 63,
|
|
||||||
I3 = 64,
|
|
||||||
I4 = 65,
|
|
||||||
I5 = 66,
|
|
||||||
FP = 67,
|
|
||||||
I7 = 68,
|
|
||||||
ICC = 69,
|
|
||||||
L0 = 70,
|
|
||||||
L1 = 71,
|
|
||||||
L2 = 72,
|
|
||||||
L3 = 73,
|
|
||||||
L4 = 74,
|
|
||||||
L5 = 75,
|
|
||||||
L6 = 76,
|
|
||||||
L7 = 77,
|
|
||||||
O0 = 78,
|
|
||||||
O1 = 79,
|
|
||||||
O2 = 80,
|
|
||||||
O3 = 81,
|
|
||||||
O4 = 82,
|
|
||||||
O5 = 83,
|
|
||||||
SP = 84,
|
|
||||||
O7 = 85,
|
|
||||||
Y = 86,
|
|
||||||
XCC = 87,
|
|
||||||
PC = 88,
|
|
||||||
}
|
|
|
@ -1,158 +0,0 @@
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
pub const API_MAJOR: u64 = 1;
|
|
||||||
pub const API_MINOR: u64 = 0;
|
|
||||||
pub const VERSION_MAJOR: u64 = 1;
|
|
||||||
pub const VERSION_MINOR: u64 = 0;
|
|
||||||
pub const VERSION_EXTRA: u64 = 2;
|
|
||||||
pub const SECOND_SCALE: u64 = 1_000_000;
|
|
||||||
pub const MILISECOND_SCALE: u64 = 1_000;
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum uc_error {
|
|
||||||
OK = 0,
|
|
||||||
NOMEM = 1,
|
|
||||||
ARCH = 2,
|
|
||||||
HANDLE = 3,
|
|
||||||
MODE = 4,
|
|
||||||
VERSION = 5,
|
|
||||||
READ_UNMAPPED = 6,
|
|
||||||
WRITE_UNMAPPED = 7,
|
|
||||||
FETCH_UNMAPPED = 8,
|
|
||||||
HOOK = 9,
|
|
||||||
INSN_INVALID = 10,
|
|
||||||
MAP = 11,
|
|
||||||
WRITE_PROT = 12,
|
|
||||||
READ_PROT = 13,
|
|
||||||
FETCH_PROT = 14,
|
|
||||||
ARG = 15,
|
|
||||||
READ_UNALIGNED = 16,
|
|
||||||
WRITE_UNALIGNED = 17,
|
|
||||||
FETCH_UNALIGNED = 18,
|
|
||||||
HOOK_EXIST = 19,
|
|
||||||
RESOURCE = 20,
|
|
||||||
EXCEPTION = 21,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum MemType {
|
|
||||||
READ = 16,
|
|
||||||
WRITE = 17,
|
|
||||||
FETCH = 18,
|
|
||||||
READ_UNMAPPED = 19,
|
|
||||||
WRITE_UNMAPPED = 20,
|
|
||||||
FETCH_UNMAPPED = 21,
|
|
||||||
WRITE_PROT = 22,
|
|
||||||
READ_PROT = 23,
|
|
||||||
FETCH_PROT = 24,
|
|
||||||
READ_AFTER = 25,
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct HookType: i32 {
|
|
||||||
const INTR = 1;
|
|
||||||
const INSN = 2;
|
|
||||||
const CODE = 4;
|
|
||||||
const BLOCK = 8;
|
|
||||||
|
|
||||||
const MEM_READ_UNMAPPED = 0x10;
|
|
||||||
const MEM_WRITE_UNMAPPED = 0x20;
|
|
||||||
const MEM_FETCH_UNMAPPED = 0x40;
|
|
||||||
const MEM_UNMAPPED = Self::MEM_READ_UNMAPPED.bits | Self::MEM_WRITE_UNMAPPED.bits | Self::MEM_FETCH_UNMAPPED.bits;
|
|
||||||
|
|
||||||
const MEM_READ_PROT = 0x80;
|
|
||||||
const MEM_WRITE_PROT = 0x100;
|
|
||||||
const MEM_FETCH_PROT = 0x200;
|
|
||||||
const MEM_PROT = Self::MEM_READ_PROT.bits | Self::MEM_WRITE_PROT.bits | Self::MEM_FETCH_PROT.bits;
|
|
||||||
|
|
||||||
const MEM_READ = 0x400;
|
|
||||||
const MEM_WRITE = 0x800;
|
|
||||||
const MEM_FETCH = 0x1000;
|
|
||||||
const MEM_VALID = Self::MEM_READ.bits | Self::MEM_WRITE.bits | Self::MEM_FETCH.bits;
|
|
||||||
|
|
||||||
const MEM_READ_AFTER = 0x2000;
|
|
||||||
|
|
||||||
const INSN_INVALID = 0x4000;
|
|
||||||
|
|
||||||
const MEM_READ_INVALID = Self::MEM_READ_UNMAPPED.bits | Self::MEM_READ_PROT.bits;
|
|
||||||
const MEM_WRITE_INVALID = Self::MEM_WRITE_UNMAPPED.bits | Self::MEM_WRITE_PROT.bits;
|
|
||||||
const MEM_FETCH_INVALID = Self::MEM_FETCH_UNMAPPED.bits | Self::MEM_FETCH_PROT.bits;
|
|
||||||
const MEM_INVALID = Self::MEM_READ_INVALID.bits | Self::MEM_WRITE_INVALID.bits | Self::MEM_FETCH_INVALID.bits;
|
|
||||||
|
|
||||||
const MEM_ALL = Self::MEM_VALID.bits | Self::MEM_INVALID.bits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum Query {
|
|
||||||
MODE = 1,
|
|
||||||
PAGE_SIZE = 2,
|
|
||||||
ARCH = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Permission : u32 {
|
|
||||||
const NONE = 0;
|
|
||||||
const READ = 1;
|
|
||||||
const WRITE = 2;
|
|
||||||
const EXEC = 4;
|
|
||||||
const ALL = Self::READ.bits | Self::WRITE.bits | Self::EXEC.bits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct MemRegion {
|
|
||||||
pub begin: u64,
|
|
||||||
pub end: u64,
|
|
||||||
pub perms: Permission,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum Arch {
|
|
||||||
ARM = 1,
|
|
||||||
ARM64 = 2,
|
|
||||||
MIPS = 3,
|
|
||||||
X86 = 4,
|
|
||||||
PPC = 5,
|
|
||||||
SPARC = 6,
|
|
||||||
M68K = 7,
|
|
||||||
MAX = 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Mode: i32 {
|
|
||||||
const LITTLE_ENDIAN = 0;
|
|
||||||
const BIG_ENDIAN = 0x4000_0000;
|
|
||||||
|
|
||||||
const ARM = 0;
|
|
||||||
const THUMB = 0x10;
|
|
||||||
const MCLASS = 0x20;
|
|
||||||
const V8 = 0x40;
|
|
||||||
const ARM926 = 0x80;
|
|
||||||
const ARM946 = 0x100;
|
|
||||||
const ARM1176 = 0x200;
|
|
||||||
const MICRO = Self::THUMB.bits;
|
|
||||||
const MIPS3 = Self::MCLASS.bits;
|
|
||||||
const MIPS32R6 = Self::V8.bits;
|
|
||||||
const MIPS32 = 4;
|
|
||||||
const MIPS64 = 8;
|
|
||||||
const MODE_16 = 2;
|
|
||||||
const MODE_32 = Self::MIPS32.bits;
|
|
||||||
const MODE_64 = Self::MIPS64.bits;
|
|
||||||
const PPC32 = Self::MIPS32.bits;
|
|
||||||
const PPC64 = Self::MIPS64.bits;
|
|
||||||
const QPX = Self::THUMB.bits;
|
|
||||||
const SPARC32 = Self::MIPS32.bits;
|
|
||||||
const SPARC64 = Self::MIPS64.bits;
|
|
||||||
const V9 = Self::THUMB.bits;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,281 +0,0 @@
|
||||||
// X86 registers
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum RegisterX86 {
|
|
||||||
INVALID = 0,
|
|
||||||
AH,
|
|
||||||
AL,
|
|
||||||
AX,
|
|
||||||
BH,
|
|
||||||
BL,
|
|
||||||
BP,
|
|
||||||
BPL,
|
|
||||||
BX,
|
|
||||||
CH,
|
|
||||||
CL,
|
|
||||||
CS,
|
|
||||||
CX,
|
|
||||||
DH,
|
|
||||||
DI,
|
|
||||||
DIL,
|
|
||||||
DL,
|
|
||||||
DS,
|
|
||||||
DX,
|
|
||||||
EAX,
|
|
||||||
EBP,
|
|
||||||
EBX,
|
|
||||||
ECX,
|
|
||||||
EDI,
|
|
||||||
EDX,
|
|
||||||
EFLAGS,
|
|
||||||
EIP,
|
|
||||||
EIZ,
|
|
||||||
ES,
|
|
||||||
ESI,
|
|
||||||
ESP,
|
|
||||||
FPSW,
|
|
||||||
FS,
|
|
||||||
GS,
|
|
||||||
IP,
|
|
||||||
RAX,
|
|
||||||
RBP,
|
|
||||||
RBX,
|
|
||||||
RCX,
|
|
||||||
RDI,
|
|
||||||
RDX,
|
|
||||||
RIP,
|
|
||||||
RIZ,
|
|
||||||
RSI,
|
|
||||||
RSP,
|
|
||||||
SI,
|
|
||||||
SIL,
|
|
||||||
SP,
|
|
||||||
SPL,
|
|
||||||
SS,
|
|
||||||
CR0,
|
|
||||||
CR1,
|
|
||||||
CR2,
|
|
||||||
CR3,
|
|
||||||
CR4,
|
|
||||||
CR5,
|
|
||||||
CR6,
|
|
||||||
CR7,
|
|
||||||
CR8,
|
|
||||||
CR9,
|
|
||||||
CR10,
|
|
||||||
CR11,
|
|
||||||
CR12,
|
|
||||||
CR13,
|
|
||||||
CR14,
|
|
||||||
CR15,
|
|
||||||
DR0,
|
|
||||||
DR1,
|
|
||||||
DR2,
|
|
||||||
DR3,
|
|
||||||
DR4,
|
|
||||||
DR5,
|
|
||||||
DR6,
|
|
||||||
DR7,
|
|
||||||
DR8,
|
|
||||||
DR9,
|
|
||||||
DR10,
|
|
||||||
DR11,
|
|
||||||
DR12,
|
|
||||||
DR13,
|
|
||||||
DR14,
|
|
||||||
DR15,
|
|
||||||
FP0,
|
|
||||||
FP1,
|
|
||||||
FP2,
|
|
||||||
FP3,
|
|
||||||
FP4,
|
|
||||||
FP5,
|
|
||||||
FP6,
|
|
||||||
FP7,
|
|
||||||
K0,
|
|
||||||
K1,
|
|
||||||
K2,
|
|
||||||
K3,
|
|
||||||
K4,
|
|
||||||
K5,
|
|
||||||
K6,
|
|
||||||
K7,
|
|
||||||
MM0,
|
|
||||||
MM1,
|
|
||||||
MM2,
|
|
||||||
MM3,
|
|
||||||
MM4,
|
|
||||||
MM5,
|
|
||||||
MM6,
|
|
||||||
MM7,
|
|
||||||
R8,
|
|
||||||
R9,
|
|
||||||
R10,
|
|
||||||
R11,
|
|
||||||
R12,
|
|
||||||
R13,
|
|
||||||
R14,
|
|
||||||
R15,
|
|
||||||
ST0,
|
|
||||||
ST1,
|
|
||||||
ST2,
|
|
||||||
ST3,
|
|
||||||
ST4,
|
|
||||||
ST5,
|
|
||||||
ST6,
|
|
||||||
ST7,
|
|
||||||
XMM0,
|
|
||||||
XMM1,
|
|
||||||
XMM2,
|
|
||||||
XMM3,
|
|
||||||
XMM4,
|
|
||||||
XMM5,
|
|
||||||
XMM6,
|
|
||||||
XMM7,
|
|
||||||
XMM8,
|
|
||||||
XMM9,
|
|
||||||
XMM10,
|
|
||||||
XMM11,
|
|
||||||
XMM12,
|
|
||||||
XMM13,
|
|
||||||
XMM14,
|
|
||||||
XMM15,
|
|
||||||
XMM16,
|
|
||||||
XMM17,
|
|
||||||
XMM18,
|
|
||||||
XMM19,
|
|
||||||
XMM20,
|
|
||||||
XMM21,
|
|
||||||
XMM22,
|
|
||||||
XMM23,
|
|
||||||
XMM24,
|
|
||||||
XMM25,
|
|
||||||
XMM26,
|
|
||||||
XMM27,
|
|
||||||
XMM28,
|
|
||||||
XMM29,
|
|
||||||
XMM30,
|
|
||||||
XMM31,
|
|
||||||
YMM0,
|
|
||||||
YMM1,
|
|
||||||
YMM2,
|
|
||||||
YMM3,
|
|
||||||
YMM4,
|
|
||||||
YMM5,
|
|
||||||
YMM6,
|
|
||||||
YMM7,
|
|
||||||
YMM8,
|
|
||||||
YMM9,
|
|
||||||
YMM10,
|
|
||||||
YMM11,
|
|
||||||
YMM12,
|
|
||||||
YMM13,
|
|
||||||
YMM14,
|
|
||||||
YMM15,
|
|
||||||
YMM16,
|
|
||||||
YMM17,
|
|
||||||
YMM18,
|
|
||||||
YMM19,
|
|
||||||
YMM20,
|
|
||||||
YMM21,
|
|
||||||
YMM22,
|
|
||||||
YMM23,
|
|
||||||
YMM24,
|
|
||||||
YMM25,
|
|
||||||
YMM26,
|
|
||||||
YMM27,
|
|
||||||
YMM28,
|
|
||||||
YMM29,
|
|
||||||
YMM30,
|
|
||||||
YMM31,
|
|
||||||
ZMM0,
|
|
||||||
ZMM1,
|
|
||||||
ZMM2,
|
|
||||||
ZMM3,
|
|
||||||
ZMM4,
|
|
||||||
ZMM5,
|
|
||||||
ZMM6,
|
|
||||||
ZMM7,
|
|
||||||
ZMM8,
|
|
||||||
ZMM9,
|
|
||||||
ZMM10,
|
|
||||||
ZMM11,
|
|
||||||
ZMM12,
|
|
||||||
ZMM13,
|
|
||||||
ZMM14,
|
|
||||||
ZMM15,
|
|
||||||
ZMM16,
|
|
||||||
ZMM17,
|
|
||||||
ZMM18,
|
|
||||||
ZMM19,
|
|
||||||
ZMM20,
|
|
||||||
ZMM21,
|
|
||||||
ZMM22,
|
|
||||||
ZMM23,
|
|
||||||
ZMM24,
|
|
||||||
ZMM25,
|
|
||||||
ZMM26,
|
|
||||||
ZMM27,
|
|
||||||
ZMM28,
|
|
||||||
ZMM29,
|
|
||||||
ZMM30,
|
|
||||||
ZMM31,
|
|
||||||
R8B,
|
|
||||||
R9B,
|
|
||||||
R10B,
|
|
||||||
R11B,
|
|
||||||
R12B,
|
|
||||||
R13B,
|
|
||||||
R14B,
|
|
||||||
R15B,
|
|
||||||
R8D,
|
|
||||||
R9D,
|
|
||||||
R10D,
|
|
||||||
R11D,
|
|
||||||
R12D,
|
|
||||||
R13D,
|
|
||||||
R14D,
|
|
||||||
R15D,
|
|
||||||
R8W,
|
|
||||||
R9W,
|
|
||||||
R10W,
|
|
||||||
R11W,
|
|
||||||
R12W,
|
|
||||||
R13W,
|
|
||||||
R14W,
|
|
||||||
R15W,
|
|
||||||
IDTR,
|
|
||||||
GDTR,
|
|
||||||
LDTR,
|
|
||||||
TR,
|
|
||||||
FPCW,
|
|
||||||
FPTAG,
|
|
||||||
MSR,
|
|
||||||
MXCSR,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum InsnX86 {
|
|
||||||
IN = 218,
|
|
||||||
OUT = 500,
|
|
||||||
SYSCALL = 699,
|
|
||||||
SYSENTER = 700,
|
|
||||||
RET = 151,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub enum InsnSysX86 {
|
|
||||||
SYSCALL = InsnX86::SYSCALL as isize,
|
|
||||||
SYSENTER = InsnX86::SYSENTER as isize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
|
||||||
pub struct X86Mmr {
|
|
||||||
pub selector: u64,
|
|
||||||
pub base: u64,
|
|
||||||
pub limit: u32,
|
|
||||||
pub flags: u32,
|
|
||||||
}
|
|
|
@ -1,683 +0,0 @@
|
||||||
#![deny(rust_2018_idioms)]
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use unicorn::unicorn_const::{uc_error, Arch, HookType, MemType, Mode, Permission, SECOND_SCALE};
|
|
||||||
use unicorn::{InsnSysX86, RegisterARM, RegisterMIPS, RegisterPPC, RegisterX86};
|
|
||||||
|
|
||||||
pub static X86_REGISTERS: [RegisterX86; 145] = [
|
|
||||||
RegisterX86::AH,
|
|
||||||
RegisterX86::AL,
|
|
||||||
RegisterX86::AX,
|
|
||||||
RegisterX86::BH,
|
|
||||||
RegisterX86::BL,
|
|
||||||
RegisterX86::BP,
|
|
||||||
RegisterX86::BPL,
|
|
||||||
RegisterX86::BX,
|
|
||||||
RegisterX86::CH,
|
|
||||||
RegisterX86::CL,
|
|
||||||
RegisterX86::CS,
|
|
||||||
RegisterX86::CX,
|
|
||||||
RegisterX86::DH,
|
|
||||||
RegisterX86::DI,
|
|
||||||
RegisterX86::DIL,
|
|
||||||
RegisterX86::DL,
|
|
||||||
RegisterX86::DS,
|
|
||||||
RegisterX86::DX,
|
|
||||||
RegisterX86::EAX,
|
|
||||||
RegisterX86::EBP,
|
|
||||||
RegisterX86::EBX,
|
|
||||||
RegisterX86::ECX,
|
|
||||||
RegisterX86::EDI,
|
|
||||||
RegisterX86::EDX,
|
|
||||||
RegisterX86::EFLAGS,
|
|
||||||
RegisterX86::EIP,
|
|
||||||
RegisterX86::EIZ,
|
|
||||||
RegisterX86::ES,
|
|
||||||
RegisterX86::ESI,
|
|
||||||
RegisterX86::ESP,
|
|
||||||
RegisterX86::FPSW,
|
|
||||||
RegisterX86::FS,
|
|
||||||
RegisterX86::GS,
|
|
||||||
RegisterX86::IP,
|
|
||||||
RegisterX86::RAX,
|
|
||||||
RegisterX86::RBP,
|
|
||||||
RegisterX86::RBX,
|
|
||||||
RegisterX86::RCX,
|
|
||||||
RegisterX86::RDI,
|
|
||||||
RegisterX86::RDX,
|
|
||||||
RegisterX86::RIP,
|
|
||||||
RegisterX86::RIZ,
|
|
||||||
RegisterX86::RSI,
|
|
||||||
RegisterX86::RSP,
|
|
||||||
RegisterX86::SI,
|
|
||||||
RegisterX86::SIL,
|
|
||||||
RegisterX86::SP,
|
|
||||||
RegisterX86::SPL,
|
|
||||||
RegisterX86::SS,
|
|
||||||
RegisterX86::CR0,
|
|
||||||
RegisterX86::CR1,
|
|
||||||
RegisterX86::CR2,
|
|
||||||
RegisterX86::CR3,
|
|
||||||
RegisterX86::CR4,
|
|
||||||
RegisterX86::CR5,
|
|
||||||
RegisterX86::CR6,
|
|
||||||
RegisterX86::CR7,
|
|
||||||
RegisterX86::CR8,
|
|
||||||
RegisterX86::CR9,
|
|
||||||
RegisterX86::CR10,
|
|
||||||
RegisterX86::CR11,
|
|
||||||
RegisterX86::CR12,
|
|
||||||
RegisterX86::CR13,
|
|
||||||
RegisterX86::CR14,
|
|
||||||
RegisterX86::CR15,
|
|
||||||
RegisterX86::DR0,
|
|
||||||
RegisterX86::DR1,
|
|
||||||
RegisterX86::DR2,
|
|
||||||
RegisterX86::DR3,
|
|
||||||
RegisterX86::DR4,
|
|
||||||
RegisterX86::DR5,
|
|
||||||
RegisterX86::DR6,
|
|
||||||
RegisterX86::DR7,
|
|
||||||
RegisterX86::DR8,
|
|
||||||
RegisterX86::DR9,
|
|
||||||
RegisterX86::DR10,
|
|
||||||
RegisterX86::DR11,
|
|
||||||
RegisterX86::DR12,
|
|
||||||
RegisterX86::DR13,
|
|
||||||
RegisterX86::DR14,
|
|
||||||
RegisterX86::DR15,
|
|
||||||
RegisterX86::FP0,
|
|
||||||
RegisterX86::FP1,
|
|
||||||
RegisterX86::FP2,
|
|
||||||
RegisterX86::FP3,
|
|
||||||
RegisterX86::FP4,
|
|
||||||
RegisterX86::FP5,
|
|
||||||
RegisterX86::FP6,
|
|
||||||
RegisterX86::FP7,
|
|
||||||
RegisterX86::K0,
|
|
||||||
RegisterX86::K1,
|
|
||||||
RegisterX86::K2,
|
|
||||||
RegisterX86::K3,
|
|
||||||
RegisterX86::K4,
|
|
||||||
RegisterX86::K5,
|
|
||||||
RegisterX86::K6,
|
|
||||||
RegisterX86::K7,
|
|
||||||
RegisterX86::MM0,
|
|
||||||
RegisterX86::MM1,
|
|
||||||
RegisterX86::MM2,
|
|
||||||
RegisterX86::MM3,
|
|
||||||
RegisterX86::MM4,
|
|
||||||
RegisterX86::MM5,
|
|
||||||
RegisterX86::MM6,
|
|
||||||
RegisterX86::MM7,
|
|
||||||
RegisterX86::R8,
|
|
||||||
RegisterX86::R9,
|
|
||||||
RegisterX86::R10,
|
|
||||||
RegisterX86::R11,
|
|
||||||
RegisterX86::R12,
|
|
||||||
RegisterX86::R13,
|
|
||||||
RegisterX86::R14,
|
|
||||||
RegisterX86::R15,
|
|
||||||
RegisterX86::ST0,
|
|
||||||
RegisterX86::ST1,
|
|
||||||
RegisterX86::ST2,
|
|
||||||
RegisterX86::ST3,
|
|
||||||
RegisterX86::ST4,
|
|
||||||
RegisterX86::ST5,
|
|
||||||
RegisterX86::ST6,
|
|
||||||
RegisterX86::ST7,
|
|
||||||
RegisterX86::R8B,
|
|
||||||
RegisterX86::R9B,
|
|
||||||
RegisterX86::R10B,
|
|
||||||
RegisterX86::R11B,
|
|
||||||
RegisterX86::R12B,
|
|
||||||
RegisterX86::R13B,
|
|
||||||
RegisterX86::R14B,
|
|
||||||
RegisterX86::R15B,
|
|
||||||
RegisterX86::R8D,
|
|
||||||
RegisterX86::R9D,
|
|
||||||
RegisterX86::R10D,
|
|
||||||
RegisterX86::R11D,
|
|
||||||
RegisterX86::R12D,
|
|
||||||
RegisterX86::R13D,
|
|
||||||
RegisterX86::R14D,
|
|
||||||
RegisterX86::R15D,
|
|
||||||
RegisterX86::R8W,
|
|
||||||
RegisterX86::R9W,
|
|
||||||
RegisterX86::R10W,
|
|
||||||
RegisterX86::R11W,
|
|
||||||
RegisterX86::R12W,
|
|
||||||
RegisterX86::R13W,
|
|
||||||
RegisterX86::R14W,
|
|
||||||
RegisterX86::R15W,
|
|
||||||
];
|
|
||||||
|
|
||||||
type Unicorn<'a> = unicorn::UnicornHandle<'a>;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn emulate_x86() {
|
|
||||||
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.reg_write(RegisterX86::EAX as i32, 123), Ok(()));
|
|
||||||
assert_eq!(emu.reg_read(RegisterX86::EAX as i32), Ok(123));
|
|
||||||
|
|
||||||
// Attempt to write to memory before mapping it.
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_write(0x1000, &x86_code32),
|
|
||||||
(Err(uc_error::WRITE_UNMAPPED))
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_read_as_vec(0x1000, x86_code32.len()),
|
|
||||||
Ok(x86_code32.clone())
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(emu.reg_write(RegisterX86::ECX as i32, 10), Ok(()));
|
|
||||||
assert_eq!(emu.reg_write(RegisterX86::EDX as i32, 50), Ok(()));
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
(0x1000 + x86_code32.len()) as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.reg_read(RegisterX86::ECX as i32), Ok(11));
|
|
||||||
assert_eq!(emu.reg_read(RegisterX86::EDX as i32), Ok(49));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x86_code_callback() {
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
struct CodeExpectation(u64, u32);
|
|
||||||
let expects = vec![CodeExpectation(0x1000, 1), CodeExpectation(0x1001, 1)];
|
|
||||||
let codes: Vec<CodeExpectation> = Vec::new();
|
|
||||||
let codes_cell = Rc::new(RefCell::new(codes));
|
|
||||||
|
|
||||||
let callback_codes = codes_cell.clone();
|
|
||||||
let callback = move |_: Unicorn<'_>, address: u64, size: u32| {
|
|
||||||
let mut codes = callback_codes.borrow_mut();
|
|
||||||
codes.push(CodeExpectation(address, size));
|
|
||||||
};
|
|
||||||
|
|
||||||
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
|
|
||||||
let hook = emu
|
|
||||||
.add_code_hook(0x1000, 0x2000, callback)
|
|
||||||
.expect("failed to add code hook");
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(0x1000, 0x1002, 10 * SECOND_SCALE, 1000),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(expects, *codes_cell.borrow());
|
|
||||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x86_intr_callback() {
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
struct IntrExpectation(u32);
|
|
||||||
let expect = IntrExpectation(0x80);
|
|
||||||
let intr_cell = Rc::new(RefCell::new(IntrExpectation(0)));
|
|
||||||
|
|
||||||
let callback_intr = intr_cell.clone();
|
|
||||||
let callback = move |_: Unicorn<'_>, intno: u32| {
|
|
||||||
*callback_intr.borrow_mut() = IntrExpectation(intno);
|
|
||||||
};
|
|
||||||
|
|
||||||
let x86_code32: Vec<u8> = vec![0xcd, 0x80]; // INT 0x80;
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
|
|
||||||
let hook = emu
|
|
||||||
.add_intr_hook(callback)
|
|
||||||
.expect("failed to add intr hook");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
0x1000 + x86_code32.len() as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(expect, *intr_cell.borrow());
|
|
||||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x86_mem_callback() {
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
struct MemExpectation(MemType, u64, usize, i64);
|
|
||||||
let expects = vec![
|
|
||||||
MemExpectation(MemType::WRITE, 0x2000, 4, 0xdeadbeef),
|
|
||||||
MemExpectation(MemType::READ_UNMAPPED, 0x10000, 4, 0),
|
|
||||||
MemExpectation(MemType::READ, 0x10000, 4, 0),
|
|
||||||
];
|
|
||||||
let mems: Vec<MemExpectation> = Vec::new();
|
|
||||||
let mems_cell = Rc::new(RefCell::new(mems));
|
|
||||||
|
|
||||||
let callback_mems = mems_cell.clone();
|
|
||||||
let callback =
|
|
||||||
move |_: Unicorn<'_>, mem_type: MemType, address: u64, size: usize, value: i64| {
|
|
||||||
let mut mems = callback_mems.borrow_mut();
|
|
||||||
mems.push(MemExpectation(mem_type, address, size, value));
|
|
||||||
};
|
|
||||||
|
|
||||||
// mov eax, 0xdeadbeef;
|
|
||||||
// mov [0x2000], eax;
|
|
||||||
// mov eax, [0x10000];
|
|
||||||
let x86_code32: Vec<u8> = vec![
|
|
||||||
0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xA3, 0x00, 0x20, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x01, 0x00,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
|
|
||||||
let hook = emu
|
|
||||||
.add_mem_hook(HookType::MEM_ALL, 0, std::u64::MAX, callback)
|
|
||||||
.expect("failed to add memory hook");
|
|
||||||
assert_eq!(emu.reg_write(RegisterX86::EAX as i32, 0x123), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
0x1000 + x86_code32.len() as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
0x1000
|
|
||||||
),
|
|
||||||
Err(uc_error::READ_UNMAPPED)
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(expects, *mems_cell.borrow());
|
|
||||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x86_insn_in_callback() {
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
struct InsnInExpectation(u32, usize);
|
|
||||||
let expect = InsnInExpectation(0x10, 4);
|
|
||||||
let insn_cell = Rc::new(RefCell::new(InsnInExpectation(0, 0)));
|
|
||||||
|
|
||||||
let callback_insn = insn_cell.clone();
|
|
||||||
let callback = move |_: Unicorn<'_>, port: u32, size: usize| {
|
|
||||||
*callback_insn.borrow_mut() = InsnInExpectation(port, size);
|
|
||||||
};
|
|
||||||
|
|
||||||
let x86_code32: Vec<u8> = vec![0xe5, 0x10]; // IN eax, 0x10;
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
|
|
||||||
let hook = emu
|
|
||||||
.add_insn_in_hook(callback)
|
|
||||||
.expect("failed to add in hook");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
0x1000 + x86_code32.len() as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(expect, *insn_cell.borrow());
|
|
||||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x86_insn_out_callback() {
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
struct InsnOutExpectation(u32, usize, u32);
|
|
||||||
let expect = InsnOutExpectation(0x46, 1, 0x32);
|
|
||||||
let insn_cell = Rc::new(RefCell::new(InsnOutExpectation(0, 0, 0)));
|
|
||||||
|
|
||||||
let callback_insn = insn_cell.clone();
|
|
||||||
let callback = move |_: Unicorn<'_>, port: u32, size: usize, value: u32| {
|
|
||||||
*callback_insn.borrow_mut() = InsnOutExpectation(port, size, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
let x86_code32: Vec<u8> = vec![0xb0, 0x32, 0xe6, 0x46]; // MOV al, 0x32; OUT 0x46, al;
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
|
|
||||||
let hook = emu
|
|
||||||
.add_insn_out_hook(callback)
|
|
||||||
.expect("failed to add out hook");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
0x1000 + x86_code32.len() as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(expect, *insn_cell.borrow());
|
|
||||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x86_insn_sys_callback() {
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
struct InsnSysExpectation(u64);
|
|
||||||
let expect = InsnSysExpectation(0xdeadbeef);
|
|
||||||
let insn_cell = Rc::new(RefCell::new(InsnSysExpectation(0)));
|
|
||||||
|
|
||||||
let callback_insn = insn_cell.clone();
|
|
||||||
let callback = move |uc: Unicorn<'_>| {
|
|
||||||
println!("!!!!");
|
|
||||||
let rax = uc.reg_read(RegisterX86::RAX as i32).unwrap();
|
|
||||||
*callback_insn.borrow_mut() = InsnSysExpectation(rax);
|
|
||||||
};
|
|
||||||
|
|
||||||
// MOV rax, 0xdeadbeef; SYSCALL;
|
|
||||||
let x86_code: Vec<u8> = vec![
|
|
||||||
0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x05,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_64)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code), Ok(()));
|
|
||||||
|
|
||||||
let hook = emu
|
|
||||||
.add_insn_sys_hook(InsnSysX86::SYSCALL, 1, 0, callback)
|
|
||||||
.expect("failed to add syscall hook");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
0x1000 + x86_code.len() as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(expect, *insn_cell.borrow());
|
|
||||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn emulate_arm() {
|
|
||||||
let arm_code32: Vec<u8> = vec![0x83, 0xb0]; // sub sp, #0xc
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::ARM, Mode::THUMB)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.reg_write(RegisterARM::R1 as i32, 123), Ok(()));
|
|
||||||
assert_eq!(emu.reg_read(RegisterARM::R1 as i32), Ok(123));
|
|
||||||
|
|
||||||
// Attempt to write to memory before mapping it.
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_write(0x1000, &arm_code32),
|
|
||||||
(Err(uc_error::WRITE_UNMAPPED))
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &arm_code32), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_read_as_vec(0x1000, arm_code32.len()),
|
|
||||||
Ok(arm_code32.clone())
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(emu.reg_write(RegisterARM::SP as i32, 12), Ok(()));
|
|
||||||
assert_eq!(emu.reg_write(RegisterARM::R0 as i32, 10), Ok(()));
|
|
||||||
|
|
||||||
// ARM checks the least significant bit of the address to know
|
|
||||||
// if the code is in Thumb mode.
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000 | 0x01,
|
|
||||||
(0x1000 | (0x01 + arm_code32.len())) as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.reg_read(RegisterARM::SP as i32), Ok(0));
|
|
||||||
assert_eq!(emu.reg_read(RegisterARM::R0 as i32), Ok(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn emulate_mips() {
|
|
||||||
let mips_code32 = vec![0x56, 0x34, 0x21, 0x34]; // ori $at, $at, 0x3456;
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::MIPS, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &mips_code32), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_read_as_vec(0x1000, mips_code32.len()),
|
|
||||||
Ok(mips_code32.clone())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.reg_write(RegisterMIPS::AT as i32, 0), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
(0x1000 + mips_code32.len()) as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.reg_read(RegisterMIPS::AT as i32), Ok(0x3456));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn emulate_ppc() {
|
|
||||||
let ppc_code32 = vec![0x7F, 0x46, 0x1A, 0x14]; // add 26, 6, 3
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::PPC, Mode::PPC32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &ppc_code32), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_read_as_vec(0x1000, ppc_code32.len()),
|
|
||||||
Ok(ppc_code32.clone())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.reg_write(RegisterPPC::GPR3 as i32, 42), Ok(()));
|
|
||||||
assert_eq!(emu.reg_write(RegisterPPC::GPR6 as i32, 1337), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
(0x1000 + ppc_code32.len()) as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.reg_read(RegisterPPC::GPR26 as i32), Ok(1379));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mem_unmapping() {
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_unmap(0x1000, 0x4000), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mem_map_ptr() {
|
|
||||||
// Use an array for the emulator memory.
|
|
||||||
let mut mem: [u8; 4000] = [0; 4000];
|
|
||||||
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
|
|
||||||
// Attempt to write to memory before mapping it.
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_write(0x1000, &x86_code32),
|
|
||||||
(Err(uc_error::WRITE_UNMAPPED))
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_map_ptr(0x1000, 0x4000, Permission::ALL, mem.as_mut_ptr() as _),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_read_as_vec(0x1000, x86_code32.len()),
|
|
||||||
Ok(x86_code32.clone())
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(emu.reg_write(RegisterX86::ECX as i32, 10), Ok(()));
|
|
||||||
assert_eq!(emu.reg_write(RegisterX86::EDX as i32, 50), Ok(()));
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
(0x1000 + x86_code32.len()) as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.reg_read(RegisterX86::ECX as i32), Ok(11));
|
|
||||||
assert_eq!(emu.reg_read(RegisterX86::EDX as i32), Ok(49));
|
|
||||||
assert_eq!(emu.mem_unmap(0x1000, 0x4000), Ok(()));
|
|
||||||
|
|
||||||
// Use a Vec for the emulator memory.
|
|
||||||
let mut mem: Vec<u8> = Vec::new();
|
|
||||||
mem.reserve(4000);
|
|
||||||
|
|
||||||
// Attempt to write to memory before mapping it.
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_write(0x1000, &x86_code32),
|
|
||||||
(Err(uc_error::WRITE_UNMAPPED))
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_map_ptr(0x1000, 0x4000, Permission::ALL, mem.as_mut_ptr() as _),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
assert_eq!(
|
|
||||||
emu.mem_read_as_vec(0x1000, x86_code32.len()),
|
|
||||||
Ok(x86_code32.clone())
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(emu.reg_write(RegisterX86::ECX as i32, 10), Ok(()));
|
|
||||||
assert_eq!(emu.reg_write(RegisterX86::EDX as i32, 50), Ok(()));
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
(0x1000 + x86_code32.len()) as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000
|
|
||||||
),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(emu.reg_read(RegisterX86::ECX as i32), Ok(11));
|
|
||||||
assert_eq!(emu.reg_read(RegisterX86::EDX as i32), Ok(49));
|
|
||||||
assert_eq!(emu.mem_unmap(0x1000, 0x4000), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x86_context_save_and_restore() {
|
|
||||||
for mode in vec![Mode::MODE_32, Mode::MODE_64] {
|
|
||||||
let x86_code: Vec<u8> = vec![
|
|
||||||
0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x05,
|
|
||||||
];
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, mode)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code), Ok(()));
|
|
||||||
let _ = emu.emu_start(
|
|
||||||
0x1000,
|
|
||||||
(0x1000 + x86_code.len()) as u64,
|
|
||||||
10 * SECOND_SCALE,
|
|
||||||
1000,
|
|
||||||
);
|
|
||||||
|
|
||||||
/* now, save the context... */
|
|
||||||
let context = emu.context_init();
|
|
||||||
let context = context.unwrap();
|
|
||||||
|
|
||||||
/* and create a new emulator, into which we will "restore" that context */
|
|
||||||
let mut unicorn2 = unicorn::Unicorn::new(Arch::X86, mode)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let emu2 = unicorn2.borrow();
|
|
||||||
assert_eq!(emu2.context_restore(&context), Ok(()));
|
|
||||||
for register in X86_REGISTERS.iter() {
|
|
||||||
println!("Testing register {:?}", register);
|
|
||||||
assert_eq!(
|
|
||||||
emu2.reg_read(*register as i32),
|
|
||||||
emu.reg_read(*register as i32)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x86_block_callback() {
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
struct BlockExpectation(u64, u32);
|
|
||||||
let expects = vec![BlockExpectation(0x1000, 2), BlockExpectation(0x1000, 2)];
|
|
||||||
let blocks: Vec<BlockExpectation> = Vec::new();
|
|
||||||
let blocks_cell = Rc::new(RefCell::new(blocks));
|
|
||||||
|
|
||||||
let callback_blocks = blocks_cell.clone();
|
|
||||||
let callback = move |_: Unicorn<'_>, address: u64, size: u32| {
|
|
||||||
let mut blocks = callback_blocks.borrow_mut();
|
|
||||||
blocks.push(BlockExpectation(address, size));
|
|
||||||
};
|
|
||||||
|
|
||||||
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
|
|
||||||
|
|
||||||
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
|
|
||||||
.expect("failed to initialize unicorn instance");
|
|
||||||
let mut emu = unicorn.borrow();
|
|
||||||
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
|
|
||||||
assert_eq!(emu.mem_write(0x1000, &x86_code32), Ok(()));
|
|
||||||
|
|
||||||
let hook = emu
|
|
||||||
.add_block_hook(callback)
|
|
||||||
.expect("failed to add block hook");
|
|
||||||
assert_eq!(
|
|
||||||
emu.emu_start(0x1000, 0x1002, 10 * SECOND_SCALE, 1000),
|
|
||||||
Ok(())
|
|
||||||
);
|
|
||||||
assert_eq!(expects, *blocks_cell.borrow());
|
|
||||||
assert_eq!(emu.remove_hook(hook), Ok(()));
|
|
||||||
}
|
|
|
@ -59,7 +59,8 @@ Public Enum uc_arch
|
||||||
UC_ARCH_PPC = 5 ' PowerPC architecture (currently unsupported)
|
UC_ARCH_PPC = 5 ' PowerPC architecture (currently unsupported)
|
||||||
UC_ARCH_SPARC = 6 ' Sparc architecture
|
UC_ARCH_SPARC = 6 ' Sparc architecture
|
||||||
UC_ARCH_M68K = 7 ' M68K architecture
|
UC_ARCH_M68K = 7 ' M68K architecture
|
||||||
UC_ARCH_MAX = 8
|
UC_ARCH_RISCV = 8 ' RISCV architecture
|
||||||
|
UC_ARCH_MAX = 9
|
||||||
End Enum
|
End Enum
|
||||||
|
|
||||||
Public Enum uc_prot
|
Public Enum uc_prot
|
||||||
|
@ -130,6 +131,8 @@ Public Enum uc_mode 'from /bindings/dotnet/common.fs
|
||||||
' UC_MODE_SPARC32 = 4 '32-bit mode
|
' UC_MODE_SPARC32 = 4 '32-bit mode
|
||||||
' UC_MODE_SPARC64 = 8 '64-bit mode
|
' UC_MODE_SPARC64 = 8 '64-bit mode
|
||||||
' UC_MODE_V9 = 16 'SparcV9 mode (currently unsupported)
|
' UC_MODE_V9 = 16 'SparcV9 mode (currently unsupported)
|
||||||
|
' UC_MODE_RISCV32 = 4 '32-bit mode
|
||||||
|
' UC_MODE_RISCV64 = 8 '64-bit mode
|
||||||
End Enum
|
End Enum
|
||||||
|
|
||||||
Public Enum uc_hook_type 'from /bindings/dotnet/common.fs
|
Public Enum uc_hook_type 'from /bindings/dotnet/common.fs
|
||||||
|
|
37
cmake.sh
37
cmake.sh
|
@ -1,17 +1,40 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Unicorn Emulator Engine (www.unicorn-engine.org)
|
# Unicorn Emulator Engine (www.unicorn-engine.org)
|
||||||
# Usage: cmake.sh [x86] [arm] [aarch64] [m68k] [mips] [sparc]
|
# Usage: cmake.sh [mingw|msys] [x86] [arm] [aarch64] [m68k] [mips] [sparc] [ppc] [riscv]
|
||||||
# By chenhuitao 2019
|
# By chenhuitao 2019
|
||||||
|
|
||||||
FLAGS="-DCMAKE_BUILD_TYPE=Release"
|
# FLAGS="-DCMAKE_BUILD_TYPE=Release"
|
||||||
|
FLAGS="-DCMAKE_BUILD_TYPE=Debug"
|
||||||
|
TOOLCHAIN=""
|
||||||
|
GENERATOR="Unix Makefiles"
|
||||||
|
CMAKE="cmake"
|
||||||
|
COMPILER=""
|
||||||
|
|
||||||
UNICORN_ARCH="${*}"
|
# process arguments
|
||||||
|
case "$1" in
|
||||||
|
"mingw" )
|
||||||
|
TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=../mingw-w64.cmake"
|
||||||
|
shift
|
||||||
|
UNICORN_ARCH="${*}";;
|
||||||
|
"msys" )
|
||||||
|
shift
|
||||||
|
UNICORN_ARCH="${*}"
|
||||||
|
CMAKE="/mingw64/bin/cmake"
|
||||||
|
GENERATOR="MSYS Makefiles";;
|
||||||
|
* )
|
||||||
|
UNICORN_ARCH="${*}";;
|
||||||
|
esac
|
||||||
|
|
||||||
if [ -z "${UNICORN_ARCH}" ]; then
|
if [ -n "${COMPILER}" ]; then
|
||||||
cmake "${FLAGS}" ..
|
TOOLCHAIN="${TOOLCHAIN} -DCMAKE_C_COMPILER=${COMPILER}"
|
||||||
else
|
|
||||||
cmake "${FLAGS}" "-DUNICORN_ARCH=${UNICORN_ARCH}" ..
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "${UNICORN_ARCH}" ]; then
|
||||||
|
${CMAKE} "${FLAGS}" ${TOOLCHAIN} -G "${GENERATOR}" ..
|
||||||
|
else
|
||||||
|
${CMAKE} "${FLAGS}" ${TOOLCHAIN} "-DUNICORN_ARCH=${UNICORN_ARCH}" -G "${GENERATOR}" ..
|
||||||
|
fi
|
||||||
|
|
||||||
|
# now build
|
||||||
make -j8
|
make -j8
|
||||||
|
|
30
config.mk
30
config.mk
|
@ -1,30 +0,0 @@
|
||||||
# Unicorn Emulator Engine
|
|
||||||
# By Nguyen Anh Quynh, 2015
|
|
||||||
|
|
||||||
# This file contains all customized compile options for Unicorn emulator.
|
|
||||||
# Consult docs/COMPILE.md & docs/README.md for more details.
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Compile with debug info when you want to debug code.
|
|
||||||
# Change this to 'no' for release edition.
|
|
||||||
|
|
||||||
UNICORN_DEBUG ?= yes
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Specify which archs you want to compile in. By default, we build all archs.
|
|
||||||
|
|
||||||
UNICORN_ARCHS ?= x86 m68k arm aarch64 mips sparc
|
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Change 'UNICORN_STATIC = yes' to 'UNICORN_STATIC = no' to avoid building
|
|
||||||
# a static library.
|
|
||||||
|
|
||||||
UNICORN_STATIC ?= yes
|
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Change 'UNICORN_SHARED = yes' to 'UNICORN_SHARED = no' to avoid building
|
|
||||||
# a shared library.
|
|
||||||
|
|
||||||
UNICORN_SHARED ?= yes
|
|
|
@ -1,57 +0,0 @@
|
||||||
This documentation explains how to compile Unicorn with CMake on Windows or
|
|
||||||
*nix.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
|
|
||||||
- Windows: MicroSoft Visual Studio(>=2013).
|
|
||||||
- *nix: GNU gcc or clang to generate dynamic source files.
|
|
||||||
|
|
||||||
Get CMake for free from http://www.cmake.org.
|
|
||||||
|
|
||||||
|
|
||||||
[1] To build Unicorn using Nmake of Windows SDK, do:
|
|
||||||
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
..\nmake.bat
|
|
||||||
|
|
||||||
After this, find the samples test*.exe, unicorn.lib & unicorn.dll
|
|
||||||
in the same directory.
|
|
||||||
|
|
||||||
|
|
||||||
- To build Unicorn using Visual Studio, choose the generator accordingly to the
|
|
||||||
version of Visual Studio on your machine. For example, with Visual Studio 2013, do:
|
|
||||||
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake -G "Visual Studio 12" ..
|
|
||||||
|
|
||||||
After this, find unicorn.sln in the same directory. Open it with Visual Studio
|
|
||||||
and build the solution including libraries & all test as usual.
|
|
||||||
|
|
||||||
|
|
||||||
[2] You can make sure the prior steps successfully worked by launching one of the
|
|
||||||
sample binary (sample_*.exe).
|
|
||||||
|
|
||||||
|
|
||||||
[3] You can also enable just one specific architecture by passing the architecture name
|
|
||||||
to either the cmake.sh or nmake.bat scripts. e.g.:
|
|
||||||
|
|
||||||
..\nmake.bat x86
|
|
||||||
|
|
||||||
Will just target the x86 architecture. The list of available architectures are:
|
|
||||||
X86 ARM AARCH64 M68K MIPS SPARC.
|
|
||||||
|
|
||||||
|
|
||||||
[4] You can also create an installation image with cmake, by using the 'install' target.
|
|
||||||
Use:
|
|
||||||
|
|
||||||
cmake --build . --config Release --target install
|
|
||||||
|
|
||||||
This will normally install an image in a default location (on MacOS and Linux, but this is not supported
|
|
||||||
on Windows). So in case you want to change the install location, set this when configuring CMake.
|
|
||||||
Use: `-DCMAKE_INSTALL_PREFIX=path` for instance, to put the installation in the 'path' subdirectory of
|
|
||||||
the build directory.
|
|
||||||
The default value of 'CMAKE_INSTALL_PREFIX' on *nix is '/usr/local'.
|
|
|
@ -1,164 +0,0 @@
|
||||||
This documentation explains how to compile, install & run Unicorn on MacOSX,
|
|
||||||
Linux, BSD, Solaris, Android & iOS.
|
|
||||||
|
|
||||||
To compile for Microsoft Windows, see [COMPILE-WINDOWS.md](COMPILE-WINDOWS.md)
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
[1] Tailor Unicorn to your need.
|
|
||||||
|
|
||||||
Out of 6 archtitectures supported by Unicorn (Arm, Arm64, M68K, Mips, Sparc,
|
|
||||||
& X86), if you just need several selected archs, choose which ones you want
|
|
||||||
to compile in by editing "config.mk" before going to next steps.
|
|
||||||
|
|
||||||
By default, all 6 architectures are compiled. If this is what you want, skip
|
|
||||||
to the section 2.
|
|
||||||
|
|
||||||
The other way of customize Unicorn without having to edit config.mk is to
|
|
||||||
pass the desired options on the commandline to ./make.sh. Currently,
|
|
||||||
Unicorn supports 4 options, as follows.
|
|
||||||
|
|
||||||
- UNICORN_ARCHS: specify list of architectures to compiled in.
|
|
||||||
- UNICORN_STATIC: build static library.
|
|
||||||
- UNICORN_SHARED: build dynamic (shared) library.
|
|
||||||
- UNICORN_QEMU_FLAGS: specify extra flags for qemu's configure script
|
|
||||||
|
|
||||||
To avoid editing config.mk for these customization, we can pass their values to
|
|
||||||
make.sh, as follows.
|
|
||||||
|
|
||||||
$ UNICORN_ARCHS="arm aarch64 x86" ./make.sh
|
|
||||||
|
|
||||||
NOTE: on commandline, put these values in front of ./make.sh, not after it.
|
|
||||||
|
|
||||||
For each option, refer to docs/README for more details.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[2] Compile and install from source on *nix
|
|
||||||
|
|
||||||
To build Unicorn on *nix (such as MacOSX, Linux, *BSD, Solaris):
|
|
||||||
|
|
||||||
- To compile for current platform, run:
|
|
||||||
|
|
||||||
$ ./make.sh
|
|
||||||
|
|
||||||
On Mac OS, to build non-universal binaries that includes only 64-bit code,
|
|
||||||
replace above command with:
|
|
||||||
|
|
||||||
$ ./make.sh macos-universal-no
|
|
||||||
|
|
||||||
- To cross-compile Unicorn on 64-bit Linux to target 32-bit binary,
|
|
||||||
cross-compile to 32-bit with:
|
|
||||||
|
|
||||||
$ ./make.sh linux32
|
|
||||||
|
|
||||||
After compiling, install Unicorn with:
|
|
||||||
|
|
||||||
$ sudo ./make.sh install
|
|
||||||
|
|
||||||
For FreeBSD/OpenBSD, where sudo is unavailable, run:
|
|
||||||
|
|
||||||
$ su; ./make.sh install
|
|
||||||
|
|
||||||
Users are then required to enter root password to copy Unicorn into machine
|
|
||||||
system directories.
|
|
||||||
|
|
||||||
Afterwards, run ./samples/sample_all.sh to test the sample emulations.
|
|
||||||
|
|
||||||
|
|
||||||
NOTE: The core framework installed by "./make.sh install" consist of
|
|
||||||
following files:
|
|
||||||
|
|
||||||
/usr/include/unicorn/unicorn.h
|
|
||||||
/usr/include/unicorn/x86.h
|
|
||||||
/usr/include/unicorn/arm.h
|
|
||||||
/usr/include/unicorn/arm64.h
|
|
||||||
/usr/include/unicorn/mips.h
|
|
||||||
/usr/include/unicorn/ppc.h
|
|
||||||
/usr/include/unicorn/sparc.h
|
|
||||||
/usr/include/unicorn/m68k.h
|
|
||||||
/usr/lib/libunicorn.so (for Linux/*nix), or /usr/lib/libunicorn.dylib (OSX)
|
|
||||||
/usr/lib/libunicorn.a
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[3] Cross-compile for iOS from macOS.
|
|
||||||
|
|
||||||
To cross-compile for iOS (iPhone/iPad/iPod), macOS with Xcode installed is required.
|
|
||||||
|
|
||||||
- To cross-compile for iOS ArmV7 (iPod 4, iPad 1/2/3, iPhone4, iPhone4S), run:
|
|
||||||
|
|
||||||
$ ./make.sh ios_armv7
|
|
||||||
|
|
||||||
- To cross-compile for iOS ArmV7s (iPad 4, iPhone 5C, iPad mini), run:
|
|
||||||
|
|
||||||
$ ./make.sh ios_armv7s
|
|
||||||
|
|
||||||
- To cross-compile for iOS Arm64 (iPhone 5S, iPad mini Retina, iPad Air), run:
|
|
||||||
|
|
||||||
$ ./make.sh ios_arm64
|
|
||||||
|
|
||||||
- To cross-compile for all iOS devices (armv7 + armv7s + arm64), run:
|
|
||||||
|
|
||||||
$ ./make.sh ios
|
|
||||||
|
|
||||||
Resulted files libunicorn.dylib, libunicorn.a & tests/test* can then
|
|
||||||
be used on iOS devices.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[4] Cross-compile for Android
|
|
||||||
|
|
||||||
To cross-compile for Android (smartphone/tablet), Android NDK is required.
|
|
||||||
|
|
||||||
- To cross-compile for Android Arm, run:
|
|
||||||
|
|
||||||
$ NDK=~/android/android-ndk-r20 ./make.sh cross-android_arm
|
|
||||||
|
|
||||||
- To cross-compile for Android Arm64, run:
|
|
||||||
|
|
||||||
$ NDK=~/android/android-ndk-r20 ./make.sh cross-android_arm64
|
|
||||||
|
|
||||||
Resulted files libunicorn.so, libunicorn.a & tests/test* can then
|
|
||||||
be used on Android devices.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[5] By default, "cc" (default C compiler on the system) is used as compiler.
|
|
||||||
|
|
||||||
- To use "clang" compiler instead, run the command below:
|
|
||||||
|
|
||||||
$ ./make.sh clang
|
|
||||||
|
|
||||||
- To use "gcc" compiler instead, run:
|
|
||||||
|
|
||||||
$ ./make.sh gcc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[6] To uninstall Unicorn, run the command below:
|
|
||||||
|
|
||||||
$ sudo ./make.sh uninstall
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[7] Language bindings
|
|
||||||
|
|
||||||
Look for the bindings under directory bindings/, and refer to README file
|
|
||||||
of corresponding languages.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[8] Unit tests
|
|
||||||
|
|
||||||
Mac OS X users will also need the GNU version of binutils (for gobjcopy).
|
|
||||||
It can be easily installed with Homebrew: `brew install binutils`.
|
|
||||||
|
|
||||||
Automated unit tests use the cmocka unit testing framework (https://cmocka.org/).
|
|
||||||
It can be installed in most Linux distros using the package manager, e.g.
|
|
||||||
`sudo yum install libcmocka libcmocka-devel`.
|
|
||||||
On Mac OS X with Homebrew: `brew install cmocka`.
|
|
||||||
You can also easily build and install it from source.
|
|
||||||
|
|
||||||
You can run the tests by running `make test` in the project directory. If you don't
|
|
||||||
build some architecture support then the corresponding tests will fail when run.
|
|
|
@ -1,184 +0,0 @@
|
||||||
To build Unicorn on Windows natively using Visual Studio, see docs under "msvc"
|
|
||||||
directory in root directory.
|
|
||||||
|
|
||||||
The rest of this manual shows how to cross-compile Unicorn for Windows using
|
|
||||||
either MingW or Msys2.
|
|
||||||
|
|
||||||
To compile for Linux, Mac OS X and Unix-based OS, see [COMPILE-NIX.md](COMPILE-NIX.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
[0] Dependencies
|
|
||||||
|
|
||||||
For Windows, cross-compile requires Mingw. At the moment, it is confirmed that
|
|
||||||
Unicorn can be compiled either on Ubuntu or Windows.
|
|
||||||
|
|
||||||
- On Ubuntu 14.04 64-bit, do:
|
|
||||||
|
|
||||||
- Download DEB packages for Mingw64 from:
|
|
||||||
|
|
||||||
https://launchpad.net/~greg-hellings/+archive/ubuntu/mingw-libs/+build/2924251
|
|
||||||
|
|
||||||
|
|
||||||
- On Windows, install MinGW via package MSYS2 at https://msys2.github.io/
|
|
||||||
|
|
||||||
Follow the install instructions and don't forget to update the system packages with:
|
|
||||||
|
|
||||||
$ pacman --needed -Sy bash pacman pacman-mirrors msys2-runtime
|
|
||||||
|
|
||||||
Then close MSYS2, run it again from Start menu and update the rest with:
|
|
||||||
|
|
||||||
$ pacman -Su
|
|
||||||
|
|
||||||
Finally, install required toolchain to build C projects.
|
|
||||||
|
|
||||||
- To compile for Windows 32-bit, run:
|
|
||||||
|
|
||||||
$ pacman -S make
|
|
||||||
$ pacman -S mingw-w64-i686-toolchain
|
|
||||||
|
|
||||||
- To compile for Windows 64-bit, run:
|
|
||||||
|
|
||||||
$ pacman -S make
|
|
||||||
$ pacman -S mingw-w64-x86_64-toolchain
|
|
||||||
|
|
||||||
- For Cygwin, "make", "gcc-core", "libpcre-devel", "zlib-devel" are needed.
|
|
||||||
|
|
||||||
If apt-cyg is available, you can install these with:
|
|
||||||
|
|
||||||
$ apt-cyg install make gcc-core libpcre-devel zlib-devel
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[1] Tailor Unicorn to your need.
|
|
||||||
|
|
||||||
Out of 6 archtitectures supported by Unicorn (Arm, Arm64, M68K, Mips, Sparc,
|
|
||||||
& X86), if you just need several selected archs, choose which ones you want
|
|
||||||
to compile in by editing "config.mk" before going to next steps.
|
|
||||||
|
|
||||||
By default, all 6 architectures are compiled.
|
|
||||||
|
|
||||||
The other way of customize Unicorn without having to edit config.mk is to
|
|
||||||
pass the desired options on the commandline to ./make.sh. Currently,
|
|
||||||
Unicorn supports 4 options, as follows.
|
|
||||||
|
|
||||||
- UNICORN_ARCHS: specify list of architectures to compiled in.
|
|
||||||
- UNICORN_STATIC: build static library.
|
|
||||||
- UNICORN_SHARED: build dynamic (shared) library.
|
|
||||||
- UNICORN_QEMU_FLAGS: specify extra flags for qemu's configure script
|
|
||||||
|
|
||||||
To avoid editing config.mk for these customization, we can pass their values to
|
|
||||||
make.sh, as follows.
|
|
||||||
|
|
||||||
$ UNICORN_ARCHS="arm aarch64 x86" ./make.sh
|
|
||||||
|
|
||||||
NOTE: on commandline, put these values in front of ./make.sh, not after it.
|
|
||||||
|
|
||||||
For each option, refer to docs/README for more details.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[2] Compile from source on Windows - with MinGW (MSYS2)
|
|
||||||
|
|
||||||
To compile with MinGW, install MSYS2 as instructed in the first section.
|
|
||||||
|
|
||||||
Note: After MSYS2 is installed, you will have 3 shortcuts to open the command prompt: "MSYS2 MSYS", "MSYS2 MinGW-32 bit" and "MSYS2 MinGW 64-bit". Use the MinGW shortcut so that compilation succeeds.
|
|
||||||
|
|
||||||
Then, build Unicorn with the next steps:
|
|
||||||
|
|
||||||
- To compile Windows 32-bit binary with MinGW, run:
|
|
||||||
|
|
||||||
$ ./make.sh cross-win32
|
|
||||||
|
|
||||||
- To compile Windows 64-bit binary with MinGW, run:
|
|
||||||
|
|
||||||
$ ./make.sh cross-win64
|
|
||||||
|
|
||||||
Resulted files unicorn.dll, unicorn.lib & samples/sample*.exe can then
|
|
||||||
be used on Windows machine.
|
|
||||||
|
|
||||||
To run sample_x86.exe on Windows 32-bit, you need the following files:
|
|
||||||
|
|
||||||
unicorn.dll
|
|
||||||
%MSYS2%\mingw32\bin\libgcc_s_dw2-1.dll
|
|
||||||
%MSYS2%\mingw32\bin\libwinpthread-1.dll
|
|
||||||
|
|
||||||
To run sample_x86.exe on Windows 64-bit, you need the following files:
|
|
||||||
|
|
||||||
unicorn.dll
|
|
||||||
%MSYS2%\mingw64\bin\libgcc_s_seh-1.dll
|
|
||||||
%MSYS2%\mingw64\bin\libwinpthread-1.dll
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[3] Compile and install from source on Cygwin
|
|
||||||
|
|
||||||
To build Unicorn on Cygwin, run:
|
|
||||||
|
|
||||||
$ ./make.sh
|
|
||||||
|
|
||||||
After compiling, install Unicorn with:
|
|
||||||
|
|
||||||
$ ./make.sh install
|
|
||||||
|
|
||||||
Resulted files cygunicorn.dll, libunicorn.dll.a and libunicorn.a can be
|
|
||||||
used on Cygwin but not native Windows.
|
|
||||||
|
|
||||||
NOTE: The core framework installed by "./make.sh install" consist of
|
|
||||||
following files:
|
|
||||||
|
|
||||||
/usr/include/unicorn/*.h
|
|
||||||
/usr/bin/cygunicorn.dll
|
|
||||||
/usr/lib/libunicorn.dll.a
|
|
||||||
/usr/lib/libunicorn.a
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[4] Cross-compile for Windows from *nix
|
|
||||||
|
|
||||||
To cross-compile for Windows, Linux & gcc-mingw-w64-i686 (and also gcc-mingw-w64-x86-64
|
|
||||||
for 64-bit binaries) are required.
|
|
||||||
|
|
||||||
- To cross-compile Windows 32-bit binary, simply run:
|
|
||||||
|
|
||||||
$ ./make.sh cross-win32
|
|
||||||
|
|
||||||
- To cross-compile Windows 64-bit binary, run:
|
|
||||||
|
|
||||||
$ ./make.sh cross-win64
|
|
||||||
|
|
||||||
Resulted files unicorn.dll, unicorn.lib & samples/sample*.exe can then
|
|
||||||
be used on Windows machine.
|
|
||||||
|
|
||||||
To run sample_x86.exe on Windows 32-bit, you need the following files:
|
|
||||||
|
|
||||||
unicorn.dll
|
|
||||||
/usr/lib/gcc/i686-w64-mingw32/4.8/libgcc_s_sjlj-1.dll
|
|
||||||
/usr/i686-w64-mingw32/lib/libwinpthread-1.dll
|
|
||||||
|
|
||||||
To run sample_x86.exe on Windows 64-bit, you need the following files:
|
|
||||||
|
|
||||||
unicorn.dll
|
|
||||||
/usr/lib/gcc/x86_64-w64-mingw32/4.8/libgcc_s_sjlj-1.dll
|
|
||||||
/usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll
|
|
||||||
|
|
||||||
Then run either "sample_x86.exe -32" or "sample_x86.exe -64" to test emulators for X86 32-bit or X86 64-bit.
|
|
||||||
For other architectures, run "sample_xxx.exe" found in the same directory.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[5] Language bindings
|
|
||||||
|
|
||||||
Look for the bindings under directory bindings/, and refer to README file
|
|
||||||
of corresponding languages.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[6] Unit tests
|
|
||||||
|
|
||||||
Automated unit tests use the cmocka unit testing framework (https://cmocka.org/).
|
|
||||||
It can be installed in most Linux distros using the package manager, e.g.
|
|
||||||
`sudo yum install libcmocka libcmocka-devel`, or you can easily build and install it from source.
|
|
||||||
|
|
||||||
You can run the tests by running `make test` in the project directory.
|
|
140
docs/COMPILE.md
140
docs/COMPILE.md
|
@ -1,25 +1,131 @@
|
||||||
To compile Unicorn on Mac OS X, Linux, BSD, Solaris and all kind of nix OS,
|
This HOWTO introduces how to build Unicorn2 natively on Linux/Mac/Windows,
|
||||||
see [COMPILE-NIX.md](COMPILE-NIX.md)
|
or cross-build to Windows from Linux host.
|
||||||
|
|
||||||
To compile Unicorn on Windows, see [COMPILE-WINDOWS.md](COMPILE-WINDOWS.md)
|
---
|
||||||
|
### Native build on Linux/MacOS
|
||||||
|
|
||||||
To compile Unicorn with CMake on Windows or *nix, see
|
This builds Unicorn2 on Linux/MacOS. The output is `libunicorn.so` or `libunicorn.dylib`, respectively.
|
||||||
[COMPILE-CMAKE.md](COMPILE-CMAKE.md)
|
|
||||||
|
|
||||||
Then learn more on how to code your own tools with our samples.
|
- Require `cmake` & `pkg-config` packages (besides `gcc`/`clang` compiler):
|
||||||
|
|
||||||
- For C sample code, see code in directory samples/sample*.c
|
```
|
||||||
- For Python sample code, see code in directory bindings/python/sample*.py
|
$ sudo apt install cmake pkg-config
|
||||||
- For samples of other bindings, look into directories bindings/<language>/
|
```
|
||||||
|
|
||||||
#Building unicorn - Using vcpkg
|
- Build with the following commands.
|
||||||
|
|
||||||
You can download and install unicorn using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
```
|
||||||
|
$ mkdir build; cd build
|
||||||
|
$ ../cmake.sh
|
||||||
|
```
|
||||||
|
|
||||||
git clone https://github.com/Microsoft/vcpkg.git
|
Then run the sample `sample_riscv` with:
|
||||||
cd vcpkg
|
|
||||||
./bootstrap-vcpkg.sh
|
|
||||||
./vcpkg integrate install
|
|
||||||
./vcpkg install unicorn
|
|
||||||
|
|
||||||
The unicorn port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
```
|
||||||
|
$ ./sample_riscv
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
### Native build on Windows, with MSVC
|
||||||
|
|
||||||
|
This builds Unicorn2 on Windows, using Microsoft MSVC compiler. The output is `unicorn.dll`.
|
||||||
|
|
||||||
|
- Require `cmake` & `Microsoft Visual Studio`.
|
||||||
|
|
||||||
|
- From Visual Studio Command Prompt, build with the following commands.
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build; cd build
|
||||||
|
../nmake.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run the sample `sample_riscv` with:
|
||||||
|
|
||||||
|
```
|
||||||
|
sample_riscv.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cross build from Linux host to Windows, with Mingw
|
||||||
|
|
||||||
|
This cross-builds Unicorn2 from **Linux host** to Windows, using `Mingw` compiler. The output is `libunicorn.dll`
|
||||||
|
|
||||||
|
- Install required package.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo apt install mingw-w64-x86-64-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
- Build Unicorn and samples with the following commands.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mkdir build; cd build
|
||||||
|
$ ../cmake.sh mingw
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulted `sample_riscv.exe` can be run with `libunicorn.dll`, and some dependecies DLLs
|
||||||
|
already provided in `bin/` directory.
|
||||||
|
|
||||||
|
To prepare for `sample_riscv.exe`, do:
|
||||||
|
|
||||||
|
```
|
||||||
|
cp libunicorn.dll ../bin
|
||||||
|
cp sample_riscv.exe ../bin
|
||||||
|
```
|
||||||
|
|
||||||
|
Then inside the `bin/` directory, you can run `sample_riscv.exe` (from `CMD.exe` prompt, for example)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Native build on Windows host, with MSYS2/Mingw
|
||||||
|
|
||||||
|
This builds Unicorn2 on **Windows host**, using **MSYS2/Mingw** compiler. The output is `libunicorn.dll`
|
||||||
|
|
||||||
|
This requires MSYS2 to be installed on Windows machine. You need to download & install MSYS2 from https://www.msys2.org.
|
||||||
|
|
||||||
|
Then from MSYS2 console, install required packages:
|
||||||
|
|
||||||
|
```
|
||||||
|
pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake
|
||||||
|
```
|
||||||
|
|
||||||
|
- Build Unicorn and samples with the following commands.
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build; cd build
|
||||||
|
../cmake.sh msys
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulted `sample_riscv.exe` can be run with `libunicorn.dll`, and some dependecies DLLs
|
||||||
|
already provided in `bin/` directory.
|
||||||
|
|
||||||
|
To prepare for `sample_riscv.exe`, do:
|
||||||
|
|
||||||
|
```
|
||||||
|
cp libunicorn.dll ../bin
|
||||||
|
cp sample_riscv.exe ../bin
|
||||||
|
```
|
||||||
|
|
||||||
|
Then inside the `bin/` directory, you can run `sample_riscv.exe` (from `CMD.exe` prompt, for example)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Cross build from Linux host to other arch
|
||||||
|
|
||||||
|
This cross-builds Unicorn2 from **Linux host** to other arch, using cross compiler. The output is `libunicorn.so`
|
||||||
|
|
||||||
|
- Install cross compiler package. For example, cross compile to ARM require below command.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo apt install gcc-arm-linux-gnueabihf
|
||||||
|
```
|
||||||
|
|
||||||
|
- Build Unicorn and samples with the following commands (note that you need to specify compiler with CC).
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mkdir build; cd build
|
||||||
|
$ CC=arm-linux-gnueabihf-gcc ../cmake.sh
|
||||||
|
```
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 34 KiB |
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Creator: CorelDRAW X7 -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="113.496mm" height="95.7057mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||||
|
viewBox="0 0 11350 9571"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<style type="text/css">
|
||||||
|
<![CDATA[
|
||||||
|
.fil2 {fill:#FEFEFE}
|
||||||
|
.fil0 {fill:#E62129}
|
||||||
|
.fil1 {fill:black}
|
||||||
|
]]>
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<g id="Layer_x0020_1">
|
||||||
|
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||||
|
<g id="_307418024">
|
||||||
|
<path class="fil0" d="M7101 1434l-1 0c487,-344 1238,-810 1653,-1216 2,-11 4,-25 -31,-17 -121,27 -433,159 -512,209 21,20 106,47 151,60 -50,6 -96,-1 -140,-5 -129,-13 -220,38 -344,99 -41,20 -79,39 -117,59 -1,26 231,92 280,88 -78,15 -136,9 -191,3 -85,-11 -151,-31 -233,-3 -113,39 -249,120 -353,173 -1,32 281,131 341,127 -240,21 -249,-21 -421,-41 -30,-3 -64,0 -113,19 -39,15 -205,96 -272,131l7 -6 0 1 -15 6c6,37 35,99 38,145 3,45 225,145 273,168z"/>
|
||||||
|
<g>
|
||||||
|
<path class="fil1" d="M1118 8018l0 -1025 373 0 0 1025c0,311 -155,466 -466,466l-559 0c-311,0 -466,-155 -466,-466l0 -1025 373 0 0 1025c0,62 31,93 93,93l559 0c62,0 93,-31 93,-93zm1084 -339l0 805 -373 0 0 -1581 1119 895 0 -805 373 0 0 1581 -1119 -895zm1830 805l-373 0 0 -1491 373 0 0 1491zm1457 -466l0 -93 372 0 0 93c0,311 -155,466 -466,466l-559 0c-311,0 -466,-155 -466,-466l0 -559c0,-311 155,-466 466,-466l559 0c311,0 466,155 466,466l0 93 -372 0 0 -93c0,-62 -32,-93 -94,-93l-559 0c-62,0 -93,31 -93,93l0 559c0,62 31,93 93,93l559 0c62,0 94,-31 94,-93zm1829 -559c0,-62 -31,-93 -93,-93l-559 0c-62,0 -94,31 -94,93l0 559c0,62 32,93 94,93l559 0c62,0 93,-31 93,-93l0 -559zm-93 -466c310,0 466,155 466,466l0 559c0,311 -156,466 -466,466l-559 0c-311,0 -466,-155 -466,-466l0 -559c0,-311 155,-466 466,-466l559 0zm804 0l1025 0c311,0 466,155 466,466 0,274 -121,427 -362,460l452 565 -478 0 -448 -559 -282 0 0 559 -373 0 0 -1491zm373 373l0 186 652 0c62,0 93,-31 93,-93 0,-62 -31,-93 -93,-93l-652 0zm1829 313l0 805 -373 0 0 -1581 1119 895 0 -805 373 0 0 1581 -1119 -895z"/>
|
||||||
|
<path class="fil1" d="M2004 9551l0 -638 598 0 0 93 -498 0 0 159 327 0 0 92 -327 0 0 202 526 0 0 92 -626 0zm1409 0l0 -638 52 0 405 448 0 -448 98 0 0 638 -52 0 -405 -447 0 447 -98 0zm1846 -248l0 -92 262 0 0 193c-36,54 -84,96 -144,124 -59,28 -128,43 -206,43 -117,0 -213,-32 -288,-95 -75,-64 -112,-144 -112,-242 0,-97 37,-178 112,-242 76,-64 171,-96 288,-96 74,0 139,13 196,38 57,26 105,63 142,112l-76 55c-27,-35 -64,-63 -110,-83 -46,-20 -97,-30 -152,-30 -87,0 -158,23 -214,69 -56,47 -84,105 -84,176 0,70 28,129 84,175 55,46 126,69 214,69 55,0 106,-10 152,-29 47,-20 79,-46 98,-76l0 -69 -162 0zm1086 248l0 -639 101 0 0 639 -101 0zm962 0l0 -638 52 0 405 448 0 -448 98 0 0 638 -52 0 -405 -447 0 447 -98 0zm1413 0l0 -638 598 0 0 93 -499 0 0 159 327 0 0 92 -327 0 0 202 526 0 0 92 -625 0z"/>
|
||||||
|
<polygon class="fil1" points="0,9165 1300,9165 1300,9257 0,9257 "/>
|
||||||
|
<polygon class="fil1" points="10050,9165 11350,9165 11350,9257 10050,9257 "/>
|
||||||
|
</g>
|
||||||
|
<path class="fil0" d="M6093 1928c-68,808 676,845 742,827 143,29 409,219 409,219 19,168 46,178 119,216 169,90 504,48 596,-158 108,-240 -244,-791 -381,-961 -171,-211 -25,-195 -113,-398 -50,-114 -146,-235 -238,-336 -44,-25 -232,-136 -241,-182 -2,-14 -8,-32 -15,-50 82,-41 348,-534 371,-616 -193,-13 -642,82 -703,233 18,76 95,130 112,206 -120,-51 -172,-117 -292,-167l-130 -761c-315,130 -399,508 -365,798 -331,-279 -667,-228 -1127,-51 208,6 316,80 361,163 -266,94 -570,161 -1121,197 82,136 254,233 389,258 -92,61 -845,-136 -1223,557 199,-199 740,-294 870,-68 -214,106 -242,312 -608,374 86,95 355,102 539,95 -464,216 -780,610 -1364,699 501,155 749,74 1051,18 -278,249 -557,583 -506,1176 59,-275 360,-529 591,-410 -122,205 -326,620 -669,844 309,48 610,-116 760,-221 -167,266 -251,557 -394,833 79,67 162,130 248,189 12,-10 24,-19 35,-29l247 134c3,25 6,49 10,73 56,30 113,58 171,85 15,-40 35,-81 58,-118 24,59 49,118 75,176 368,150 769,232 1190,232 1063,0 2002,-524 2576,-1328 -86,-12 -1934,-233 -1529,-1704 -337,-164 -688,-486 -501,-1044zm-790 -679c-807,838 -83,1836 699,2200 -576,-416 -1302,-1282 -699,-2200zm-737 870c-408,546 -247,1080 64,1388 102,102 229,188 370,267 657,365 1590,567 2009,1199 -159,-412 -359,-636 -616,-799 -603,-381 -1604,-489 -1884,-1204 -94,-241 -81,-522 57,-851z"/>
|
||||||
|
<path class="fil0" d="M5319 6134c1651,121 3087,-1120 3207,-2771 53,-727 -158,-1412 -552,-1962l-9 7c250,477 375,1027 333,1603 -119,1642 -1547,2875 -3189,2756 -974,-71 -1804,-603 -2293,-1366 442,957 1377,1651 2503,1733z"/>
|
||||||
|
<path class="fil2" d="M6976 1558c117,44 208,189 330,310 -118,-13 -192,-47 -279,-53 74,-103 -11,-187 -51,-257z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
|
@ -0,0 +1,2 @@
|
||||||
|
This is a compatible glib library, customized for Unicorn.
|
||||||
|
Based on glib 2.64.4.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_ARRAY_H__
|
||||||
|
#define __G_ARRAY_H__
|
||||||
|
|
||||||
|
#include "gtypes.h"
|
||||||
|
|
||||||
|
typedef struct _GBytes GBytes;
|
||||||
|
typedef struct _GArray GArray;
|
||||||
|
typedef struct _GByteArray GByteArray;
|
||||||
|
typedef struct _GPtrArray GPtrArray;
|
||||||
|
|
||||||
|
struct _GArray
|
||||||
|
{
|
||||||
|
gchar *data;
|
||||||
|
guint len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GByteArray
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
guint len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GPtrArray
|
||||||
|
{
|
||||||
|
gpointer *pdata;
|
||||||
|
guint len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Resizable arrays. remove fills any cleared spot and shortens the
|
||||||
|
* array, while preserving the order. remove_fast will distort the
|
||||||
|
* order by moving the last element to the position of the removed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define g_array_append_val(a,v) g_array_append_vals (a, &(v), 1)
|
||||||
|
#define g_array_index(a,t,i) (((t*) (void *) (a)->data) [(i)])
|
||||||
|
|
||||||
|
GArray* g_array_append_vals (GArray *array,
|
||||||
|
gconstpointer data,
|
||||||
|
guint len);
|
||||||
|
|
||||||
|
GArray* g_array_new (gboolean zero_terminated, gboolean clear_, guint element_size);
|
||||||
|
GArray* g_array_sized_new (gboolean zero_terminated,
|
||||||
|
gboolean clear_,
|
||||||
|
guint element_size,
|
||||||
|
guint reserved_size);
|
||||||
|
|
||||||
|
gchar* g_array_free(GArray *array, gboolean free_segment);
|
||||||
|
GArray* g_array_set_size(GArray *array, guint length);
|
||||||
|
GArray*
|
||||||
|
g_array_remove_range (GArray *farray,
|
||||||
|
guint index_,
|
||||||
|
guint length);
|
||||||
|
|
||||||
|
void g_ptr_array_set_free_func (GPtrArray *array,
|
||||||
|
GDestroyNotify element_free_func);
|
||||||
|
|
||||||
|
/* Resizable pointer array. This interface is much less complicated
|
||||||
|
* than the above. Add appends a pointer. Remove fills any cleared
|
||||||
|
* spot and shortens the array. remove_fast will again distort order.
|
||||||
|
*/
|
||||||
|
#define g_ptr_array_index(array,index_) ((array)->pdata)[index_]
|
||||||
|
GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func);
|
||||||
|
void g_ptr_array_add(GPtrArray *array, gpointer data);
|
||||||
|
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
||||||
|
GPtrArray* g_ptr_array_remove_range (GPtrArray *array, guint index_, guint length);
|
||||||
|
|
||||||
|
/* Byte arrays, an array of guint8. Implemented as a GArray,
|
||||||
|
* but type-safe.
|
||||||
|
*/
|
||||||
|
GByteArray* g_byte_array_sized_new(guint reserved_size);
|
||||||
|
guint8* g_byte_array_free(GByteArray *array, gboolean free_segment);
|
||||||
|
GByteArray* g_byte_array_append(GByteArray *array, const guint8 *data, guint len);
|
||||||
|
GByteArray* g_byte_array_set_size(GByteArray *array, guint length);
|
||||||
|
|
||||||
|
#endif /* __G_ARRAY_H__ */
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_HASH_H__
|
||||||
|
#define __G_HASH_H__
|
||||||
|
|
||||||
|
#include "gtypes.h"
|
||||||
|
|
||||||
|
typedef struct _GHashTable GHashTable;
|
||||||
|
|
||||||
|
typedef gboolean (*GHRFunc) (gpointer key, gpointer value, gpointer user_data);
|
||||||
|
|
||||||
|
struct _GHashTableIter
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
gpointer dummy1;
|
||||||
|
gpointer dummy2;
|
||||||
|
gpointer dummy3;
|
||||||
|
int dummy4;
|
||||||
|
gboolean dummy5;
|
||||||
|
gpointer dummy6;
|
||||||
|
};
|
||||||
|
|
||||||
|
GHashTable* g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func);
|
||||||
|
|
||||||
|
GHashTable* g_hash_table_new_full (GHashFunc hash_func,
|
||||||
|
GEqualFunc key_equal_func,
|
||||||
|
GDestroyNotify key_destroy_func,
|
||||||
|
GDestroyNotify value_destroy_func);
|
||||||
|
|
||||||
|
void g_hash_table_destroy (GHashTable *hash_table);
|
||||||
|
|
||||||
|
gboolean g_hash_table_insert (GHashTable *hash_table, gpointer key, gpointer value);
|
||||||
|
|
||||||
|
void g_hash_table_replace (GHashTable *hash_table, gpointer key, gpointer value);
|
||||||
|
|
||||||
|
gboolean g_hash_table_remove (GHashTable *hash_table, gconstpointer key);
|
||||||
|
|
||||||
|
void g_hash_table_remove_all (GHashTable *hash_table);
|
||||||
|
|
||||||
|
gpointer g_hash_table_lookup (GHashTable *hash_table, gconstpointer key);
|
||||||
|
|
||||||
|
void g_hash_table_foreach (GHashTable *hash_table, GHFunc func, gpointer user_data);
|
||||||
|
|
||||||
|
guint g_hash_table_size (GHashTable *hash_table);
|
||||||
|
|
||||||
|
GHashTable* g_hash_table_ref (GHashTable *hash_table);
|
||||||
|
|
||||||
|
void g_hash_table_unref (GHashTable *hash_table);
|
||||||
|
|
||||||
|
/* Hash Functions
|
||||||
|
*/
|
||||||
|
gboolean g_int_equal (gconstpointer v1, gconstpointer v2);
|
||||||
|
guint g_int_hash (gconstpointer v);
|
||||||
|
|
||||||
|
#endif /* __G_HASH_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -25,35 +25,27 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#ifndef TRUE
|
#define G_MAXUINT UINT_MAX
|
||||||
#define TRUE 1
|
#define G_MAXINT INT_MAX
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FALSE
|
#include "gtestutils.h"
|
||||||
#define FALSE 0
|
#include "gtypes.h"
|
||||||
#endif
|
#include "garray.h"
|
||||||
|
#include "gtree.h"
|
||||||
#define g_assert(expr) assert(expr)
|
#include "ghash.h"
|
||||||
#define g_assert_not_reached() assert(0)
|
#include "gmem.h"
|
||||||
|
#include "gslice.h"
|
||||||
/* typedefs for glib related types that may still be referenced */
|
#include "gmessages.h"
|
||||||
typedef void* gpointer;
|
#include "gpattern.h"
|
||||||
typedef const void *gconstpointer;
|
#include "grand.h"
|
||||||
typedef int gint;
|
#include "glist.h"
|
||||||
typedef uint32_t guint32;
|
#include "gnode.h"
|
||||||
typedef uint64_t guint64;
|
|
||||||
typedef unsigned int guint;
|
|
||||||
typedef char gchar;
|
|
||||||
typedef int gboolean;
|
|
||||||
typedef unsigned long gulong;
|
|
||||||
typedef unsigned long gsize;
|
|
||||||
|
|
||||||
typedef gint (*GCompareDataFunc)(gconstpointer a,
|
typedef gint (*GCompareDataFunc)(gconstpointer a,
|
||||||
gconstpointer b,
|
gconstpointer b,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
typedef void (*GFunc)(gpointer data, gpointer user_data);
|
typedef void (*GFunc)(gpointer data, gpointer user_data);
|
||||||
typedef gint (*GCompareFunc)(gconstpointer v1, gconstpointer v2);
|
typedef gint (*GCompareFunc)(gconstpointer v1, gconstpointer v2);
|
||||||
typedef void (*GDestroyNotify)(gpointer data);
|
|
||||||
|
|
||||||
guint g_str_hash(gconstpointer v);
|
guint g_str_hash(gconstpointer v);
|
||||||
gboolean g_str_equal(gconstpointer v1, gconstpointer v2);
|
gboolean g_str_equal(gconstpointer v1, gconstpointer v2);
|
||||||
|
@ -61,11 +53,7 @@ guint g_int_hash(gconstpointer v);
|
||||||
|
|
||||||
gboolean g_int_equal(gconstpointer v1, gconstpointer v2);
|
gboolean g_int_equal(gconstpointer v1, gconstpointer v2);
|
||||||
|
|
||||||
typedef struct _GList {
|
int g_strcmp0(const char *str1, const char *str2);
|
||||||
gpointer data;
|
|
||||||
struct _GList *next;
|
|
||||||
struct _GList *prev;
|
|
||||||
} GList;
|
|
||||||
|
|
||||||
GList *g_list_first(GList *list);
|
GList *g_list_first(GList *list);
|
||||||
void g_list_foreach(GList *list, GFunc func, gpointer user_data);
|
void g_list_foreach(GList *list, GFunc func, gpointer user_data);
|
||||||
|
@ -86,34 +74,12 @@ void g_slist_foreach(GSList *list, GFunc func, gpointer user_data);
|
||||||
void g_slist_free(GSList *list);
|
void g_slist_free(GSList *list);
|
||||||
GSList *g_slist_prepend(GSList *list, gpointer data);
|
GSList *g_slist_prepend(GSList *list, gpointer data);
|
||||||
GSList *g_slist_sort(GSList *list, GCompareFunc compare);
|
GSList *g_slist_sort(GSList *list, GCompareFunc compare);
|
||||||
|
GSList *g_slist_find_custom(GSList *list, gconstpointer data, GCompareFunc func);
|
||||||
typedef guint (*GHashFunc)(gconstpointer key);
|
|
||||||
typedef gboolean (*GEqualFunc)(gconstpointer a, gconstpointer b);
|
|
||||||
typedef void (*GHFunc)(gpointer key, gpointer value, gpointer user_data);
|
|
||||||
typedef gboolean (*GHRFunc)(gpointer key, gpointer value, gpointer user_data);
|
|
||||||
|
|
||||||
typedef struct _GHashTable GHashTable;
|
|
||||||
|
|
||||||
void g_hash_table_destroy(GHashTable *hash_table);
|
|
||||||
gpointer g_hash_table_find(GHashTable *hash_table, GHRFunc predicate, gpointer user_data);
|
|
||||||
void g_hash_table_foreach(GHashTable *hash_table, GHFunc func, gpointer user_data);
|
|
||||||
void g_hash_table_insert(GHashTable *hash_table, gpointer key, gpointer value);
|
|
||||||
gpointer g_hash_table_lookup(GHashTable *hash_table, gconstpointer key);
|
|
||||||
GHashTable *g_hash_table_new(GHashFunc hash_func, GEqualFunc key_equal_func);
|
|
||||||
GHashTable *g_hash_table_new_full(GHashFunc hash_func, GEqualFunc key_equal_func,
|
|
||||||
GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func);
|
|
||||||
void g_hash_table_remove_all(GHashTable *hash_table);
|
|
||||||
gboolean g_hash_table_remove(GHashTable *hash_table, gconstpointer key);
|
|
||||||
void g_hash_table_unref(GHashTable *hash_table);
|
|
||||||
GHashTable *g_hash_table_ref(GHashTable *hash_table);
|
|
||||||
guint g_hash_table_size(GHashTable *hash_table);
|
|
||||||
|
|
||||||
/* replacement for g_malloc dependency */
|
/* replacement for g_malloc dependency */
|
||||||
void g_free(gpointer ptr);
|
void g_free(gpointer ptr);
|
||||||
gpointer g_malloc(size_t size);
|
|
||||||
gpointer g_malloc0(size_t size);
|
|
||||||
gpointer g_try_malloc0(size_t size);
|
|
||||||
gpointer g_realloc(gpointer ptr, size_t size);
|
gpointer g_realloc(gpointer ptr, size_t size);
|
||||||
|
|
||||||
char *g_strdup(const char *str);
|
char *g_strdup(const char *str);
|
||||||
char *g_strdup_printf(const char *format, ...);
|
char *g_strdup_printf(const char *format, ...);
|
||||||
char *g_strdup_vprintf(const char *format, va_list ap);
|
char *g_strdup_vprintf(const char *format, va_list ap);
|
||||||
|
@ -123,14 +89,9 @@ gpointer g_memdup(gconstpointer mem, size_t byte_size);
|
||||||
gpointer g_new_(size_t sz, size_t n_structs);
|
gpointer g_new_(size_t sz, size_t n_structs);
|
||||||
gpointer g_new0_(size_t sz, size_t n_structs);
|
gpointer g_new0_(size_t sz, size_t n_structs);
|
||||||
gpointer g_renew_(size_t sz, gpointer mem, size_t n_structs);
|
gpointer g_renew_(size_t sz, gpointer mem, size_t n_structs);
|
||||||
gchar* g_strconcat (const gchar *string1, ...);
|
|
||||||
gchar** g_strsplit (const gchar *string,
|
gchar** g_strsplit (const gchar *string,
|
||||||
const gchar *delimiter,
|
const gchar *delimiter,
|
||||||
gint max_tokens);
|
gint max_tokens);
|
||||||
|
|
||||||
|
|
||||||
#define g_new(struct_type, n_structs) ((struct_type*)g_new_(sizeof(struct_type), n_structs))
|
|
||||||
#define g_new0(struct_type, n_structs) ((struct_type*)g_new0_(sizeof(struct_type), n_structs))
|
|
||||||
#define g_renew(struct_type, mem, n_structs) ((struct_type*)g_renew_(sizeof(struct_type), mem, n_structs))
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -0,0 +1,154 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MT safe
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gtypes.h"
|
||||||
|
#include "glist.h"
|
||||||
|
#include "gslice.h"
|
||||||
|
#include "gmessages.h"
|
||||||
|
|
||||||
|
#define _g_list_alloc() g_slice_new (GList)
|
||||||
|
#define _g_list_alloc0() g_slice_new0 (GList)
|
||||||
|
#define _g_list_free1(list) g_slice_free (GList, list)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_list_alloc:
|
||||||
|
*
|
||||||
|
* Allocates space for one #GList element. It is called by
|
||||||
|
* g_list_append(), g_list_prepend(), g_list_insert() and
|
||||||
|
* g_list_insert_sorted() and so is rarely used on its own.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the newly-allocated #GList element
|
||||||
|
**/
|
||||||
|
GList *g_list_alloc (void)
|
||||||
|
{
|
||||||
|
return _g_list_alloc0 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GList *_g_list_remove_link (GList *list, GList *link)
|
||||||
|
{
|
||||||
|
if (link == NULL)
|
||||||
|
return list;
|
||||||
|
|
||||||
|
if (link->prev)
|
||||||
|
{
|
||||||
|
if (link->prev->next == link)
|
||||||
|
link->prev->next = link->next;
|
||||||
|
//else
|
||||||
|
// g_warning ("corrupted double-linked list detected");
|
||||||
|
}
|
||||||
|
if (link->next)
|
||||||
|
{
|
||||||
|
if (link->next->prev == link)
|
||||||
|
link->next->prev = link->prev;
|
||||||
|
//else
|
||||||
|
// g_warning ("corrupted double-linked list detected");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link == list)
|
||||||
|
list = list->next;
|
||||||
|
|
||||||
|
link->next = NULL;
|
||||||
|
link->prev = NULL;
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_list_delete_link:
|
||||||
|
* @list: a #GList, this must point to the top of the list
|
||||||
|
* @link_: node to delete from @list
|
||||||
|
*
|
||||||
|
* Removes the node link_ from the list and frees it.
|
||||||
|
* Compare this to g_list_remove_link() which removes the node
|
||||||
|
* without freeing it.
|
||||||
|
*
|
||||||
|
* Returns: the (possibly changed) start of the #GList
|
||||||
|
*/
|
||||||
|
GList *g_list_delete_link (GList *list, GList *link_)
|
||||||
|
{
|
||||||
|
list = _g_list_remove_link (list, link_);
|
||||||
|
_g_list_free1 (link_);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_list_insert_before:
|
||||||
|
* @list: a pointer to a #GList, this must point to the top of the list
|
||||||
|
* @sibling: the list element before which the new element
|
||||||
|
* is inserted or %NULL to insert at the end of the list
|
||||||
|
* @data: the data for the new element
|
||||||
|
*
|
||||||
|
* Inserts a new element into the list before the given position.
|
||||||
|
*
|
||||||
|
* Returns: the (possibly changed) start of the #GList
|
||||||
|
*/
|
||||||
|
GList *g_list_insert_before (GList *list, GList *sibling, gpointer data)
|
||||||
|
{
|
||||||
|
if (list == NULL)
|
||||||
|
{
|
||||||
|
list = g_list_alloc ();
|
||||||
|
list->data = data;
|
||||||
|
g_return_val_if_fail (sibling == NULL, list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
else if (sibling != NULL)
|
||||||
|
{
|
||||||
|
GList *node;
|
||||||
|
|
||||||
|
node = _g_list_alloc ();
|
||||||
|
node->data = data;
|
||||||
|
node->prev = sibling->prev;
|
||||||
|
node->next = sibling;
|
||||||
|
sibling->prev = node;
|
||||||
|
if (node->prev != NULL)
|
||||||
|
{
|
||||||
|
node->prev->next = node;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (sibling == list, node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GList *last;
|
||||||
|
|
||||||
|
for (last = list; last->next != NULL; last = last->next) {}
|
||||||
|
|
||||||
|
last->next = _g_list_alloc ();
|
||||||
|
last->next->data = data;
|
||||||
|
last->next->prev = last;
|
||||||
|
last->next->next = NULL;
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_LIST_H__
|
||||||
|
#define __G_LIST_H__
|
||||||
|
|
||||||
|
#include "gmem.h"
|
||||||
|
|
||||||
|
typedef struct _GList GList;
|
||||||
|
|
||||||
|
struct _GList
|
||||||
|
{
|
||||||
|
gpointer data;
|
||||||
|
GList *next;
|
||||||
|
GList *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GList* g_list_insert_before (GList *list, GList *sibling, gpointer data);
|
||||||
|
|
||||||
|
GList* g_list_delete_link (GList *list, GList *link_);
|
||||||
|
|
||||||
|
#endif /* __G_LIST_H__ */
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file must not include any other glib header file and must thus
|
||||||
|
* not refer to variables from glibconfig.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_MACROS_H__
|
||||||
|
#define __G_MACROS_H__
|
||||||
|
|
||||||
|
/* We include stddef.h to get the system's definition of NULL
|
||||||
|
*/
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* Here we provide G_GNUC_EXTENSION as an alias for __extension__,
|
||||||
|
* where this is valid. This allows for warningless compilation of
|
||||||
|
* "long long" types even in the presence of '-ansi -pedantic'.
|
||||||
|
*/
|
||||||
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
|
||||||
|
#define G_GNUC_EXTENSION __extension__
|
||||||
|
#else
|
||||||
|
#define G_GNUC_EXTENSION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !(defined (G_STMT_START) && defined (G_STMT_END))
|
||||||
|
#define G_STMT_START do
|
||||||
|
#if defined (_MSC_VER) && (_MSC_VER >= 1500)
|
||||||
|
#define G_STMT_END \
|
||||||
|
__pragma(warning(push)) \
|
||||||
|
__pragma(warning(disable:4127)) \
|
||||||
|
while(0) \
|
||||||
|
__pragma(warning(pop))
|
||||||
|
#else
|
||||||
|
#define G_STMT_END while (0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __G_MACROS_H__ */
|
|
@ -0,0 +1,257 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MT safe
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gtypes.h"
|
||||||
|
#include "gmem.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "gslice.h"
|
||||||
|
|
||||||
|
#define SIZE_OVERFLOWS(a,b) (((b) > 0 && (a) > G_MAXSIZE / (b)))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_try_malloc:
|
||||||
|
* @n_bytes: number of bytes to allocate.
|
||||||
|
*
|
||||||
|
* Attempts to allocate @n_bytes, and returns %NULL on failure.
|
||||||
|
* Contrast with g_malloc(), which aborts the program on failure.
|
||||||
|
*
|
||||||
|
* Returns: the allocated memory, or %NULL.
|
||||||
|
*/
|
||||||
|
gpointer g_try_malloc (gsize n_bytes)
|
||||||
|
{
|
||||||
|
gpointer mem;
|
||||||
|
|
||||||
|
if (n_bytes)
|
||||||
|
mem = malloc (n_bytes);
|
||||||
|
else
|
||||||
|
mem = NULL;
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_try_malloc_n:
|
||||||
|
* @n_blocks: the number of blocks to allocate
|
||||||
|
* @n_block_bytes: the size of each block in bytes
|
||||||
|
*
|
||||||
|
* This function is similar to g_try_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
* but care is taken to detect possible overflow during multiplication.
|
||||||
|
*
|
||||||
|
* Since: 2.24
|
||||||
|
* Returns: the allocated memory, or %NULL.
|
||||||
|
*/
|
||||||
|
gpointer g_try_malloc_n (gsize n_blocks, gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_try_malloc (n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_malloc:
|
||||||
|
* @n_bytes: the number of bytes to allocate
|
||||||
|
*
|
||||||
|
* Allocates @n_bytes bytes of memory.
|
||||||
|
* If @n_bytes is 0 it returns %NULL.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the allocated memory
|
||||||
|
*/
|
||||||
|
gpointer g_malloc (gsize n_bytes)
|
||||||
|
{
|
||||||
|
if (n_bytes) {
|
||||||
|
gpointer mem;
|
||||||
|
|
||||||
|
mem = malloc (n_bytes);
|
||||||
|
if (mem)
|
||||||
|
return mem;
|
||||||
|
|
||||||
|
//g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
|
||||||
|
// G_STRLOC, n_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_malloc_n:
|
||||||
|
* @n_blocks: the number of blocks to allocate
|
||||||
|
* @n_block_bytes: the size of each block in bytes
|
||||||
|
*
|
||||||
|
* This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
* but care is taken to detect possible overflow during multiplication.
|
||||||
|
*
|
||||||
|
* Since: 2.24
|
||||||
|
* Returns: a pointer to the allocated memory
|
||||||
|
*/
|
||||||
|
gpointer g_malloc_n (gsize n_blocks, gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
|
||||||
|
//g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
||||||
|
// G_STRLOC, n_blocks, n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_malloc (n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_malloc0:
|
||||||
|
* @n_bytes: the number of bytes to allocate
|
||||||
|
*
|
||||||
|
* Allocates @n_bytes bytes of memory, initialized to 0's.
|
||||||
|
* If @n_bytes is 0 it returns %NULL.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the allocated memory
|
||||||
|
*/
|
||||||
|
gpointer g_malloc0 (gsize n_bytes)
|
||||||
|
{
|
||||||
|
if (n_bytes) {
|
||||||
|
gpointer mem;
|
||||||
|
|
||||||
|
mem = calloc (1, n_bytes);
|
||||||
|
if (mem)
|
||||||
|
return mem;
|
||||||
|
|
||||||
|
//g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
|
||||||
|
// G_STRLOC, n_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_malloc0_n:
|
||||||
|
* @n_blocks: the number of blocks to allocate
|
||||||
|
* @n_block_bytes: the size of each block in bytes
|
||||||
|
*
|
||||||
|
* This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
* but care is taken to detect possible overflow during multiplication.
|
||||||
|
*
|
||||||
|
* Since: 2.24
|
||||||
|
* Returns: a pointer to the allocated memory
|
||||||
|
*/
|
||||||
|
gpointer g_malloc0_n (gsize n_blocks, gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
|
||||||
|
//g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
||||||
|
// G_STRLOC, n_blocks, n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_malloc0 (n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_try_malloc0:
|
||||||
|
* @n_bytes: number of bytes to allocate
|
||||||
|
*
|
||||||
|
* Attempts to allocate @n_bytes, initialized to 0's, and returns %NULL on
|
||||||
|
* failure. Contrast with g_malloc0(), which aborts the program on failure.
|
||||||
|
*
|
||||||
|
* Since: 2.8
|
||||||
|
* Returns: the allocated memory, or %NULL
|
||||||
|
*/
|
||||||
|
gpointer g_try_malloc0 (gsize n_bytes)
|
||||||
|
{
|
||||||
|
gpointer mem;
|
||||||
|
|
||||||
|
if (n_bytes)
|
||||||
|
mem = calloc (1, n_bytes);
|
||||||
|
else
|
||||||
|
mem = NULL;
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_realloc:
|
||||||
|
* @mem: (nullable): the memory to reallocate
|
||||||
|
* @n_bytes: new size of the memory in bytes
|
||||||
|
*
|
||||||
|
* Reallocates the memory pointed to by @mem, so that it now has space for
|
||||||
|
* @n_bytes bytes of memory. It returns the new address of the memory, which may
|
||||||
|
* have been moved. @mem may be %NULL, in which case it's considered to
|
||||||
|
* have zero-length. @n_bytes may be 0, in which case %NULL will be returned
|
||||||
|
* and @mem will be freed unless it is %NULL.
|
||||||
|
*
|
||||||
|
* Returns: the new address of the allocated memory
|
||||||
|
*/
|
||||||
|
gpointer g_realloc (gpointer mem, gsize n_bytes)
|
||||||
|
{
|
||||||
|
gpointer newmem;
|
||||||
|
|
||||||
|
if (n_bytes) {
|
||||||
|
newmem = realloc (mem, n_bytes);
|
||||||
|
if (newmem)
|
||||||
|
return newmem;
|
||||||
|
|
||||||
|
//g_error("%s: failed to allocate %"G_GSIZE_FORMAT" bytes", G_STRLOC, n_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (mem);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_realloc_n:
|
||||||
|
* @mem: (nullable): the memory to reallocate
|
||||||
|
* @n_blocks: the number of blocks to allocate
|
||||||
|
* @n_block_bytes: the size of each block in bytes
|
||||||
|
*
|
||||||
|
* This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
* but care is taken to detect possible overflow during multiplication.
|
||||||
|
*
|
||||||
|
* Since: 2.24
|
||||||
|
* Returns: the new address of the allocated memory
|
||||||
|
*/
|
||||||
|
gpointer g_realloc_n (gpointer mem, gsize n_blocks, gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
|
||||||
|
//g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
||||||
|
// G_STRLOC, n_blocks, n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_realloc (mem, n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_free:
|
||||||
|
* @mem: (nullable): the memory to free
|
||||||
|
*
|
||||||
|
* Frees the memory pointed to by @mem.
|
||||||
|
*
|
||||||
|
* If @mem is %NULL it simply returns, so there is no need to check @mem
|
||||||
|
* against %NULL before calling this function.
|
||||||
|
*/
|
||||||
|
void g_free (gpointer mem)
|
||||||
|
{
|
||||||
|
free (mem);
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_MEM_H__
|
||||||
|
#define __G_MEM_H__
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include "gmacros.h"
|
||||||
|
|
||||||
|
#define G_MAXSIZE ULONG_MAX
|
||||||
|
|
||||||
|
/* Optimise: avoid the call to the (slower) _n function if we can
|
||||||
|
* determine at compile-time that no overflow happens.
|
||||||
|
*/
|
||||||
|
#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
|
||||||
|
# define _G_NEW(struct_type, n_structs, func) \
|
||||||
|
(struct_type *) (G_GNUC_EXTENSION ({ \
|
||||||
|
gsize __n = (gsize) (n_structs); \
|
||||||
|
gsize __s = sizeof (struct_type); \
|
||||||
|
gpointer __p; \
|
||||||
|
if (__s == 1) \
|
||||||
|
__p = g_##func (__n); \
|
||||||
|
else if (__builtin_constant_p (__n) && \
|
||||||
|
(__s == 0 || __n <= G_MAXSIZE / __s)) \
|
||||||
|
__p = g_##func (__n * __s); \
|
||||||
|
else \
|
||||||
|
__p = g_##func##_n (__n, __s); \
|
||||||
|
__p; \
|
||||||
|
}))
|
||||||
|
# define _G_RENEW(struct_type, mem, n_structs, func) \
|
||||||
|
(struct_type *) (G_GNUC_EXTENSION ({ \
|
||||||
|
gsize __n = (gsize) (n_structs); \
|
||||||
|
gsize __s = sizeof (struct_type); \
|
||||||
|
gpointer __p = (gpointer) (mem); \
|
||||||
|
if (__s == 1) \
|
||||||
|
__p = g_##func (__p, __n); \
|
||||||
|
else if (__builtin_constant_p (__n) && \
|
||||||
|
(__s == 0 || __n <= G_MAXSIZE / __s)) \
|
||||||
|
__p = g_##func (__p, __n * __s); \
|
||||||
|
else \
|
||||||
|
__p = g_##func##_n (__p, __n, __s); \
|
||||||
|
__p; \
|
||||||
|
}))
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* Unoptimised version: always call the _n() function. */
|
||||||
|
#define _G_NEW(struct_type, n_structs, func) \
|
||||||
|
((struct_type *) g_##func##_n ((n_structs), sizeof (struct_type)))
|
||||||
|
#define _G_RENEW(struct_type, mem, n_structs, func) \
|
||||||
|
((struct_type *) g_##func##_n (mem, (n_structs), sizeof (struct_type)))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gpointer g_try_malloc (gsize n_bytes);
|
||||||
|
|
||||||
|
gpointer g_try_malloc0 (gsize n_bytes);
|
||||||
|
|
||||||
|
gpointer g_try_malloc_n (gsize n_blocks, gsize n_block_bytes);
|
||||||
|
|
||||||
|
gpointer g_malloc0_n (gsize n_blocks, gsize n_block_bytes);
|
||||||
|
|
||||||
|
gpointer g_realloc_n (gpointer mem, gsize n_blocks, gsize n_block_bytes);
|
||||||
|
|
||||||
|
gpointer g_malloc_n (gsize n_blocks, gsize n_block_bytes);
|
||||||
|
|
||||||
|
gpointer g_malloc0 (gsize n_bytes);
|
||||||
|
|
||||||
|
gpointer g_malloc (gsize n_bytes);
|
||||||
|
|
||||||
|
void g_free (gpointer mem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_try_new:
|
||||||
|
* @struct_type: the type of the elements to allocate
|
||||||
|
* @n_structs: the number of elements to allocate
|
||||||
|
*
|
||||||
|
* Attempts to allocate @n_structs elements of type @struct_type, and returns
|
||||||
|
* %NULL on failure. Contrast with g_new(), which aborts the program on failure.
|
||||||
|
* The returned pointer is cast to a pointer to the given type.
|
||||||
|
* The function returns %NULL when @n_structs is 0 of if an overflow occurs.
|
||||||
|
*
|
||||||
|
* Since: 2.8
|
||||||
|
* Returns: a pointer to the allocated memory, cast to a pointer to @struct_type
|
||||||
|
*/
|
||||||
|
#define g_try_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, try_malloc)
|
||||||
|
#define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0)
|
||||||
|
#define g_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc)
|
||||||
|
#define g_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, realloc)
|
||||||
|
|
||||||
|
#endif /* __G_MEM_H__ */
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_MESSAGES_H__
|
||||||
|
#define __G_MESSAGES_H__
|
||||||
|
|
||||||
|
#include "gmacros.h"
|
||||||
|
|
||||||
|
#define g_return_val_if_fail(expr,val) G_STMT_START{ (void)0; }G_STMT_END
|
||||||
|
#define g_return_if_fail(expr) G_STMT_START{ (void)0; }G_STMT_END
|
||||||
|
#define g_return_if_reached() G_STMT_START{ return; }G_STMT_END
|
||||||
|
#define g_return_val_if_reached(val) G_STMT_START{ return (val); }G_STMT_END
|
||||||
|
|
||||||
|
#endif /* __G_MESSAGES_H__ */
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_NODE_H__
|
||||||
|
#define __G_NODE_H__
|
||||||
|
|
||||||
|
#include "gmem.h"
|
||||||
|
|
||||||
|
/* Tree traverse orders */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
G_IN_ORDER,
|
||||||
|
G_PRE_ORDER,
|
||||||
|
G_POST_ORDER,
|
||||||
|
G_LEVEL_ORDER
|
||||||
|
} GTraverseType;
|
||||||
|
|
||||||
|
#endif /* __G_NODE_H__ */
|
|
@ -0,0 +1,400 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997, 1999 Peter Mattis, Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gpattern.h"
|
||||||
|
|
||||||
|
#include "gmacros.h"
|
||||||
|
#include "gmessages.h"
|
||||||
|
#include "gmem.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:patterns
|
||||||
|
* @title: Glob-style pattern matching
|
||||||
|
* @short_description: matches strings against patterns containing '*'
|
||||||
|
* (wildcard) and '?' (joker)
|
||||||
|
*
|
||||||
|
* The g_pattern_match* functions match a string
|
||||||
|
* against a pattern containing '*' and '?' wildcards with similar
|
||||||
|
* semantics as the standard glob() function: '*' matches an arbitrary,
|
||||||
|
* possibly empty, string, '?' matches an arbitrary character.
|
||||||
|
*
|
||||||
|
* Note that in contrast to glob(), the '/' character can be matched by
|
||||||
|
* the wildcards, there are no '[...]' character ranges and '*' and '?'
|
||||||
|
* can not be escaped to include them literally in a pattern.
|
||||||
|
*
|
||||||
|
* When multiple strings must be matched against the same pattern, it
|
||||||
|
* is better to compile the pattern to a #GPatternSpec using
|
||||||
|
* g_pattern_spec_new() and use g_pattern_match_string() instead of
|
||||||
|
* g_pattern_match_simple(). This avoids the overhead of repeated
|
||||||
|
* pattern compilation.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GPatternSpec:
|
||||||
|
*
|
||||||
|
* A GPatternSpec struct is the 'compiled' form of a pattern. This
|
||||||
|
* structure is opaque and its fields cannot be accessed directly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* keep enum and structure of gpattern.c and patterntest.c in sync */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
G_MATCH_ALL, /* "*A?A*" */
|
||||||
|
G_MATCH_ALL_TAIL, /* "*A?AA" */
|
||||||
|
G_MATCH_HEAD, /* "AAAA*" */
|
||||||
|
G_MATCH_TAIL, /* "*AAAA" */
|
||||||
|
G_MATCH_EXACT, /* "AAAAA" */
|
||||||
|
G_MATCH_LAST
|
||||||
|
} GMatchType;
|
||||||
|
|
||||||
|
struct _GPatternSpec
|
||||||
|
{
|
||||||
|
GMatchType match_type;
|
||||||
|
guint pattern_length;
|
||||||
|
guint min_length;
|
||||||
|
guint max_length;
|
||||||
|
gchar *pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* --- functions --- */
|
||||||
|
static inline gboolean g_pattern_ph_match (const gchar *match_pattern,
|
||||||
|
const gchar *match_string,
|
||||||
|
gboolean *wildcard_reached_p)
|
||||||
|
{
|
||||||
|
const gchar *pattern, *string;
|
||||||
|
gchar ch;
|
||||||
|
|
||||||
|
pattern = match_pattern;
|
||||||
|
string = match_string;
|
||||||
|
|
||||||
|
ch = *pattern;
|
||||||
|
pattern++;
|
||||||
|
while (ch)
|
||||||
|
{
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '?':
|
||||||
|
if (!*string)
|
||||||
|
return FALSE;
|
||||||
|
string = string + 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
*wildcard_reached_p = TRUE;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ch = *pattern;
|
||||||
|
pattern++;
|
||||||
|
if (ch == '?')
|
||||||
|
{
|
||||||
|
if (!*string)
|
||||||
|
return FALSE;
|
||||||
|
string = string + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (ch == '*' || ch == '?');
|
||||||
|
if (!ch)
|
||||||
|
return TRUE;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
gboolean next_wildcard_reached = FALSE;
|
||||||
|
while (ch != *string)
|
||||||
|
{
|
||||||
|
if (!*string)
|
||||||
|
return FALSE;
|
||||||
|
string = string + 1;
|
||||||
|
}
|
||||||
|
string++;
|
||||||
|
if (g_pattern_ph_match (pattern, string, &next_wildcard_reached))
|
||||||
|
return TRUE;
|
||||||
|
if (next_wildcard_reached)
|
||||||
|
/* the forthcoming pattern substring up to the next wildcard has
|
||||||
|
* been matched, but a mismatch occurred for the rest of the
|
||||||
|
* pattern, following the next wildcard.
|
||||||
|
* there's no need to advance the current match position any
|
||||||
|
* further if the rest pattern will not match.
|
||||||
|
*/
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
while (*string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (ch == *string)
|
||||||
|
string++;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = *pattern;
|
||||||
|
pattern++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *string == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *string_reverse(const gchar *string, gint string_length)
|
||||||
|
{
|
||||||
|
gchar *new_string;
|
||||||
|
gint i, j;
|
||||||
|
if (string == NULL || string_length <= 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_string = g_new(gchar, string_length + 1);
|
||||||
|
if (new_string) {
|
||||||
|
for (i = 0; i < string_length; i++) {
|
||||||
|
j = string_length - i - 1;
|
||||||
|
new_string[j] = string[i];
|
||||||
|
}
|
||||||
|
new_string[string_length] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_pattern_match:
|
||||||
|
* @pspec: a #GPatternSpec
|
||||||
|
* @string_length: the length of @string (in bytes, i.e. strlen(),
|
||||||
|
* not g_utf8_strlen())
|
||||||
|
* @string: the UTF-8 encoded string to match
|
||||||
|
* @string_reversed: (nullable): the reverse of @string or %NULL
|
||||||
|
*
|
||||||
|
* Matches a string against a compiled pattern. Passing the correct
|
||||||
|
* length of the string given is mandatory. The reversed string can be
|
||||||
|
* omitted by passing %NULL, this is more efficient if the reversed
|
||||||
|
* version of the string to be matched is not at hand, as
|
||||||
|
* g_pattern_match() will only construct it if the compiled pattern
|
||||||
|
* requires reverse matches.
|
||||||
|
*
|
||||||
|
* Note that, if the user code will (possibly) match a string against a
|
||||||
|
* multitude of patterns containing wildcards, chances are high that
|
||||||
|
* some patterns will require a reversed string. In this case, it's
|
||||||
|
* more efficient to provide the reversed string to avoid multiple
|
||||||
|
* constructions thereof in the various calls to g_pattern_match().
|
||||||
|
*
|
||||||
|
* Note also that the reverse of a UTF-8 encoded string can in general
|
||||||
|
* not be obtained by g_strreverse(). This works only if the string
|
||||||
|
* does not contain any multibyte characters. GLib offers the
|
||||||
|
* g_utf8_strreverse() function to reverse UTF-8 encoded strings.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if @string matches @pspec
|
||||||
|
**/
|
||||||
|
gboolean g_pattern_match (GPatternSpec *pspec,
|
||||||
|
guint string_length,
|
||||||
|
const gchar *string,
|
||||||
|
const gchar *string_reversed)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (pspec != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (string != NULL, FALSE);
|
||||||
|
|
||||||
|
if (string_length < pspec->min_length ||
|
||||||
|
string_length > pspec->max_length)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch (pspec->match_type)
|
||||||
|
{
|
||||||
|
gboolean dummy;
|
||||||
|
case G_MATCH_ALL:
|
||||||
|
return g_pattern_ph_match (pspec->pattern, string, &dummy);
|
||||||
|
case G_MATCH_ALL_TAIL:
|
||||||
|
if (string_reversed)
|
||||||
|
return g_pattern_ph_match (pspec->pattern, string_reversed, &dummy);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gboolean result;
|
||||||
|
gchar *tmp;
|
||||||
|
tmp = string_reverse (string, string_length);
|
||||||
|
result = g_pattern_ph_match (pspec->pattern, tmp, &dummy);
|
||||||
|
g_free (tmp);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case G_MATCH_HEAD:
|
||||||
|
if (pspec->pattern_length == string_length)
|
||||||
|
return strcmp (pspec->pattern, string) == 0;
|
||||||
|
else if (pspec->pattern_length)
|
||||||
|
return strncmp (pspec->pattern, string, pspec->pattern_length) == 0;
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
case G_MATCH_TAIL:
|
||||||
|
if (pspec->pattern_length)
|
||||||
|
return strcmp (pspec->pattern, string + (string_length - pspec->pattern_length)) == 0;
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
case G_MATCH_EXACT:
|
||||||
|
if (pspec->pattern_length != string_length)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return strcmp (pspec->pattern, string) == 0;
|
||||||
|
default:
|
||||||
|
g_return_val_if_fail (pspec->match_type < G_MATCH_LAST, FALSE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_pattern_spec_new:
|
||||||
|
* @pattern: a zero-terminated UTF-8 encoded string
|
||||||
|
*
|
||||||
|
* Compiles a pattern to a #GPatternSpec.
|
||||||
|
*
|
||||||
|
* Returns: a newly-allocated #GPatternSpec
|
||||||
|
**/
|
||||||
|
GPatternSpec* g_pattern_spec_new (const gchar *pattern)
|
||||||
|
{
|
||||||
|
GPatternSpec *pspec;
|
||||||
|
gboolean seen_joker = FALSE, seen_wildcard = FALSE, more_wildcards = FALSE;
|
||||||
|
gint hw_pos = -1, tw_pos = -1, hj_pos = -1, tj_pos = -1;
|
||||||
|
gboolean follows_wildcard = FALSE;
|
||||||
|
guint pending_jokers = 0;
|
||||||
|
const gchar *s;
|
||||||
|
gchar *d;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (pattern != NULL, NULL);
|
||||||
|
|
||||||
|
/* canonicalize pattern and collect necessary stats */
|
||||||
|
pspec = g_new (GPatternSpec, 1);
|
||||||
|
pspec->pattern_length = strlen (pattern);
|
||||||
|
pspec->min_length = 0;
|
||||||
|
pspec->max_length = 0;
|
||||||
|
pspec->pattern = g_new (gchar, pspec->pattern_length + 1);
|
||||||
|
d = pspec->pattern;
|
||||||
|
for (i = 0, s = pattern; *s != 0; s++)
|
||||||
|
{
|
||||||
|
switch (*s)
|
||||||
|
{
|
||||||
|
case '*':
|
||||||
|
if (follows_wildcard) /* compress multiple wildcards */
|
||||||
|
{
|
||||||
|
pspec->pattern_length--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
follows_wildcard = TRUE;
|
||||||
|
if (hw_pos < 0)
|
||||||
|
hw_pos = i;
|
||||||
|
tw_pos = i;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
pending_jokers++;
|
||||||
|
pspec->min_length++;
|
||||||
|
pspec->max_length += 4; /* maximum UTF-8 character length */
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
for (; pending_jokers; pending_jokers--, i++) {
|
||||||
|
*d++ = '?';
|
||||||
|
if (hj_pos < 0)
|
||||||
|
hj_pos = i;
|
||||||
|
tj_pos = i;
|
||||||
|
}
|
||||||
|
follows_wildcard = FALSE;
|
||||||
|
pspec->min_length++;
|
||||||
|
pspec->max_length++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*d++ = *s;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
for (; pending_jokers; pending_jokers--) {
|
||||||
|
*d++ = '?';
|
||||||
|
if (hj_pos < 0)
|
||||||
|
hj_pos = i;
|
||||||
|
tj_pos = i;
|
||||||
|
}
|
||||||
|
*d++ = 0;
|
||||||
|
seen_joker = hj_pos >= 0;
|
||||||
|
seen_wildcard = hw_pos >= 0;
|
||||||
|
more_wildcards = seen_wildcard && hw_pos != tw_pos;
|
||||||
|
if (seen_wildcard)
|
||||||
|
pspec->max_length = UINT_MAX;
|
||||||
|
|
||||||
|
/* special case sole head/tail wildcard or exact matches */
|
||||||
|
if (!seen_joker && !more_wildcards)
|
||||||
|
{
|
||||||
|
if (pspec->pattern[0] == '*')
|
||||||
|
{
|
||||||
|
pspec->match_type = G_MATCH_TAIL;
|
||||||
|
memmove (pspec->pattern, pspec->pattern + 1, --pspec->pattern_length);
|
||||||
|
pspec->pattern[pspec->pattern_length] = 0;
|
||||||
|
return pspec;
|
||||||
|
}
|
||||||
|
if (pspec->pattern_length > 0 &&
|
||||||
|
pspec->pattern[pspec->pattern_length - 1] == '*')
|
||||||
|
{
|
||||||
|
pspec->match_type = G_MATCH_HEAD;
|
||||||
|
pspec->pattern[--pspec->pattern_length] = 0;
|
||||||
|
return pspec;
|
||||||
|
}
|
||||||
|
if (!seen_wildcard)
|
||||||
|
{
|
||||||
|
pspec->match_type = G_MATCH_EXACT;
|
||||||
|
return pspec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now just need to distinguish between head or tail match start */
|
||||||
|
tw_pos = pspec->pattern_length - 1 - tw_pos; /* last pos to tail distance */
|
||||||
|
tj_pos = pspec->pattern_length - 1 - tj_pos; /* last pos to tail distance */
|
||||||
|
if (seen_wildcard)
|
||||||
|
pspec->match_type = tw_pos > hw_pos ? G_MATCH_ALL_TAIL : G_MATCH_ALL;
|
||||||
|
else /* seen_joker */
|
||||||
|
pspec->match_type = tj_pos > hj_pos ? G_MATCH_ALL_TAIL : G_MATCH_ALL;
|
||||||
|
if (pspec->match_type == G_MATCH_ALL_TAIL) {
|
||||||
|
gchar *tmp = pspec->pattern;
|
||||||
|
pspec->pattern = string_reverse (pspec->pattern, pspec->pattern_length);
|
||||||
|
g_free (tmp);
|
||||||
|
}
|
||||||
|
return pspec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_pattern_spec_free:
|
||||||
|
* @pspec: a #GPatternSpec
|
||||||
|
*
|
||||||
|
* Frees the memory allocated for the #GPatternSpec.
|
||||||
|
**/
|
||||||
|
void g_pattern_spec_free (GPatternSpec *pspec)
|
||||||
|
{
|
||||||
|
g_return_if_fail (pspec != NULL);
|
||||||
|
|
||||||
|
g_free (pspec->pattern);
|
||||||
|
g_free (pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_pattern_match_string:
|
||||||
|
* @pspec: a #GPatternSpec
|
||||||
|
* @string: the UTF-8 encoded string to match
|
||||||
|
*
|
||||||
|
* Matches a string against a compiled pattern. If the string is to be
|
||||||
|
* matched against more than one pattern, consider using
|
||||||
|
* g_pattern_match() instead while supplying the reversed string.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if @string matches @pspec
|
||||||
|
**/
|
||||||
|
gboolean g_pattern_match_string (GPatternSpec *pspec, const gchar *string)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (pspec != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (string != NULL, FALSE);
|
||||||
|
|
||||||
|
return g_pattern_match (pspec, strlen (string), string, NULL);
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997, 1999 Peter Mattis, Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_PATTERN_H__
|
||||||
|
#define __G_PATTERN_H__
|
||||||
|
|
||||||
|
#include "gtypes.h"
|
||||||
|
|
||||||
|
typedef struct _GPatternSpec GPatternSpec;
|
||||||
|
|
||||||
|
GPatternSpec* g_pattern_spec_new (const gchar *pattern);
|
||||||
|
void g_pattern_spec_free (GPatternSpec *pspec);
|
||||||
|
gboolean g_pattern_match (GPatternSpec *pspec,
|
||||||
|
guint string_length,
|
||||||
|
const gchar *string,
|
||||||
|
const gchar *string_reversed);
|
||||||
|
gboolean g_pattern_match_string (GPatternSpec *pspec,
|
||||||
|
const gchar *string);
|
||||||
|
|
||||||
|
#endif /* __G_PATTERN_H__ */
|
|
@ -0,0 +1,384 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Originally developed and coded by Makoto Matsumoto and Takuji
|
||||||
|
* Nishimura. Please mail <matumoto@math.keio.ac.jp>, if you're using
|
||||||
|
* code from this file in your own programs or libraries.
|
||||||
|
* Further information on the Mersenne Twister can be found at
|
||||||
|
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
|
||||||
|
* This code was adapted to glib by Sebastian Wilhelmi.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MT safe
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _CRT_RAND_S
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "grand.h"
|
||||||
|
#include "gmem.h"
|
||||||
|
#include "gmessages.h"
|
||||||
|
|
||||||
|
#define G_USEC_PER_SEC 1000000
|
||||||
|
|
||||||
|
#if defined(__MINGW64_VERSION_MAJOR) || defined(_WIN32)
|
||||||
|
errno_t rand_s(unsigned int* randomValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define G_GINT64_CONSTANT(val) (val##L)
|
||||||
|
|
||||||
|
/* Period parameters */
|
||||||
|
#define N 624
|
||||||
|
#define M 397
|
||||||
|
#define MATRIX_A 0x9908b0df /* constant vector a */
|
||||||
|
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
|
||||||
|
#define LOWER_MASK 0x7fffffff /* least significant r bits */
|
||||||
|
|
||||||
|
/* Tempering parameters */
|
||||||
|
#define TEMPERING_MASK_B 0x9d2c5680
|
||||||
|
#define TEMPERING_MASK_C 0xefc60000
|
||||||
|
#define TEMPERING_SHIFT_U(y) (y >> 11)
|
||||||
|
#define TEMPERING_SHIFT_S(y) (y << 7)
|
||||||
|
#define TEMPERING_SHIFT_T(y) (y << 15)
|
||||||
|
#define TEMPERING_SHIFT_L(y) (y >> 18)
|
||||||
|
|
||||||
|
struct _GRand
|
||||||
|
{
|
||||||
|
guint32 mt[N]; /* the array for the state vector */
|
||||||
|
guint mti;
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint get_random_version (void)
|
||||||
|
{
|
||||||
|
static gsize initialized = FALSE;
|
||||||
|
static guint random_version;
|
||||||
|
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
// g_warning ("Unknown G_RANDOM_VERSION \"%s\". Using version 2.2.", version_string);
|
||||||
|
random_version = 22;
|
||||||
|
initialized = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return random_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_rand_set_seed:
|
||||||
|
* @rand_: a #GRand
|
||||||
|
* @seed: a value to reinitialize the random number generator
|
||||||
|
*
|
||||||
|
* Sets the seed for the random number generator #GRand to @seed.
|
||||||
|
*/
|
||||||
|
void g_rand_set_seed (GRand *rand, guint32 seed)
|
||||||
|
{
|
||||||
|
g_return_if_fail (rand != NULL);
|
||||||
|
|
||||||
|
switch (get_random_version ())
|
||||||
|
{
|
||||||
|
case 20:
|
||||||
|
/* setting initial seeds to mt[N] using */
|
||||||
|
/* the generator Line 25 of Table 1 in */
|
||||||
|
/* [KNUTH 1981, The Art of Computer Programming */
|
||||||
|
/* Vol. 2 (2nd Ed.), pp102] */
|
||||||
|
|
||||||
|
if (seed == 0) /* This would make the PRNG produce only zeros */
|
||||||
|
seed = 0x6b842128; /* Just set it to another number */
|
||||||
|
|
||||||
|
rand->mt[0]= seed;
|
||||||
|
for (rand->mti=1; rand->mti<N; rand->mti++)
|
||||||
|
rand->mt[rand->mti] = (69069 * rand->mt[rand->mti-1]);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
|
||||||
|
/* In the previous version (see above), MSBs of the */
|
||||||
|
/* seed affect only MSBs of the array mt[]. */
|
||||||
|
|
||||||
|
rand->mt[0]= seed;
|
||||||
|
for (rand->mti=1; rand->mti<N; rand->mti++)
|
||||||
|
rand->mt[rand->mti] = 1812433253UL *
|
||||||
|
(rand->mt[rand->mti-1] ^ (rand->mt[rand->mti-1] >> 30)) + rand->mti;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_rand_new_with_seed:
|
||||||
|
* @seed: a value to initialize the random number generator
|
||||||
|
*
|
||||||
|
* Creates a new random number generator initialized with @seed.
|
||||||
|
*
|
||||||
|
* Returns: the new #GRand
|
||||||
|
**/
|
||||||
|
GRand* g_rand_new_with_seed (guint32 seed)
|
||||||
|
{
|
||||||
|
GRand *rand = g_new0 (GRand, 1);
|
||||||
|
g_rand_set_seed (rand, seed);
|
||||||
|
return rand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_rand_set_seed_array:
|
||||||
|
* @rand_: a #GRand
|
||||||
|
* @seed: array to initialize with
|
||||||
|
* @seed_length: length of array
|
||||||
|
*
|
||||||
|
* Initializes the random number generator by an array of longs.
|
||||||
|
* Array can be of arbitrary size, though only the first 624 values
|
||||||
|
* are taken. This function is useful if you have many low entropy
|
||||||
|
* seeds, or if you require more then 32 bits of actual entropy for
|
||||||
|
* your application.
|
||||||
|
*
|
||||||
|
* Since: 2.4
|
||||||
|
*/
|
||||||
|
void g_rand_set_seed_array (GRand *rand, const guint32 *seed, guint seed_length)
|
||||||
|
{
|
||||||
|
guint i, j, k;
|
||||||
|
|
||||||
|
g_return_if_fail (rand != NULL);
|
||||||
|
g_return_if_fail (seed_length >= 1);
|
||||||
|
|
||||||
|
g_rand_set_seed (rand, 19650218UL);
|
||||||
|
|
||||||
|
i=1; j=0;
|
||||||
|
k = (N>seed_length ? N : seed_length);
|
||||||
|
for (; k; k--)
|
||||||
|
{
|
||||||
|
rand->mt[i] = (rand->mt[i] ^
|
||||||
|
((rand->mt[i-1] ^ (rand->mt[i-1] >> 30)) * 1664525UL))
|
||||||
|
+ seed[j] + j; /* non linear */
|
||||||
|
rand->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
|
||||||
|
i++; j++;
|
||||||
|
if (i>=N)
|
||||||
|
{
|
||||||
|
rand->mt[0] = rand->mt[N-1];
|
||||||
|
i=1;
|
||||||
|
}
|
||||||
|
if (j>=seed_length)
|
||||||
|
j=0;
|
||||||
|
}
|
||||||
|
for (k=N-1; k; k--)
|
||||||
|
{
|
||||||
|
rand->mt[i] = (rand->mt[i] ^
|
||||||
|
((rand->mt[i-1] ^ (rand->mt[i-1] >> 30)) * 1566083941UL))
|
||||||
|
- i; /* non linear */
|
||||||
|
rand->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
|
||||||
|
i++;
|
||||||
|
if (i>=N)
|
||||||
|
{
|
||||||
|
rand->mt[0] = rand->mt[N-1];
|
||||||
|
i=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rand->mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_rand_new_with_seed_array:
|
||||||
|
* @seed: an array of seeds to initialize the random number generator
|
||||||
|
* @seed_length: an array of seeds to initialize the random number
|
||||||
|
* generator
|
||||||
|
*
|
||||||
|
* Creates a new random number generator initialized with @seed.
|
||||||
|
*
|
||||||
|
* Returns: the new #GRand
|
||||||
|
*
|
||||||
|
* Since: 2.4
|
||||||
|
*/
|
||||||
|
GRand *g_rand_new_with_seed_array (const guint32 *seed, guint seed_length)
|
||||||
|
{
|
||||||
|
GRand *rand = g_new0 (GRand, 1);
|
||||||
|
g_rand_set_seed_array (rand, seed, seed_length);
|
||||||
|
return rand;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint64 g_get_real_time (void)
|
||||||
|
{
|
||||||
|
#if defined(unix) || defined(__unix__) || defined(__unix) || defined (__MINGW32__) || defined(__APPLE__)
|
||||||
|
struct timeval r;
|
||||||
|
|
||||||
|
/* this is required on alpha, there the timeval structs are ints
|
||||||
|
* not longs and a cast only would fail horribly */
|
||||||
|
gettimeofday (&r, NULL);
|
||||||
|
|
||||||
|
return (((gint64) r.tv_sec) * 1000000) + r.tv_usec;
|
||||||
|
#else
|
||||||
|
FILETIME ft;
|
||||||
|
guint64 time64;
|
||||||
|
|
||||||
|
GetSystemTimeAsFileTime (&ft);
|
||||||
|
memmove (&time64, &ft, sizeof (FILETIME));
|
||||||
|
|
||||||
|
/* Convert from 100s of nanoseconds since 1601-01-01
|
||||||
|
* to Unix epoch. This is Y2038 safe.
|
||||||
|
*/
|
||||||
|
time64 -= G_GINT64_CONSTANT (116444736000000000);
|
||||||
|
time64 /= 10;
|
||||||
|
|
||||||
|
return time64;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_rand_new:
|
||||||
|
*
|
||||||
|
* Creates a new random number generator initialized with a seed taken
|
||||||
|
* either from `/dev/urandom` (if existing) or from the current time
|
||||||
|
* (as a fallback).
|
||||||
|
*
|
||||||
|
* On Windows, the seed is taken from rand_s().
|
||||||
|
*
|
||||||
|
* Returns: the new #GRand
|
||||||
|
*/
|
||||||
|
GRand *g_rand_new (void)
|
||||||
|
{
|
||||||
|
guint32 seed[4];
|
||||||
|
#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__)
|
||||||
|
static gboolean dev_urandom_exists = TRUE;
|
||||||
|
|
||||||
|
if (dev_urandom_exists)
|
||||||
|
{
|
||||||
|
FILE* dev_urandom;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dev_urandom = fopen("/dev/urandom", "rb");
|
||||||
|
}
|
||||||
|
while (dev_urandom == NULL && errno == EINTR);
|
||||||
|
|
||||||
|
if (dev_urandom)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
setvbuf (dev_urandom, NULL, _IONBF, 0);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
r = fread (seed, sizeof (seed), 1, dev_urandom);
|
||||||
|
}
|
||||||
|
while (errno == EINTR);
|
||||||
|
|
||||||
|
if (r != 1)
|
||||||
|
dev_urandom_exists = FALSE;
|
||||||
|
|
||||||
|
fclose (dev_urandom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dev_urandom_exists = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev_urandom_exists)
|
||||||
|
{
|
||||||
|
gint64 now_us = g_get_real_time ();
|
||||||
|
seed[0] = now_us / G_USEC_PER_SEC;
|
||||||
|
seed[1] = now_us % G_USEC_PER_SEC;
|
||||||
|
seed[2] = getpid ();
|
||||||
|
seed[3] = getppid ();
|
||||||
|
}
|
||||||
|
#else /* G_OS_WIN32 */
|
||||||
|
/* rand_s() is only available since Visual Studio 2005 and
|
||||||
|
* MinGW-w64 has a wrapper that will emulate rand_s() if it's not in msvcrt
|
||||||
|
*/
|
||||||
|
#if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__MINGW64_VERSION_MAJOR)
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4;/* array size of seed */ i++) {
|
||||||
|
rand_s(&seed[i]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#warning Using insecure seed for random number generation because of missing rand_s() in Windows XP
|
||||||
|
GTimeVal now;
|
||||||
|
|
||||||
|
g_get_current_time (&now);
|
||||||
|
seed[0] = now.tv_sec;
|
||||||
|
seed[1] = now.tv_usec;
|
||||||
|
seed[2] = getpid ();
|
||||||
|
seed[3] = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return g_rand_new_with_seed_array (seed, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_rand_int:
|
||||||
|
* @rand_: a #GRand
|
||||||
|
*
|
||||||
|
* Returns the next random #guint32 from @rand_ equally distributed over
|
||||||
|
* the range [0..2^32-1].
|
||||||
|
*
|
||||||
|
* Returns: a random number
|
||||||
|
*/
|
||||||
|
guint32 g_rand_int (GRand *rand)
|
||||||
|
{
|
||||||
|
guint32 y;
|
||||||
|
static const guint32 mag01[2]={0x0, MATRIX_A};
|
||||||
|
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||||
|
|
||||||
|
g_return_val_if_fail (rand != NULL, 0);
|
||||||
|
|
||||||
|
if (rand->mti >= N) { /* generate N words at one time */
|
||||||
|
int kk;
|
||||||
|
|
||||||
|
for (kk = 0; kk < N - M; kk++) {
|
||||||
|
y = (rand->mt[kk]&UPPER_MASK)|(rand->mt[kk+1]&LOWER_MASK);
|
||||||
|
rand->mt[kk] = rand->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||||
|
}
|
||||||
|
for (; kk < N - 1; kk++) {
|
||||||
|
y = (rand->mt[kk]&UPPER_MASK)|(rand->mt[kk+1]&LOWER_MASK);
|
||||||
|
rand->mt[kk] = rand->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||||
|
}
|
||||||
|
y = (rand->mt[N-1]&UPPER_MASK)|(rand->mt[0]&LOWER_MASK);
|
||||||
|
rand->mt[N-1] = rand->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||||
|
|
||||||
|
rand->mti = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
y = rand->mt[rand->mti++];
|
||||||
|
y ^= TEMPERING_SHIFT_U(y);
|
||||||
|
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
|
||||||
|
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
|
||||||
|
y ^= TEMPERING_SHIFT_L(y);
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_RAND_H__
|
||||||
|
#define __G_RAND_H__
|
||||||
|
|
||||||
|
#include "gtypes.h"
|
||||||
|
|
||||||
|
typedef struct _GRand GRand;
|
||||||
|
|
||||||
|
GRand *g_rand_new_with_seed(guint32 seed);
|
||||||
|
GRand *g_rand_new_with_seed_array (const guint32 *seed, guint seed_length);
|
||||||
|
GRand *g_rand_new(void);
|
||||||
|
guint32 g_rand_int(GRand *rand_);
|
||||||
|
|
||||||
|
#endif /* __G_RAND_H__ */
|
|
@ -0,0 +1,91 @@
|
||||||
|
/* GLIB sliced memory - fast concurrent memory chunk allocator
|
||||||
|
* Copyright (C) 2005 Tim Janik
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/* MT safe */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gtypes.h"
|
||||||
|
#include "gslice.h"
|
||||||
|
#include "gmem.h" /* gslice.h */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_slice_alloc:
|
||||||
|
* @block_size: the number of bytes to allocate
|
||||||
|
*
|
||||||
|
* Allocates a block of memory from the slice allocator.
|
||||||
|
* The block address handed out can be expected to be aligned
|
||||||
|
* to at least 1 * sizeof (void*),
|
||||||
|
* though in general slices are 2 * sizeof (void*) bytes aligned,
|
||||||
|
* if a malloc() fallback implementation is used instead,
|
||||||
|
* the alignment may be reduced in a libc dependent fashion.
|
||||||
|
* Note that the underlying slice allocation mechanism can
|
||||||
|
* be changed with the [`G_SLICE=always-malloc`][G_SLICE]
|
||||||
|
* environment variable.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the allocated memory block, which will be %NULL if and
|
||||||
|
* only if @mem_size is 0
|
||||||
|
*
|
||||||
|
* Since: 2.10
|
||||||
|
*/
|
||||||
|
gpointer g_slice_alloc (gsize mem_size)
|
||||||
|
{
|
||||||
|
return g_malloc (mem_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_slice_alloc0:
|
||||||
|
* @block_size: the number of bytes to allocate
|
||||||
|
*
|
||||||
|
* Allocates a block of memory via g_slice_alloc() and initializes
|
||||||
|
* the returned memory to 0. Note that the underlying slice allocation
|
||||||
|
* mechanism can be changed with the [`G_SLICE=always-malloc`][G_SLICE]
|
||||||
|
* environment variable.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the allocated block, which will be %NULL if and only
|
||||||
|
* if @mem_size is 0
|
||||||
|
*
|
||||||
|
* Since: 2.10
|
||||||
|
*/
|
||||||
|
gpointer g_slice_alloc0 (gsize mem_size)
|
||||||
|
{
|
||||||
|
gpointer mem = g_slice_alloc (mem_size);
|
||||||
|
if (mem)
|
||||||
|
memset (mem, 0, mem_size);
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_slice_free1:
|
||||||
|
* @block_size: the size of the block
|
||||||
|
* @mem_block: a pointer to the block to free
|
||||||
|
*
|
||||||
|
* Frees a block of memory.
|
||||||
|
*
|
||||||
|
* The memory must have been allocated via g_slice_alloc() or
|
||||||
|
* g_slice_alloc0() and the @block_size has to match the size
|
||||||
|
* specified upon allocation. Note that the exact release behaviour
|
||||||
|
* can be changed with the [`G_DEBUG=gc-friendly`][G_DEBUG] environment
|
||||||
|
* variable, also see [`G_SLICE`][G_SLICE] for related debugging options.
|
||||||
|
*
|
||||||
|
* If @mem_block is %NULL, this function does nothing.
|
||||||
|
*
|
||||||
|
* Since: 2.10
|
||||||
|
*/
|
||||||
|
void g_slice_free1 (gsize mem_size, gpointer mem_block)
|
||||||
|
{
|
||||||
|
g_free (mem_block);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* GLIB sliced memory - fast threaded memory chunk allocator
|
||||||
|
* Copyright (C) 2005 Tim Janik
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_SLICE_H__
|
||||||
|
#define __G_SLICE_H__
|
||||||
|
|
||||||
|
#include "gtypes.h"
|
||||||
|
|
||||||
|
#define g_slice_new(type) ((type*) g_slice_alloc (sizeof (type)))
|
||||||
|
#define g_slice_new0(type) ((type*) g_slice_alloc0 (sizeof (type)))
|
||||||
|
|
||||||
|
gpointer g_slice_alloc0 (gsize block_size);
|
||||||
|
gpointer g_slice_alloc (gsize block_size);
|
||||||
|
void g_slice_free1 (gsize block_size, gpointer mem_block);
|
||||||
|
|
||||||
|
#define g_slice_free(type, mem) \
|
||||||
|
G_STMT_START { \
|
||||||
|
if (1) g_slice_free1 (sizeof (type), (mem)); \
|
||||||
|
else (void) ((type*) 0 == (mem)); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#endif /* __G_SLICE_H__ */
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* GLib testing utilities
|
||||||
|
* Copyright (C) 2007 Imendio AB
|
||||||
|
* Authors: Tim Janik, Sven Herzberg
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gtestutils.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
g_assertion_message_expr (const char *file,
|
||||||
|
int line,
|
||||||
|
const char *expr)
|
||||||
|
{
|
||||||
|
if (!expr)
|
||||||
|
printf("%s:%d code should not be reached", file, line);
|
||||||
|
else
|
||||||
|
printf("%s:%d assertion failed: %s", file, line, expr);
|
||||||
|
|
||||||
|
abort();
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* GLib testing utilities
|
||||||
|
* Copyright (C) 2007 Imendio AB
|
||||||
|
* Authors: Tim Janik
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_TEST_UTILS_H__
|
||||||
|
#define __G_TEST_UTILS_H__
|
||||||
|
|
||||||
|
|
||||||
|
#if !(defined (G_STMT_START) && defined (G_STMT_END))
|
||||||
|
#define G_STMT_START do
|
||||||
|
#if defined (_MSC_VER) && (_MSC_VER >= 1500)
|
||||||
|
#define G_STMT_END \
|
||||||
|
__pragma(warning(push)) \
|
||||||
|
__pragma(warning(disable:4127)) \
|
||||||
|
while(0) \
|
||||||
|
__pragma(warning(pop))
|
||||||
|
#else
|
||||||
|
#define G_STMT_END while (0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
|
||||||
|
#define G_GNUC_NORETURN \
|
||||||
|
__attribute__((__noreturn__))
|
||||||
|
#else /* !__GNUC__ */
|
||||||
|
/* NOTE: MSVC has __declspec(noreturn) but unlike GCC __attribute__,
|
||||||
|
* __declspec can only be placed at the start of the function prototype
|
||||||
|
* and not at the end, so we can't use it without breaking API.
|
||||||
|
*/
|
||||||
|
#define G_GNUC_NORETURN
|
||||||
|
#endif /* !__GNUC__ */
|
||||||
|
|
||||||
|
void g_assertion_message_expr (const char *file,
|
||||||
|
int line,
|
||||||
|
const char *expr) G_GNUC_NORETURN;
|
||||||
|
|
||||||
|
#define g_assert_not_reached() G_STMT_START { g_assertion_message_expr (__FILE__, __LINE__, NULL); } G_STMT_END
|
||||||
|
#define g_assert(expr) G_STMT_START { \
|
||||||
|
if (expr) ; else \
|
||||||
|
g_assertion_message_expr (__FILE__, __LINE__, #expr); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#endif /* __G_TEST_UTILS_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,55 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_TREE_H__
|
||||||
|
#define __G_TREE_H__
|
||||||
|
|
||||||
|
typedef struct _GTree GTree;
|
||||||
|
|
||||||
|
typedef gboolean (*GTraverseFunc) (gpointer key, gpointer value, gpointer data);
|
||||||
|
|
||||||
|
/* Balanced binary trees
|
||||||
|
*/
|
||||||
|
GTree* g_tree_new (GCompareFunc key_compare_func);
|
||||||
|
|
||||||
|
GTree* g_tree_new_full (GCompareDataFunc key_compare_func,
|
||||||
|
gpointer key_compare_data,
|
||||||
|
GDestroyNotify key_destroy_func,
|
||||||
|
GDestroyNotify value_destroy_func);
|
||||||
|
|
||||||
|
GTree* g_tree_ref (GTree *tree);
|
||||||
|
|
||||||
|
void g_tree_destroy (GTree *tree);
|
||||||
|
|
||||||
|
void g_tree_insert (GTree *tree, gpointer key, gpointer value);
|
||||||
|
|
||||||
|
gboolean g_tree_remove (GTree *tree, gconstpointer key);
|
||||||
|
|
||||||
|
gpointer g_tree_lookup (GTree *tree, gconstpointer key);
|
||||||
|
|
||||||
|
void g_tree_foreach (GTree *tree, GTraverseFunc func, gpointer user_data);
|
||||||
|
|
||||||
|
gint g_tree_nnodes (GTree *tree);
|
||||||
|
|
||||||
|
#endif /* __G_TREE_H__ */
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_TYPES_H__
|
||||||
|
#define __G_TYPES_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
/* typedefs for glib related types that may still be referenced */
|
||||||
|
typedef void* gpointer;
|
||||||
|
|
||||||
|
typedef const void *gconstpointer;
|
||||||
|
|
||||||
|
typedef int gint;
|
||||||
|
typedef uint8_t guint8;
|
||||||
|
typedef int8_t gint8;
|
||||||
|
typedef uint16_t guint16;
|
||||||
|
typedef int16_t gint16;
|
||||||
|
typedef uint32_t guint32;
|
||||||
|
typedef int32_t gint32;
|
||||||
|
typedef uint64_t guint64;
|
||||||
|
typedef int64_t gint64;
|
||||||
|
typedef unsigned int guint;
|
||||||
|
typedef char gchar;
|
||||||
|
typedef int gboolean;
|
||||||
|
typedef unsigned long gulong;
|
||||||
|
typedef unsigned long gsize;
|
||||||
|
|
||||||
|
typedef gint grefcount;
|
||||||
|
|
||||||
|
typedef volatile gint gatomicrefcount;
|
||||||
|
|
||||||
|
typedef void (*GDestroyNotify) (gpointer data);
|
||||||
|
|
||||||
|
typedef gint (*GCompareFunc) (gconstpointer a, gconstpointer b);
|
||||||
|
|
||||||
|
typedef gint (*GCompareDataFunc) (gconstpointer a, gconstpointer b, gpointer user_data);
|
||||||
|
|
||||||
|
typedef guint (*GHashFunc) (gconstpointer key);
|
||||||
|
|
||||||
|
typedef gboolean (*GEqualFunc) (gconstpointer a, gconstpointer b);
|
||||||
|
|
||||||
|
typedef void (*GHFunc) (gpointer key, gpointer value, gpointer user_data);
|
||||||
|
|
||||||
|
typedef gpointer (*GCopyFunc) (gconstpointer src, gpointer data);
|
||||||
|
|
||||||
|
#endif /* __G_TYPES_H__ */
|
|
@ -1,4 +1,5 @@
|
||||||
/* By Dang Hoang Vu <dang.hvu -at- gmail.com>, 2015 */
|
/* By Dang Hoang Vu <dang.hvu -at- gmail.com>, 2015 */
|
||||||
|
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||||
|
|
||||||
#ifndef UC_QEMU_H
|
#ifndef UC_QEMU_H
|
||||||
#define UC_QEMU_H
|
#define UC_QEMU_H
|
||||||
|
@ -13,25 +14,23 @@ struct uc_struct;
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
|
|
||||||
#include "qemu/thread.h"
|
#include "qemu/thread.h"
|
||||||
#include "include/qom/cpu.h"
|
#include "hw/core/cpu.h"
|
||||||
|
|
||||||
#include "vl.h"
|
#include "vl.h"
|
||||||
|
|
||||||
// This two struct is originally from qemu/include/exec/cpu-all.h
|
// This struct is originally from qemu/include/exec/ramblock.h
|
||||||
// Temporarily moved here since there is circular inclusion.
|
// Temporarily moved here since there is circular inclusion.
|
||||||
typedef struct RAMBlock {
|
struct RAMBlock {
|
||||||
struct MemoryRegion *mr;
|
struct MemoryRegion *mr;
|
||||||
uint8_t *host;
|
uint8_t *host;
|
||||||
ram_addr_t offset;
|
ram_addr_t offset;
|
||||||
ram_addr_t length;
|
ram_addr_t used_length;
|
||||||
|
ram_addr_t max_length;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
char idstr[256];
|
/* RCU-enabled, writes protected by the ramlist lock */
|
||||||
/* Reads can take either the iothread or the ramlist lock.
|
QLIST_ENTRY(RAMBlock) next;
|
||||||
* Writes must take both locks.
|
size_t page_size;
|
||||||
*/
|
};
|
||||||
QTAILQ_ENTRY(RAMBlock) next;
|
|
||||||
int fd;
|
|
||||||
} RAMBlock;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
|
@ -40,12 +39,10 @@ typedef struct {
|
||||||
hwaddr len;
|
hwaddr len;
|
||||||
} BounceBuffer;
|
} BounceBuffer;
|
||||||
|
|
||||||
|
// This struct is originally from qemu/include/exec/ramlist.h
|
||||||
typedef struct RAMList {
|
typedef struct RAMList {
|
||||||
/* Protected by the iothread lock. */
|
|
||||||
unsigned long *dirty_memory[DIRTY_MEMORY_NUM];
|
|
||||||
RAMBlock *mru_block;
|
RAMBlock *mru_block;
|
||||||
QTAILQ_HEAD(, RAMBlock) blocks;
|
QLIST_HEAD(, RAMBlock) blocks;
|
||||||
uint32_t version;
|
|
||||||
} RAMList;
|
} RAMList;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* Unicorn Emulator Engine */
|
/* Unicorn Emulator Engine */
|
||||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
|
||||||
|
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||||
|
|
||||||
|
|
||||||
#ifndef UC_PRIV_H
|
#ifndef UC_PRIV_H
|
||||||
#define UC_PRIV_H
|
#define UC_PRIV_H
|
||||||
|
@ -14,16 +16,17 @@
|
||||||
// These are masks of supported modes for each cpu/arch.
|
// These are masks of supported modes for each cpu/arch.
|
||||||
// They should be updated when changes are made to the uc_mode enum typedef.
|
// They should be updated when changes are made to the uc_mode enum typedef.
|
||||||
#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \
|
#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \
|
||||||
|UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN|UC_MODE_ARMBE8)
|
|UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN)
|
||||||
#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN)
|
#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN)
|
||||||
#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN)
|
#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN)
|
||||||
#define UC_MODE_PPC_MASK (UC_MODE_PPC64|UC_MODE_BIG_ENDIAN)
|
#define UC_MODE_PPC_MASK (UC_MODE_PPC32|UC_MODE_PPC64|UC_MODE_BIG_ENDIAN)
|
||||||
#define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN)
|
#define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN)
|
||||||
#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN)
|
#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN)
|
||||||
|
#define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN)
|
||||||
|
|
||||||
#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||||
|
|
||||||
#define READ_QWORD(x) ((uint64)x)
|
#define READ_QWORD(x) ((uint64_t)x)
|
||||||
#define READ_DWORD(x) (x & 0xffffffff)
|
#define READ_DWORD(x) (x & 0xffffffff)
|
||||||
#define READ_WORD(x) (x & 0xffff)
|
#define READ_WORD(x) (x & 0xffff)
|
||||||
#define READ_BYTE_H(x) ((x & 0xffff) >> 8)
|
#define READ_BYTE_H(x) ((x & 0xffff) >> 8)
|
||||||
|
@ -34,20 +37,19 @@
|
||||||
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))
|
||||||
|
|
||||||
|
|
||||||
typedef struct ModuleEntry {
|
|
||||||
void (*init)(void);
|
|
||||||
QTAILQ_ENTRY(ModuleEntry) node;
|
|
||||||
module_init_type type;
|
|
||||||
} ModuleEntry;
|
|
||||||
|
|
||||||
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
|
|
||||||
|
|
||||||
typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result);
|
typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result);
|
||||||
|
|
||||||
// return 0 on success, -1 on failure
|
// return 0 on success, -1 on failure
|
||||||
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, int count);
|
||||||
typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count);
|
||||||
|
|
||||||
|
typedef int (*context_reg_read_t)(struct uc_context *ctx, unsigned int *regs, void **vals, int count);
|
||||||
|
typedef int (*context_reg_write_t)(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count);
|
||||||
|
typedef struct {
|
||||||
|
context_reg_read_t context_reg_read;
|
||||||
|
context_reg_write_t context_reg_write;
|
||||||
|
} context_reg_rw_t;
|
||||||
|
|
||||||
typedef void (*reg_reset_t)(struct uc_struct *uc);
|
typedef void (*reg_reset_t)(struct uc_struct *uc);
|
||||||
|
|
||||||
typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len);
|
typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len);
|
||||||
|
@ -57,9 +59,7 @@ typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, int l
|
||||||
typedef void (*uc_args_void_t)(void*);
|
typedef void (*uc_args_void_t)(void*);
|
||||||
|
|
||||||
typedef void (*uc_args_uc_t)(struct uc_struct*);
|
typedef void (*uc_args_uc_t)(struct uc_struct*);
|
||||||
typedef int (*uc_args_int_uc_t)(struct uc_struct*);
|
typedef void (*uc_args_int_uc_t)(struct uc_struct*);
|
||||||
|
|
||||||
typedef bool (*uc_args_tcg_enable_t)(struct uc_struct*);
|
|
||||||
|
|
||||||
typedef void (*uc_args_uc_long_t)(struct uc_struct*, unsigned long);
|
typedef void (*uc_args_uc_long_t)(struct uc_struct*, unsigned long);
|
||||||
|
|
||||||
|
@ -73,8 +73,12 @@ typedef void (*uc_mem_unmap_t)(struct uc_struct*, MemoryRegion *mr);
|
||||||
|
|
||||||
typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly);
|
typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly);
|
||||||
|
|
||||||
|
typedef int (*uc_cpus_init)(struct uc_struct *, const char *);
|
||||||
|
|
||||||
|
typedef MemoryRegion* (*uc_memory_map_io_t)(struct uc_struct *uc, ram_addr_t begin, size_t size, uc_cb_mmio_read_t read_cb, uc_cb_mmio_write_t write_cb, void *user_data_read, void *user_data_write);
|
||||||
|
|
||||||
// which interrupt should make emulation stop?
|
// which interrupt should make emulation stop?
|
||||||
typedef bool (*uc_args_int_t)(int intno);
|
typedef bool (*uc_args_int_t)(struct uc_struct *uc, int intno);
|
||||||
|
|
||||||
// some architecture redirect virtual memory to physical memory like Mips
|
// some architecture redirect virtual memory to physical memory like Mips
|
||||||
typedef uint64_t (*uc_mem_redirect_t)(uint64_t address);
|
typedef uint64_t (*uc_mem_redirect_t)(uint64_t address);
|
||||||
|
@ -82,6 +86,15 @@ typedef uint64_t (*uc_mem_redirect_t)(uint64_t address);
|
||||||
// validate if Unicorn supports hooking a given instruction
|
// validate if Unicorn supports hooking a given instruction
|
||||||
typedef bool(*uc_insn_hook_validate)(uint32_t insn_enum);
|
typedef bool(*uc_insn_hook_validate)(uint32_t insn_enum);
|
||||||
|
|
||||||
|
// init target page
|
||||||
|
typedef void (*uc_target_page_init)(struct uc_struct *);
|
||||||
|
|
||||||
|
// soft float init
|
||||||
|
typedef void (*uc_softfloat_initialize)(void);
|
||||||
|
|
||||||
|
// tcg flush softmmu tlb
|
||||||
|
typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc);
|
||||||
|
|
||||||
struct hook {
|
struct hook {
|
||||||
int type; // UC_HOOK_*
|
int type; // UC_HOOK_*
|
||||||
int insn; // instruction for HOOK_INSN
|
int insn; // instruction for HOOK_INSN
|
||||||
|
@ -93,8 +106,12 @@ struct hook {
|
||||||
};
|
};
|
||||||
|
|
||||||
// hook list offsets
|
// hook list offsets
|
||||||
|
//
|
||||||
|
// The lowest 6 bits are used for hook type index while the others
|
||||||
|
// are used for hook flags.
|
||||||
|
//
|
||||||
// mirrors the order of uc_hook_type from include/unicorn/unicorn.h
|
// mirrors the order of uc_hook_type from include/unicorn/unicorn.h
|
||||||
enum uc_hook_idx {
|
typedef enum uc_hook_idx {
|
||||||
UC_HOOK_INTR_IDX,
|
UC_HOOK_INTR_IDX,
|
||||||
UC_HOOK_INSN_IDX,
|
UC_HOOK_INSN_IDX,
|
||||||
UC_HOOK_CODE_IDX,
|
UC_HOOK_CODE_IDX,
|
||||||
|
@ -112,7 +129,16 @@ enum uc_hook_idx {
|
||||||
UC_HOOK_INSN_INVALID_IDX,
|
UC_HOOK_INSN_INVALID_IDX,
|
||||||
|
|
||||||
UC_HOOK_MAX,
|
UC_HOOK_MAX,
|
||||||
};
|
} uc_hook_idx;
|
||||||
|
|
||||||
|
// The lowest 6 bits are used for hook type index.
|
||||||
|
#define UC_HOOK_IDX_MASK ((1<<6)-1)
|
||||||
|
|
||||||
|
// hook flags
|
||||||
|
#define UC_HOOK_FLAG_NO_STOP (1 << 6) // Don't stop emulation in this uc_tracecode.
|
||||||
|
|
||||||
|
// The rest of bits are reserved for hook flags.
|
||||||
|
#define UC_HOOK_FLAG_MASK (~(UC_HOOK_IDX_MASK))
|
||||||
|
|
||||||
#define HOOK_FOREACH_VAR_DECLARE \
|
#define HOOK_FOREACH_VAR_DECLARE \
|
||||||
struct list_item *cur
|
struct list_item *cur
|
||||||
|
@ -145,11 +171,15 @@ static inline bool _hook_exists_bounded(struct list_item *cur, uint64_t addr)
|
||||||
//relloc increment, KEEP THIS A POWER OF 2!
|
//relloc increment, KEEP THIS A POWER OF 2!
|
||||||
#define MEM_BLOCK_INCR 32
|
#define MEM_BLOCK_INCR 32
|
||||||
|
|
||||||
|
typedef struct TargetPageBits TargetPageBits;
|
||||||
|
typedef struct TCGContext TCGContext;
|
||||||
|
|
||||||
struct uc_struct {
|
struct uc_struct {
|
||||||
uc_arch arch;
|
uc_arch arch;
|
||||||
uc_mode mode;
|
uc_mode mode;
|
||||||
uc_err errnum; // qemu/cpu-exec.c
|
uc_err errnum; // qemu/cpu-exec.c
|
||||||
AddressSpace as;
|
AddressSpace address_space_memory;
|
||||||
|
AddressSpace address_space_io;
|
||||||
query_t query;
|
query_t query;
|
||||||
reg_read_t reg_read;
|
reg_read_t reg_read;
|
||||||
reg_write_t reg_write;
|
reg_write_t reg_write;
|
||||||
|
@ -160,56 +190,55 @@ struct uc_struct {
|
||||||
uc_args_void_t release; // release resource when uc_close()
|
uc_args_void_t release; // release resource when uc_close()
|
||||||
uc_args_uc_u64_t set_pc; // set PC for tracecode
|
uc_args_uc_u64_t set_pc; // set PC for tracecode
|
||||||
uc_args_int_t stop_interrupt; // check if the interrupt should stop emulation
|
uc_args_int_t stop_interrupt; // check if the interrupt should stop emulation
|
||||||
|
uc_memory_map_io_t memory_map_io;
|
||||||
|
|
||||||
uc_args_uc_t init_arch, cpu_exec_init_all;
|
uc_args_uc_t init_arch, cpu_exec_init_all;
|
||||||
uc_args_int_uc_t vm_start;
|
uc_args_int_uc_t vm_start;
|
||||||
uc_args_tcg_enable_t tcg_enabled;
|
|
||||||
uc_args_uc_long_t tcg_exec_init;
|
uc_args_uc_long_t tcg_exec_init;
|
||||||
uc_args_uc_ram_size_t memory_map;
|
uc_args_uc_ram_size_t memory_map;
|
||||||
uc_args_uc_ram_size_ptr_t memory_map_ptr;
|
uc_args_uc_ram_size_ptr_t memory_map_ptr;
|
||||||
uc_mem_unmap_t memory_unmap;
|
uc_mem_unmap_t memory_unmap;
|
||||||
uc_readonly_mem_t readonly_mem;
|
uc_readonly_mem_t readonly_mem;
|
||||||
uc_mem_redirect_t mem_redirect;
|
uc_mem_redirect_t mem_redirect;
|
||||||
// TODO: remove current_cpu, as it's a flag for something else ("cpu running"?)
|
uc_cpus_init cpus_init;
|
||||||
CPUState *cpu, *current_cpu;
|
uc_target_page_init target_page;
|
||||||
|
uc_softfloat_initialize softfloat_initialize;
|
||||||
|
uc_tcg_flush_tlb tcg_flush_tlb;
|
||||||
|
|
||||||
|
/* only 1 cpu in unicorn,
|
||||||
|
do not need current_cpu to handle current running cpu. */
|
||||||
|
CPUState *cpu;
|
||||||
|
|
||||||
uc_insn_hook_validate insn_hook_validate;
|
uc_insn_hook_validate insn_hook_validate;
|
||||||
|
|
||||||
MemoryRegion *system_memory; // qemu/exec.c
|
MemoryRegion *system_memory; // qemu/exec.c
|
||||||
MemoryRegion io_mem_rom; // qemu/exec.c
|
MemoryRegion *system_io; // qemu/exec.c
|
||||||
MemoryRegion io_mem_notdirty; // qemu/exec.c
|
|
||||||
MemoryRegion io_mem_unassigned; // qemu/exec.c
|
MemoryRegion io_mem_unassigned; // qemu/exec.c
|
||||||
MemoryRegion io_mem_watch; // qemu/exec.c
|
|
||||||
RAMList ram_list; // qemu/exec.c
|
RAMList ram_list; // qemu/exec.c
|
||||||
|
/* qemu/exec.c */
|
||||||
|
unsigned int alloc_hint;
|
||||||
|
/* qemu/exec-vary.c */
|
||||||
|
TargetPageBits *init_target_page;
|
||||||
BounceBuffer bounce; // qemu/cpu-exec.c
|
BounceBuffer bounce; // qemu/cpu-exec.c
|
||||||
volatile sig_atomic_t exit_request; // qemu/cpu-exec.c
|
volatile sig_atomic_t exit_request; // qemu/cpu-exec.c
|
||||||
bool global_dirty_log; // qemu/memory.c
|
/* qemu/accel/tcg/cpu-exec-common.c */
|
||||||
|
/* always be true after call tcg_exec_init(). */
|
||||||
|
bool tcg_allowed;
|
||||||
/* This is a multi-level map on the virtual address space.
|
/* This is a multi-level map on the virtual address space.
|
||||||
The bottom level has pointers to PageDesc. */
|
The bottom level has pointers to PageDesc. */
|
||||||
void **l1_map; // qemu/translate-all.c
|
void **l1_map; // qemu/accel/tcg/translate-all.c
|
||||||
size_t l1_map_size;
|
size_t l1_map_size;
|
||||||
|
/* qemu/accel/tcg/translate-all.c */
|
||||||
|
int v_l1_size;
|
||||||
|
int v_l1_shift;
|
||||||
|
int v_l2_levels;
|
||||||
/* code generation context */
|
/* code generation context */
|
||||||
void *tcg_ctx; // for "TCGContext tcg_ctx" in qemu/translate-all.c
|
TCGContext *tcg_ctx;
|
||||||
/* memory.c */
|
/* memory.c */
|
||||||
unsigned memory_region_transaction_depth;
|
|
||||||
bool memory_region_update_pending;
|
|
||||||
bool ioeventfd_update_pending;
|
|
||||||
QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners;
|
QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners;
|
||||||
QTAILQ_HEAD(, AddressSpace) address_spaces;
|
QTAILQ_HEAD(, AddressSpace) address_spaces;
|
||||||
MachineState *machine_state;
|
GHashTable *flat_views;
|
||||||
// qom/object.c
|
bool memory_region_update_pending;
|
||||||
GHashTable *type_table;
|
|
||||||
Type type_interface;
|
|
||||||
Object *root;
|
|
||||||
Object *owner;
|
|
||||||
bool enumerating_types;
|
|
||||||
// util/module.c
|
|
||||||
ModuleTypeList init_type_list[MODULE_INIT_MAX];
|
|
||||||
// hw/intc/apic_common.c
|
|
||||||
DeviceState *vapic;
|
|
||||||
int apic_no;
|
|
||||||
bool mmio_registered;
|
|
||||||
bool apic_report_tpr_access;
|
|
||||||
|
|
||||||
// linked lists containing hooks per type
|
// linked lists containing hooks per type
|
||||||
struct list hook[UC_HOOK_MAX];
|
struct list hook[UC_HOOK_MAX];
|
||||||
|
@ -221,8 +250,6 @@ struct uc_struct {
|
||||||
size_t emu_counter; // current counter of uc_emu_start()
|
size_t emu_counter; // current counter of uc_emu_start()
|
||||||
size_t emu_count; // save counter of uc_emu_start()
|
size_t emu_count; // save counter of uc_emu_start()
|
||||||
|
|
||||||
uint64_t block_addr; // save the last block address we hooked
|
|
||||||
|
|
||||||
int size_recur_mem; // size for mem access when in a recursive call
|
int size_recur_mem; // size for mem access when in a recursive call
|
||||||
|
|
||||||
bool init_tcg; // already initialized local TCGv variables?
|
bool init_tcg; // already initialized local TCGv variables?
|
||||||
|
@ -239,19 +266,22 @@ struct uc_struct {
|
||||||
uint64_t addr_end; // address where emulation stops (@end param of uc_emu_start())
|
uint64_t addr_end; // address where emulation stops (@end param of uc_emu_start())
|
||||||
|
|
||||||
int thumb; // thumb mode for ARM
|
int thumb; // thumb mode for ARM
|
||||||
int bswap_code; // For mixed endian mode
|
|
||||||
// full TCG cache leads to middle-block break in the last translation?
|
|
||||||
bool block_full;
|
|
||||||
int size_arg; // what tcg arg slot do we need to update with the size of the block?
|
|
||||||
MemoryRegion **mapped_blocks;
|
MemoryRegion **mapped_blocks;
|
||||||
uint32_t mapped_block_count;
|
uint32_t mapped_block_count;
|
||||||
uint32_t mapped_block_cache_index;
|
uint32_t mapped_block_cache_index;
|
||||||
void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c)
|
void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c)
|
||||||
uint32_t target_page_size;
|
uint32_t target_page_size;
|
||||||
uint32_t target_page_align;
|
uint32_t target_page_align;
|
||||||
|
uint64_t qemu_host_page_size;
|
||||||
|
uint64_t qemu_real_host_page_size;
|
||||||
|
int qemu_icache_linesize;
|
||||||
|
/* ARCH_REGS_STORAGE_SIZE */
|
||||||
|
int cpu_context_size;
|
||||||
uint64_t next_pc; // save next PC for some special cases
|
uint64_t next_pc; // save next PC for some special cases
|
||||||
bool hook_insert; // insert new hook at begin of the hook list (append by default)
|
bool hook_insert; // insert new hook at begin of the hook list (append by default)
|
||||||
|
bool first_tb; // is this the first Translation-Block ever generated since uc_emu_start()?
|
||||||
struct list saved_contexts; // The contexts saved by this uc_struct.
|
struct list saved_contexts; // The contexts saved by this uc_struct.
|
||||||
|
bool no_exit_request; // Disable check_exit_request temporarily. A workaround to treat the IT block as a whole block.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Metadata stub for the variable-size cpu context used with uc_context_*()
|
// Metadata stub for the variable-size cpu context used with uc_context_*()
|
||||||
|
@ -259,7 +289,9 @@ struct uc_struct {
|
||||||
struct uc_context {
|
struct uc_context {
|
||||||
size_t context_size; // size of the real internal context structure
|
size_t context_size; // size of the real internal context structure
|
||||||
size_t jmp_env_size; // size of cpu->jmp_env
|
size_t jmp_env_size; // size of cpu->jmp_env
|
||||||
struct uc_struct* uc; // the uc_struct which creates this context
|
uc_mode mode; // the mode of this context (uc may be free-ed already)
|
||||||
|
uc_arch arch; // the arch of this context (uc may be free-ed already)
|
||||||
|
struct uc_struct *uc; // the uc_struct which creates this context
|
||||||
char data[0]; // context + cpu->jmp_env
|
char data[0]; // context + cpu->jmp_env
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,27 @@ typedef enum uc_arm_reg {
|
||||||
UC_ARM_REG_MSP,
|
UC_ARM_REG_MSP,
|
||||||
UC_ARM_REG_PSP,
|
UC_ARM_REG_PSP,
|
||||||
UC_ARM_REG_CONTROL,
|
UC_ARM_REG_CONTROL,
|
||||||
|
UC_ARM_REG_IAPSR,
|
||||||
|
UC_ARM_REG_EAPSR,
|
||||||
|
UC_ARM_REG_XPSR,
|
||||||
|
UC_ARM_REG_EPSR,
|
||||||
|
UC_ARM_REG_IEPSR,
|
||||||
|
UC_ARM_REG_PRIMASK,
|
||||||
|
UC_ARM_REG_BASEPRI,
|
||||||
|
UC_ARM_REG_BASEPRI_MAX,
|
||||||
|
UC_ARM_REG_FAULTMASK,
|
||||||
|
UC_ARM_REG_APSR_NZCVQ,
|
||||||
|
UC_ARM_REG_APSR_G,
|
||||||
|
UC_ARM_REG_APSR_NZCVQG,
|
||||||
|
UC_ARM_REG_IAPSR_NZCVQ,
|
||||||
|
UC_ARM_REG_IAPSR_G,
|
||||||
|
UC_ARM_REG_IAPSR_NZCVQG,
|
||||||
|
UC_ARM_REG_EAPSR_NZCVQ,
|
||||||
|
UC_ARM_REG_EAPSR_G,
|
||||||
|
UC_ARM_REG_EAPSR_NZCVQG,
|
||||||
|
UC_ARM_REG_XPSR_NZCVQ,
|
||||||
|
UC_ARM_REG_XPSR_G,
|
||||||
|
UC_ARM_REG_XPSR_NZCVQG,
|
||||||
UC_ARM_REG_ENDING, // <-- mark the end of the list or registers
|
UC_ARM_REG_ENDING, // <-- mark the end of the list or registers
|
||||||
|
|
||||||
//> alias registers
|
//> alias registers
|
||||||
|
|
|
@ -64,23 +64,6 @@ typedef unsigned int uint32_t;
|
||||||
typedef signed long long int64_t;
|
typedef signed long long int64_t;
|
||||||
typedef unsigned long long uint64_t;
|
typedef unsigned long long uint64_t;
|
||||||
|
|
||||||
typedef signed char int_fast8_t;
|
|
||||||
typedef int int_fast16_t;
|
|
||||||
typedef int int_fast32_t;
|
|
||||||
typedef long long int_fast64_t;
|
|
||||||
typedef unsigned char uint_fast8_t;
|
|
||||||
typedef unsigned int uint_fast16_t;
|
|
||||||
typedef unsigned int uint_fast32_t;
|
|
||||||
typedef unsigned long long uint_fast64_t;
|
|
||||||
|
|
||||||
#if !defined(_W64)
|
|
||||||
#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
|
||||||
#define _W64 __w64
|
|
||||||
#else
|
|
||||||
#define _W64
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _INTPTR_T_DEFINED
|
#ifndef _INTPTR_T_DEFINED
|
||||||
#define _INTPTR_T_DEFINED
|
#define _INTPTR_T_DEFINED
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
@ -111,36 +94,7 @@ typedef _W64 unsigned int uintptr_t;
|
||||||
#define UINT16_MAX 0xffffui16
|
#define UINT16_MAX 0xffffui16
|
||||||
#define UINT32_MAX 0xffffffffui32
|
#define UINT32_MAX 0xffffffffui32
|
||||||
#define UINT64_MAX 0xffffffffffffffffui64
|
#define UINT64_MAX 0xffffffffffffffffui64
|
||||||
|
|
||||||
#define INT_FAST8_MIN INT8_MIN
|
|
||||||
#define INT_FAST16_MIN INT32_MIN
|
|
||||||
#define INT_FAST32_MIN INT32_MIN
|
|
||||||
#define INT_FAST64_MIN INT64_MIN
|
|
||||||
#define INT_FAST8_MAX INT8_MAX
|
|
||||||
#define INT_FAST16_MAX INT32_MAX
|
|
||||||
#define INT_FAST32_MAX INT32_MAX
|
|
||||||
#define INT_FAST64_MAX INT64_MAX
|
|
||||||
#define UINT_FAST8_MAX UINT8_MAX
|
|
||||||
#define UINT_FAST16_MAX UINT32_MAX
|
|
||||||
#define UINT_FAST32_MAX UINT32_MAX
|
|
||||||
#define UINT_FAST64_MAX UINT64_MAX
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
#define INTPTR_MIN INT64_MIN
|
|
||||||
#define INTPTR_MAX INT64_MAX
|
|
||||||
#define UINTPTR_MAX UINT64_MAX
|
|
||||||
#else /* _WIN64 */
|
|
||||||
#define INTPTR_MIN INT32_MIN
|
|
||||||
#define INTPTR_MAX INT32_MAX
|
|
||||||
#define UINTPTR_MAX UINT32_MAX
|
|
||||||
#endif /* _WIN64 */
|
|
||||||
|
|
||||||
#else // this system has stdint.h
|
#else // this system has stdint.h
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER == MSC_VER_VS2010)
|
|
||||||
#define _INTPTR 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE)
|
#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE)
|
||||||
|
|
||||||
|
@ -200,6 +154,7 @@ typedef _W64 unsigned int uintptr_t;
|
||||||
|
|
||||||
// sys/time.h compatibility
|
// sys/time.h compatibility
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
#include <sys/types.h>
|
||||||
#include <sys/timeb.h>
|
#include <sys/timeb.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* Unicorn Engine */
|
||||||
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015-2017 */
|
||||||
|
/* This file is released under LGPL2.
|
||||||
|
See COPYING.LGPL2 in root directory for more details
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UNICORN_PPC_H
|
||||||
|
#define UNICORN_PPC_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable:4201)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//> PPC registers
|
||||||
|
typedef enum uc_ppc_reg {
|
||||||
|
UC_PPC_REG_INVALID = 0,
|
||||||
|
//> General purpose registers
|
||||||
|
UC_PPC_REG_PC,
|
||||||
|
|
||||||
|
UC_PPC_REG_0,
|
||||||
|
UC_PPC_REG_1,
|
||||||
|
UC_PPC_REG_2,
|
||||||
|
UC_PPC_REG_3,
|
||||||
|
UC_PPC_REG_4,
|
||||||
|
UC_PPC_REG_5,
|
||||||
|
UC_PPC_REG_6,
|
||||||
|
UC_PPC_REG_7,
|
||||||
|
UC_PPC_REG_8,
|
||||||
|
UC_PPC_REG_9,
|
||||||
|
UC_PPC_REG_10,
|
||||||
|
UC_PPC_REG_11,
|
||||||
|
UC_PPC_REG_12,
|
||||||
|
UC_PPC_REG_13,
|
||||||
|
UC_PPC_REG_14,
|
||||||
|
UC_PPC_REG_15,
|
||||||
|
UC_PPC_REG_16,
|
||||||
|
UC_PPC_REG_17,
|
||||||
|
UC_PPC_REG_18,
|
||||||
|
UC_PPC_REG_19,
|
||||||
|
UC_PPC_REG_20,
|
||||||
|
UC_PPC_REG_21,
|
||||||
|
UC_PPC_REG_22,
|
||||||
|
UC_PPC_REG_23,
|
||||||
|
UC_PPC_REG_24,
|
||||||
|
UC_PPC_REG_25,
|
||||||
|
UC_PPC_REG_26,
|
||||||
|
UC_PPC_REG_27,
|
||||||
|
UC_PPC_REG_28,
|
||||||
|
UC_PPC_REG_29,
|
||||||
|
UC_PPC_REG_30,
|
||||||
|
UC_PPC_REG_31,
|
||||||
|
} uc_ppc_reg;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,167 @@
|
||||||
|
/* Unicorn Engine */
|
||||||
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015-2020 */
|
||||||
|
/* This file is released under LGPL2.
|
||||||
|
See COPYING.LGPL2 in root directory for more details
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UNICORN_RISCV_H
|
||||||
|
#define UNICORN_RISCV_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable:4201)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//> RISCV registers
|
||||||
|
typedef enum uc_riscv_reg {
|
||||||
|
UC_RISCV_REG_INVALID = 0,
|
||||||
|
//> General purpose registers
|
||||||
|
UC_RISCV_REG_X0,
|
||||||
|
UC_RISCV_REG_X1,
|
||||||
|
UC_RISCV_REG_X2,
|
||||||
|
UC_RISCV_REG_X3,
|
||||||
|
UC_RISCV_REG_X4,
|
||||||
|
UC_RISCV_REG_X5,
|
||||||
|
UC_RISCV_REG_X6,
|
||||||
|
UC_RISCV_REG_X7,
|
||||||
|
UC_RISCV_REG_X8,
|
||||||
|
UC_RISCV_REG_X9,
|
||||||
|
UC_RISCV_REG_X10,
|
||||||
|
UC_RISCV_REG_X11,
|
||||||
|
UC_RISCV_REG_X12,
|
||||||
|
UC_RISCV_REG_X13,
|
||||||
|
UC_RISCV_REG_X14,
|
||||||
|
UC_RISCV_REG_X15,
|
||||||
|
UC_RISCV_REG_X16,
|
||||||
|
UC_RISCV_REG_X17,
|
||||||
|
UC_RISCV_REG_X18,
|
||||||
|
UC_RISCV_REG_X19,
|
||||||
|
UC_RISCV_REG_X20,
|
||||||
|
UC_RISCV_REG_X21,
|
||||||
|
UC_RISCV_REG_X22,
|
||||||
|
UC_RISCV_REG_X23,
|
||||||
|
UC_RISCV_REG_X24,
|
||||||
|
UC_RISCV_REG_X25,
|
||||||
|
UC_RISCV_REG_X26,
|
||||||
|
UC_RISCV_REG_X27,
|
||||||
|
UC_RISCV_REG_X28,
|
||||||
|
UC_RISCV_REG_X29,
|
||||||
|
UC_RISCV_REG_X30,
|
||||||
|
UC_RISCV_REG_X31,
|
||||||
|
|
||||||
|
//> Floating-point registers
|
||||||
|
UC_RISCV_REG_F0, // "ft0"
|
||||||
|
UC_RISCV_REG_F1, // "ft1"
|
||||||
|
UC_RISCV_REG_F2, // "ft2"
|
||||||
|
UC_RISCV_REG_F3, // "ft3"
|
||||||
|
UC_RISCV_REG_F4, // "ft4"
|
||||||
|
UC_RISCV_REG_F5, // "ft5"
|
||||||
|
UC_RISCV_REG_F6, // "ft6"
|
||||||
|
UC_RISCV_REG_F7, // "ft7"
|
||||||
|
UC_RISCV_REG_F8, // "fs0"
|
||||||
|
UC_RISCV_REG_F9, // "fs1"
|
||||||
|
UC_RISCV_REG_F10, // "fa0"
|
||||||
|
UC_RISCV_REG_F11, // "fa1"
|
||||||
|
UC_RISCV_REG_F12, // "fa2"
|
||||||
|
UC_RISCV_REG_F13, // "fa3"
|
||||||
|
UC_RISCV_REG_F14, // "fa4"
|
||||||
|
UC_RISCV_REG_F15, // "fa5"
|
||||||
|
UC_RISCV_REG_F16, // "fa6"
|
||||||
|
UC_RISCV_REG_F17, // "fa7"
|
||||||
|
UC_RISCV_REG_F18, // "fs2"
|
||||||
|
UC_RISCV_REG_F19, // "fs3"
|
||||||
|
UC_RISCV_REG_F20, // "fs4"
|
||||||
|
UC_RISCV_REG_F21, // "fs5"
|
||||||
|
UC_RISCV_REG_F22, // "fs6"
|
||||||
|
UC_RISCV_REG_F23, // "fs7"
|
||||||
|
UC_RISCV_REG_F24, // "fs8"
|
||||||
|
UC_RISCV_REG_F25, // "fs9"
|
||||||
|
UC_RISCV_REG_F26, // "fs10"
|
||||||
|
UC_RISCV_REG_F27, // "fs11"
|
||||||
|
UC_RISCV_REG_F28, // "ft8"
|
||||||
|
UC_RISCV_REG_F29, // "ft9"
|
||||||
|
UC_RISCV_REG_F30, // "ft10"
|
||||||
|
UC_RISCV_REG_F31, // "ft11"
|
||||||
|
|
||||||
|
UC_RISCV_REG_PC, // PC register
|
||||||
|
|
||||||
|
UC_RISCV_REG_ENDING, // <-- mark the end of the list or registers
|
||||||
|
|
||||||
|
//> Alias registers
|
||||||
|
UC_RISCV_REG_ZERO = UC_RISCV_REG_X0, // "zero"
|
||||||
|
UC_RISCV_REG_RA = UC_RISCV_REG_X1, // "ra"
|
||||||
|
UC_RISCV_REG_SP = UC_RISCV_REG_X2, // "sp"
|
||||||
|
UC_RISCV_REG_GP = UC_RISCV_REG_X3, // "gp"
|
||||||
|
UC_RISCV_REG_TP = UC_RISCV_REG_X4, // "tp"
|
||||||
|
UC_RISCV_REG_T0 = UC_RISCV_REG_X5, // "t0"
|
||||||
|
UC_RISCV_REG_T1 = UC_RISCV_REG_X6, // "t1"
|
||||||
|
UC_RISCV_REG_T2 = UC_RISCV_REG_X7, // "t2"
|
||||||
|
UC_RISCV_REG_S0 = UC_RISCV_REG_X8, // "s0"
|
||||||
|
UC_RISCV_REG_FP = UC_RISCV_REG_X8, // "fp"
|
||||||
|
UC_RISCV_REG_S1 = UC_RISCV_REG_X9, // "s1"
|
||||||
|
UC_RISCV_REG_A0 = UC_RISCV_REG_X10, // "a0"
|
||||||
|
UC_RISCV_REG_A1 = UC_RISCV_REG_X11, // "a1"
|
||||||
|
UC_RISCV_REG_A2 = UC_RISCV_REG_X12, // "a2"
|
||||||
|
UC_RISCV_REG_A3 = UC_RISCV_REG_X13, // "a3"
|
||||||
|
UC_RISCV_REG_A4 = UC_RISCV_REG_X14, // "a4"
|
||||||
|
UC_RISCV_REG_A5 = UC_RISCV_REG_X15, // "a5"
|
||||||
|
UC_RISCV_REG_A6 = UC_RISCV_REG_X16, // "a6"
|
||||||
|
UC_RISCV_REG_A7 = UC_RISCV_REG_X17, // "a7"
|
||||||
|
UC_RISCV_REG_S2 = UC_RISCV_REG_X18, // "s2"
|
||||||
|
UC_RISCV_REG_S3 = UC_RISCV_REG_X19, // "s3"
|
||||||
|
UC_RISCV_REG_S4 = UC_RISCV_REG_X20, // "s4"
|
||||||
|
UC_RISCV_REG_S5 = UC_RISCV_REG_X21, // "s5"
|
||||||
|
UC_RISCV_REG_S6 = UC_RISCV_REG_X22, // "s6"
|
||||||
|
UC_RISCV_REG_S7 = UC_RISCV_REG_X23, // "s7"
|
||||||
|
UC_RISCV_REG_S8 = UC_RISCV_REG_X24, // "s8"
|
||||||
|
UC_RISCV_REG_S9 = UC_RISCV_REG_X25, // "s9"
|
||||||
|
UC_RISCV_REG_S10 = UC_RISCV_REG_X26, // "s10"
|
||||||
|
UC_RISCV_REG_S11 = UC_RISCV_REG_X27, // "s11"
|
||||||
|
UC_RISCV_REG_T3 = UC_RISCV_REG_X28, // "t3"
|
||||||
|
UC_RISCV_REG_T4 = UC_RISCV_REG_X29, // "t4"
|
||||||
|
UC_RISCV_REG_T5 = UC_RISCV_REG_X30, // "t5"
|
||||||
|
UC_RISCV_REG_T6 = UC_RISCV_REG_X31, // "t6"
|
||||||
|
|
||||||
|
UC_RISCV_REG_FT0 = UC_RISCV_REG_F0, // "ft0"
|
||||||
|
UC_RISCV_REG_FT1 = UC_RISCV_REG_F1, // "ft1"
|
||||||
|
UC_RISCV_REG_FT2 = UC_RISCV_REG_F2, // "ft2"
|
||||||
|
UC_RISCV_REG_FT3 = UC_RISCV_REG_F3, // "ft3"
|
||||||
|
UC_RISCV_REG_FT4 = UC_RISCV_REG_F4, // "ft4"
|
||||||
|
UC_RISCV_REG_FT5 = UC_RISCV_REG_F5, // "ft5"
|
||||||
|
UC_RISCV_REG_FT6 = UC_RISCV_REG_F6, // "ft6"
|
||||||
|
UC_RISCV_REG_FT7 = UC_RISCV_REG_F7, // "ft7"
|
||||||
|
UC_RISCV_REG_FS0 = UC_RISCV_REG_F8, // "fs0"
|
||||||
|
UC_RISCV_REG_FS1 = UC_RISCV_REG_F9, // "fs1"
|
||||||
|
|
||||||
|
UC_RISCV_REG_FA0 = UC_RISCV_REG_F10, // "fa0"
|
||||||
|
UC_RISCV_REG_FA1 = UC_RISCV_REG_F11, // "fa1"
|
||||||
|
UC_RISCV_REG_FA2 = UC_RISCV_REG_F12, // "fa2"
|
||||||
|
UC_RISCV_REG_FA3 = UC_RISCV_REG_F13, // "fa3"
|
||||||
|
UC_RISCV_REG_FA4 = UC_RISCV_REG_F14, // "fa4"
|
||||||
|
UC_RISCV_REG_FA5 = UC_RISCV_REG_F15, // "fa5"
|
||||||
|
UC_RISCV_REG_FA6 = UC_RISCV_REG_F16, // "fa6"
|
||||||
|
UC_RISCV_REG_FA7 = UC_RISCV_REG_F17, // "fa7"
|
||||||
|
UC_RISCV_REG_FS2 = UC_RISCV_REG_F18, // "fs2"
|
||||||
|
UC_RISCV_REG_FS3 = UC_RISCV_REG_F19, // "fs3"
|
||||||
|
UC_RISCV_REG_FS4 = UC_RISCV_REG_F20, // "fs4"
|
||||||
|
UC_RISCV_REG_FS5 = UC_RISCV_REG_F21, // "fs5"
|
||||||
|
UC_RISCV_REG_FS6 = UC_RISCV_REG_F22, // "fs6"
|
||||||
|
UC_RISCV_REG_FS7 = UC_RISCV_REG_F23, // "fs7"
|
||||||
|
UC_RISCV_REG_FS8 = UC_RISCV_REG_F24, // "fs8"
|
||||||
|
UC_RISCV_REG_FS9 = UC_RISCV_REG_F25, // "fs9"
|
||||||
|
UC_RISCV_REG_FS10 = UC_RISCV_REG_F26, // "fs10"
|
||||||
|
UC_RISCV_REG_FS11 = UC_RISCV_REG_F27, // "fs11"
|
||||||
|
UC_RISCV_REG_FT8 = UC_RISCV_REG_F28, // "ft8"
|
||||||
|
UC_RISCV_REG_FT9 = UC_RISCV_REG_F29, // "ft9"
|
||||||
|
UC_RISCV_REG_FT10 = UC_RISCV_REG_F30, // "ft10"
|
||||||
|
UC_RISCV_REG_FT11 = UC_RISCV_REG_F31, // "ft11"
|
||||||
|
} uc_riscv_reg;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue