import Unicorn2
This commit is contained in:
parent
772558119a
commit
aaaea14214
|
@ -12,8 +12,6 @@
|
|||
*.jar
|
||||
*~
|
||||
|
||||
qemu/config-all-devices.mak
|
||||
|
||||
qemu/aarch64-softmmu/
|
||||
qemu/aarch64eb-softmmu/
|
||||
qemu/arm-softmmu/
|
||||
|
@ -29,6 +27,8 @@ qemu/i386-softmmu/
|
|||
qemu/x86_64-softmmu/
|
||||
qemu/ppc-softmmu/
|
||||
qemu/ppc64-softmmu/
|
||||
qemu/riscv32-softmmu/
|
||||
qemu/riscv64-softmmu/
|
||||
|
||||
tags
|
||||
qemu/config-host.ld
|
||||
|
@ -67,8 +67,6 @@ bindings/python/unicorn.egg-info/
|
|||
bindings/python/unicorn/lib/
|
||||
bindings/python/unicorn/include/
|
||||
bindings/python/MANIFEST
|
||||
bindings/rust/target/
|
||||
bindings/rust/Cargo.lock
|
||||
config.log
|
||||
|
||||
|
||||
|
|
147
.travis.yml
147
.travis.yml
|
@ -4,19 +4,10 @@ env:
|
|||
script:
|
||||
- |
|
||||
if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
|
||||
if [[ "$TRAVIS_COMPILER" == "clang" ]]; then
|
||||
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'"
|
||||
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
|
||||
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'"
|
||||
else
|
||||
make header && make && make -C bindings/go && make -C bindings/go test && make test
|
||||
fi
|
||||
|
@ -25,52 +16,28 @@ compiler:
|
|||
- gcc
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
- windows
|
||||
arch:
|
||||
- amd64
|
||||
- arm64
|
||||
matrix:
|
||||
fast_finish: true
|
||||
exclude:
|
||||
- os: windows
|
||||
arch: arm64
|
||||
include:
|
||||
|
||||
- name: "Compiler: clang C"
|
||||
os: osx
|
||||
osx_image: xcode10.1
|
||||
python: 3.7
|
||||
- name: "Linux arm64 clang C"
|
||||
arch: arm64
|
||||
os: linux
|
||||
compiler: clang
|
||||
before_cache:
|
||||
- brew cleanup
|
||||
- find /usr/local/Homebrew \! -regex ".+\.git.+" -delete;
|
||||
cache:
|
||||
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
|
||||
language: c
|
||||
env:
|
||||
- PATH=$PATH:/usr/local/opt/binutils/bin
|
||||
script: make header && make && make -C tests/unit test && make -C tests/regress test
|
||||
|
||||
- name: "Compiler: gcc C"
|
||||
os: osx
|
||||
osx_image: xcode10.1
|
||||
python: 3.7
|
||||
- name: "Linux arm64 gcc C"
|
||||
arch: arm64
|
||||
os: linux
|
||||
compiler: gcc
|
||||
before_cache:
|
||||
- brew cleanup
|
||||
- find /usr/local/Homebrew \! -regex ".+\.git.+" -delete;
|
||||
cache:
|
||||
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
|
||||
language: c
|
||||
env:
|
||||
- PATH=$PATH:/usr/local/opt/binutils/bin
|
||||
script: make header && make && make -C tests/unit test && make -C tests/regress test
|
||||
|
||||
- name: "Linux clang ASAN"
|
||||
os: linux
|
||||
|
@ -81,9 +48,7 @@ matrix:
|
|||
- 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"
|
||||
- LDFLAGS="-fsanitize=address"
|
||||
script:
|
||||
- make header && make
|
||||
- make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||
script: make header && make && make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||
|
||||
- name: "Linux clang MSAN"
|
||||
os: linux
|
||||
|
@ -94,9 +59,7 @@ matrix:
|
|||
- 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"
|
||||
- LDFLAGS="-fsanitize=memory"
|
||||
script:
|
||||
- make header && make
|
||||
- make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||
script: make header && make && make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||
|
||||
- name: "Linux clang USAN"
|
||||
os: linux
|
||||
|
@ -107,9 +70,7 @@ matrix:
|
|||
- 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"
|
||||
- LDFLAGS="-fsanitize=undefined"
|
||||
script:
|
||||
- make header && make
|
||||
- make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||
script: make header && make && make -C tests/fuzz && sh tests/fuzz/dlcorpus.sh
|
||||
|
||||
- name: "Linux 32bit"
|
||||
os: linux
|
||||
|
@ -164,42 +125,6 @@ matrix:
|
|||
- cp libunicorn.* ../
|
||||
- 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"
|
||||
os: osx
|
||||
osx_image: xcode10.1
|
||||
|
@ -289,14 +214,12 @@ matrix:
|
|||
- export LDFLAGS="-m32"
|
||||
- export LDFLAGS_STATIC="-m32"
|
||||
- export UNICORN_QEMU_FLAGS="--cpu=i386"
|
||||
# before_cache:
|
||||
# - $msys2 pacman --sync --clean --noconfirm
|
||||
# cache:
|
||||
# timeout:
|
||||
# 1000
|
||||
# directories:
|
||||
# - $HOME/AppData/Local/Temp/chocolatey
|
||||
# - /C/tools/msys64
|
||||
before_cache:
|
||||
- $msys2 pacman --sync --clean --noconfirm
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/AppData/Local/Temp/chocolatey
|
||||
- /C/tools/msys64
|
||||
script:
|
||||
- $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 AR=gcc-ar
|
||||
- export RANLIB=gcc-ranlib
|
||||
# before_cache:
|
||||
# - $msys2 pacman --sync --clean --noconfirm
|
||||
# cache:
|
||||
# timeout:
|
||||
# 1000
|
||||
# directories:
|
||||
# - $HOME/AppData/Local/Temp/chocolatey
|
||||
# - /C/tools/msys64
|
||||
before_cache:
|
||||
- $msys2 pacman --sync --clean --noconfirm
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/AppData/Local/Temp/chocolatey
|
||||
- /C/tools/msys64
|
||||
script:
|
||||
- $shell make header; $shell make; cp unicorn.dll /C/Windows/System32/; $shell make test
|
||||
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>
|
||||
Dang Hoang Vu <dang.hvu -at- gmail.com>
|
||||
Huitao Chen (chenhuitao)
|
||||
Ziqiao Kong (lazymio)
|
||||
KaiJernLau (xwings)
|
||||
|
||||
|
||||
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): Python3 support for building
|
||||
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.
|
||||
Sven Almgren (blindmatrix): bug fix
|
||||
|
|
71
ChangeLog
71
ChangeLog
|
@ -1,76 +1,5 @@
|
|||
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
|
||||
|
||||
|
|
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
|
||||
==============
|
||||
|
||||
[![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)
|
||||
[![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:
|
||||
|
||||
- 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
|
||||
- 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)
|
||||
|
|
|
@ -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.
|
||||
|
||||
The following bindings are contributed by community.
|
||||
|
@ -10,14 +10,13 @@ The following bindings are contributed by community.
|
|||
- Haskell binding: by Adrian Herrera.
|
||||
- VB6 binding: David Zimmer.
|
||||
- FreePascal/Delphi binding: Mohamed Osama.
|
||||
- Rust binding: Lukas Seidel.
|
||||
|
||||
More bindings created & maintained externally by community are available as follows.
|
||||
|
||||
- UnicornPascal: Delphi/Free Pascal binding (by Stievie).
|
||||
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
|
||||
|
||||
- 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)
|
||||
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')
|
||||
|
||||
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 = {
|
||||
'python': {
|
||||
|
@ -21,6 +21,8 @@ template = {
|
|||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '#',
|
||||
'comment_close': '',
|
||||
|
@ -37,6 +39,8 @@ template = {
|
|||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '#',
|
||||
'comment_close': '',
|
||||
|
@ -53,6 +57,8 @@ template = {
|
|||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
|
@ -69,6 +75,8 @@ template = {
|
|||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
'unicorn.h': 'Unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
|
@ -85,6 +93,8 @@ template = {
|
|||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
'unicorn.h': 'Common',
|
||||
'comment_open': ' //',
|
||||
'comment_close': '',
|
||||
|
@ -101,6 +111,8 @@ template = {
|
|||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
'unicorn.h': 'Unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
|
|
|
@ -6,13 +6,14 @@ open System
|
|||
|
||||
[<AutoOpen>]
|
||||
module Common =
|
||||
let UC_API_MAJOR = 1
|
||||
let UC_API_MAJOR = 2
|
||||
|
||||
let UC_API_MINOR = 0
|
||||
let UC_VERSION_MAJOR = 1
|
||||
let UC_VERSION_MAJOR = 2
|
||||
|
||||
let UC_VERSION_MINOR = 0
|
||||
let UC_VERSION_EXTRA = 3
|
||||
|
||||
let UC_VERSION_EXTRA = 0
|
||||
let UC_SECOND_SCALE = 1000000
|
||||
let UC_MILISECOND_SCALE = 1000
|
||||
let UC_ARCH_ARM = 1
|
||||
|
@ -22,7 +23,8 @@ module Common =
|
|||
let UC_ARCH_PPC = 5
|
||||
let UC_ARCH_SPARC = 6
|
||||
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_BIG_ENDIAN = 1073741824
|
||||
|
@ -34,7 +36,6 @@ module Common =
|
|||
let UC_MODE_ARM926 = 128
|
||||
let UC_MODE_ARM946 = 256
|
||||
let UC_MODE_ARM1176 = 512
|
||||
let UC_MODE_ARMBE8 = 1024
|
||||
let UC_MODE_MICRO = 16
|
||||
let UC_MODE_MIPS3 = 32
|
||||
let UC_MODE_MIPS32R6 = 64
|
||||
|
@ -49,6 +50,8 @@ module Common =
|
|||
let UC_MODE_SPARC32 = 4
|
||||
let UC_MODE_SPARC64 = 8
|
||||
let UC_MODE_V9 = 16
|
||||
let UC_MODE_RISCV32 = 4
|
||||
let UC_MODE_RISCV64 = 8
|
||||
|
||||
let UC_ERR_OK = 0
|
||||
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
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go]
|
||||
const (
|
||||
API_MAJOR = 1
|
||||
API_MAJOR = 2
|
||||
|
||||
API_MINOR = 0
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MAJOR = 2
|
||||
|
||||
VERSION_MINOR = 0
|
||||
VERSION_EXTRA = 3
|
||||
|
||||
VERSION_EXTRA = 0
|
||||
SECOND_SCALE = 1000000
|
||||
MILISECOND_SCALE = 1000
|
||||
ARCH_ARM = 1
|
||||
|
@ -17,7 +18,8 @@ const (
|
|||
ARCH_PPC = 5
|
||||
ARCH_SPARC = 6
|
||||
ARCH_M68K = 7
|
||||
ARCH_MAX = 8
|
||||
ARCH_RISCV = 8
|
||||
ARCH_MAX = 9
|
||||
|
||||
MODE_LITTLE_ENDIAN = 0
|
||||
MODE_BIG_ENDIAN = 1073741824
|
||||
|
@ -29,7 +31,6 @@ const (
|
|||
MODE_ARM926 = 128
|
||||
MODE_ARM946 = 256
|
||||
MODE_ARM1176 = 512
|
||||
MODE_ARMBE8 = 1024
|
||||
MODE_MICRO = 16
|
||||
MODE_MIPS3 = 32
|
||||
MODE_MIPS32R6 = 64
|
||||
|
@ -44,6 +45,8 @@ const (
|
|||
MODE_SPARC32 = 4
|
||||
MODE_SPARC64 = 8
|
||||
MODE_V9 = 16
|
||||
MODE_RISCV32 = 4
|
||||
MODE_RISCV64 = 8
|
||||
|
||||
ERR_OK = 0
|
||||
ERR_NOMEM = 1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
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`)
|
||||
|
||||
|
@ -46,7 +46,7 @@ all: lib jar samples
|
|||
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
|
||||
|
||||
unicorn_Unicorn.h: unicorn/Unicorn.java
|
||||
javac -h unicorn/ unicorn/*.java
|
||||
javah unicorn.Unicorn
|
||||
|
||||
unicorn_Unicorn.o: unicorn_Unicorn.c unicorn_Unicorn.h
|
||||
$(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;
|
||||
|
||||
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_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_EXTRA = 3;
|
||||
|
||||
public static final int UC_VERSION_EXTRA = 0;
|
||||
public static final int UC_SECOND_SCALE = 1000000;
|
||||
public static final int UC_MILISECOND_SCALE = 1000;
|
||||
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_SPARC = 6;
|
||||
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_BIG_ENDIAN = 1073741824;
|
||||
|
@ -31,7 +33,6 @@ public interface UnicornConst {
|
|||
public static final int UC_MODE_ARM926 = 128;
|
||||
public static final int UC_MODE_ARM946 = 256;
|
||||
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_MIPS3 = 32;
|
||||
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_SPARC64 = 8;
|
||||
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_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
|
||||
|
||||
const UC_API_MAJOR = 1;
|
||||
const UC_API_MAJOR = 2;
|
||||
|
||||
UC_API_MINOR = 0;
|
||||
UC_VERSION_MAJOR = 1;
|
||||
UC_VERSION_MAJOR = 2;
|
||||
|
||||
UC_VERSION_MINOR = 0;
|
||||
UC_VERSION_EXTRA = 3;
|
||||
|
||||
UC_VERSION_EXTRA = 0;
|
||||
UC_SECOND_SCALE = 1000000;
|
||||
UC_MILISECOND_SCALE = 1000;
|
||||
UC_ARCH_ARM = 1;
|
||||
|
@ -20,7 +21,8 @@ const UC_API_MAJOR = 1;
|
|||
UC_ARCH_PPC = 5;
|
||||
UC_ARCH_SPARC = 6;
|
||||
UC_ARCH_M68K = 7;
|
||||
UC_ARCH_MAX = 8;
|
||||
UC_ARCH_RISCV = 8;
|
||||
UC_ARCH_MAX = 9;
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0;
|
||||
UC_MODE_BIG_ENDIAN = 1073741824;
|
||||
|
@ -32,7 +34,6 @@ const UC_API_MAJOR = 1;
|
|||
UC_MODE_ARM926 = 128;
|
||||
UC_MODE_ARM946 = 256;
|
||||
UC_MODE_ARM1176 = 512;
|
||||
UC_MODE_ARMBE8 = 1024;
|
||||
UC_MODE_MICRO = 16;
|
||||
UC_MODE_MIPS3 = 32;
|
||||
UC_MODE_MIPS32R6 = 64;
|
||||
|
@ -47,6 +48,8 @@ const UC_API_MAJOR = 1;
|
|||
UC_MODE_SPARC32 = 4;
|
||||
UC_MODE_SPARC64 = 8;
|
||||
UC_MODE_V9 = 16;
|
||||
UC_MODE_RISCV32 = 4;
|
||||
UC_MODE_RISCV64 = 8;
|
||||
|
||||
UC_ERR_OK = 0;
|
||||
UC_ERR_NOMEM = 1;
|
||||
|
|
|
@ -108,7 +108,7 @@ type
|
|||
@user_data: user data passed to tracing APIs
|
||||
|
||||
@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.
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
# 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_CODE64_SYSCALL = b'\x0f\x05' # SYSCALL
|
||||
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
|
||||
ADDRESS = 0x1000000
|
||||
|
@ -386,7 +387,6 @@ def test_i386_loop():
|
|||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
# Test X86 32 bit with IN/OUT instruction
|
||||
def test_i386_inout():
|
||||
print("Emulate i386 code with IN/OUT instructions")
|
||||
|
@ -464,6 +464,9 @@ def test_i386_context_save():
|
|||
print(">>> Unpickling CPU 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")
|
||||
mu.context_restore(saved_context)
|
||||
print(">>> EAX = 0x%x" %(mu.reg_read(UC_X86_REG_EAX)))
|
||||
|
@ -628,6 +631,38 @@ def test_x86_16():
|
|||
except UcError as 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__':
|
||||
test_x86_16()
|
||||
|
@ -651,3 +686,5 @@ if __name__ == '__main__':
|
|||
test_x86_64()
|
||||
print("=" * 35)
|
||||
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.sdist import sdist
|
||||
from setuptools.command.bdist_egg import bdist_egg
|
||||
from setuptools.command.develop import develop
|
||||
|
||||
SYSTEM = sys.platform
|
||||
|
||||
|
@ -23,36 +22,18 @@ SYSTEM = sys.platform
|
|||
IS_64BITS = platform.architecture()[0] == '64bit'
|
||||
|
||||
# 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')
|
||||
HEADERS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'include')
|
||||
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 = {}
|
||||
with open(os.path.join(BUILD_DIR, 'pkgconfig.mk')) as fp:
|
||||
lines = fp.readlines()
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
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")
|
||||
VERSION_DATA['PKG_MAJOR'] = "2"
|
||||
VERSION_DATA['PKG_MINOR'] = "0"
|
||||
VERSION_DATA['PKG_EXTRA'] = "0"
|
||||
# VERSION_DATA['PKG_TAG'] = "0"
|
||||
|
||||
if 'PKG_TAG' in 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"
|
||||
MAC_LIBRARY_FILE = "libunicorn*.dylib"
|
||||
STATIC_LIBRARY_FILE = None
|
||||
elif SYSTEM == 'win32':
|
||||
elif SYSTEM in ('win32', 'cygwin'):
|
||||
LIBRARY_FILE = "unicorn.dll"
|
||||
STATIC_LIBRARY_FILE = "unicorn.lib"
|
||||
elif SYSTEM == 'cygwin':
|
||||
LIBRARY_FILE = "cygunicorn.dll"
|
||||
STATIC_LIBRARY_FILE = None
|
||||
else:
|
||||
LIBRARY_FILE = "libunicorn.so"
|
||||
STATIC_LIBRARY_FILE = None
|
||||
|
@ -84,7 +62,6 @@ def copy_sources():
|
|||
"""
|
||||
src = []
|
||||
|
||||
os.system('make -C %s clean' % os.path.join(ROOT_DIR, '../..'))
|
||||
shutil.rmtree(SRC_DIR, ignore_errors=True)
|
||||
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, "../../*.TXT")))
|
||||
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, "../../pkgconfig.mk")))
|
||||
|
||||
for filename in src:
|
||||
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
|
||||
|
@ -130,7 +106,7 @@ def build_libraries():
|
|||
os.mkdir(LIBS_DIR)
|
||||
|
||||
# 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
|
||||
# if so, use it instead of building
|
||||
|
@ -141,35 +117,37 @@ def build_libraries():
|
|||
return
|
||||
|
||||
# otherwise, build!!
|
||||
os.chdir(BUILD_DIR)
|
||||
os.chdir(UC_DIR)
|
||||
|
||||
try:
|
||||
subprocess.check_call(['msbuild', '-ver'])
|
||||
subprocess.check_call(['msbuild', '/help'])
|
||||
except:
|
||||
has_msbuild = False
|
||||
else:
|
||||
has_msbuild = True
|
||||
|
||||
if has_msbuild and SYSTEM == 'win32':
|
||||
if platform.architecture()[0] == '32bit':
|
||||
plat = 'Win32'
|
||||
elif 'win32' in sys.argv:
|
||||
plat = 'Win32'
|
||||
else:
|
||||
plat = 'x64'
|
||||
|
||||
plat = 'Win32' if platform.architecture()[0] == '32bit' else 'x64'
|
||||
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, STATIC_LIBRARY_FILE), LIBS_DIR)
|
||||
else:
|
||||
# platform description refs at https://docs.python.org/2/library/sys.html#sys.platform
|
||||
new_env = dict(os.environ)
|
||||
new_env['UNICORN_BUILD_CORE_ONLY'] = 'yes'
|
||||
cmd = ['sh', './make.sh']
|
||||
if SYSTEM == "win32":
|
||||
if not os.path.exists(BUILD_DIR):
|
||||
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:
|
||||
cmd.append('cross-win64')
|
||||
else:
|
||||
|
@ -196,6 +174,7 @@ def build_libraries():
|
|||
sys.exit(1)
|
||||
os.chdir(cwd)
|
||||
|
||||
|
||||
class custom_sdist(sdist):
|
||||
def run(self):
|
||||
clean_bins()
|
||||
|
@ -211,12 +190,6 @@ class custom_build(build):
|
|||
build_libraries()
|
||||
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):
|
||||
def run(self):
|
||||
self.run_command('build')
|
||||
|
@ -225,6 +198,10 @@ class custom_bdist_egg(bdist_egg):
|
|||
def dummy_src():
|
||||
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:
|
||||
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/
|
||||
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 = '''
|
||||
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:
|
||||
|
||||
- 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
|
||||
- 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)
|
||||
|
@ -261,7 +252,7 @@ Unicorn offers some unparalleled features:
|
|||
- Thread-safety by design
|
||||
- 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(
|
||||
|
@ -273,18 +264,18 @@ setup(
|
|||
author_email='aquynh@gmail.com',
|
||||
description='Unicorn CPU emulator engine',
|
||||
long_description=long_desc,
|
||||
long_description_content_type="text/markdown",
|
||||
url='https://www.unicorn-engine.org',
|
||||
#long_description_content_type="text/markdown",
|
||||
url='http://www.unicorn-engine.org',
|
||||
classifiers=[
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 3',
|
||||
],
|
||||
requires=['ctypes'],
|
||||
cmdclass={'build': custom_build, 'develop': custom_develop, 'sdist': custom_sdist, 'bdist_egg': custom_bdist_egg},
|
||||
zip_safe=False,
|
||||
cmdclass=cmdclass,
|
||||
zip_safe=True,
|
||||
include_package_data=True,
|
||||
is_pure=False,
|
||||
is_pure=True,
|
||||
package_data={
|
||||
'unicorn': ['lib/*', 'include/unicorn/*']
|
||||
}
|
||||
|
|
|
@ -120,7 +120,28 @@ UC_ARM_REG_IPSR = 114
|
|||
UC_ARM_REG_MSP = 115
|
||||
UC_ARM_REG_PSP = 116
|
||||
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
|
||||
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.util
|
||||
import distutils.sysconfig
|
||||
from functools import wraps
|
||||
import pkg_resources
|
||||
import inspect
|
||||
import os.path
|
||||
import sys
|
||||
import weakref
|
||||
import functools
|
||||
|
||||
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
|
||||
|
||||
ucerr = ctypes.c_int
|
||||
uc_mode = ctypes.c_int
|
||||
uc_arch = ctypes.c_int
|
||||
uc_engine = ctypes.c_void_p
|
||||
uc_context = ctypes.c_void_p
|
||||
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_stop", ucerr, uc_engine)
|
||||
_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_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)
|
||||
|
@ -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_restore", ucerr, uc_engine, uc_context)
|
||||
_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_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes.POINTER(_uc_mem_region)), ctypes.POINTER(ctypes.c_uint32))
|
||||
|
||||
# uc_hook_add is special due to variable number of arguments
|
||||
_uc.uc_hook_add = _uc.uc_hook_add
|
||||
_uc.uc_hook_add.restype = ucerr
|
||||
# https://bugs.python.org/issue42880
|
||||
_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_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)
|
||||
|
@ -168,7 +171,12 @@ UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(
|
|||
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_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
|
||||
class UcError(Exception):
|
||||
|
@ -199,27 +207,103 @@ def version_bind():
|
|||
def 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):
|
||||
@wraps(func)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
"""Catches exceptions raised in hook functions.
|
||||
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()
|
||||
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
|
||||
emulation is issued.
|
||||
"""
|
||||
try:
|
||||
return func(self, *args, **kwargs)
|
||||
except Exception as e:
|
||||
# If multiple hooks raise exceptions, just use the first one
|
||||
if self._hook_exception is None:
|
||||
self._hook_exception = e
|
||||
# read to 64bit number to be safe
|
||||
reg = ctypes.c_uint64(0)
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.value
|
||||
|
||||
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):
|
||||
"""Memory-Management Register for instructions IDTR, GDTR, LDTR, TR."""
|
||||
|
@ -306,6 +390,8 @@ class Uc(object):
|
|||
def __init__(self, arch, mode):
|
||||
# verify version compatibility with the core before doing anything
|
||||
(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:
|
||||
self._uch = None
|
||||
# our binding version is different from the core's API version
|
||||
|
@ -319,10 +405,9 @@ class Uc(object):
|
|||
raise UcError(status)
|
||||
# internal mapping table to save callback & userdata
|
||||
self._callbacks = {}
|
||||
self._ctype_cbs = {}
|
||||
self._ctype_cbs = []
|
||||
self._callback_count = 0
|
||||
self._cleanup.register(self)
|
||||
self._hook_exception = None # The exception raised in a hook
|
||||
|
||||
@staticmethod
|
||||
def release_handle(uch):
|
||||
|
@ -340,9 +425,6 @@ class Uc(object):
|
|||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
if self._hook_exception is not None:
|
||||
raise self._hook_exception
|
||||
|
||||
# stop emulation
|
||||
def emu_stop(self):
|
||||
status = _uc.uc_emu_stop(self._uch)
|
||||
|
@ -351,100 +433,11 @@ class Uc(object):
|
|||
|
||||
# return the value of a register
|
||||
def reg_read(self, reg_id, opt=None):
|
||||
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]:
|
||||
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
|
||||
return reg_read(functools.partial(_uc.uc_reg_read, self._uch), self._arch, reg_id, opt)
|
||||
|
||||
# write to a register
|
||||
def reg_write(self, reg_id, value):
|
||||
reg = None
|
||||
|
||||
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)
|
||||
return reg_write(functools.partial(_uc.uc_reg_write, self._uch), self._arch, reg_id, value)
|
||||
|
||||
# read from MSR - X86 only
|
||||
def msr_read(self, msr_id):
|
||||
|
@ -468,6 +461,33 @@ class Uc(object):
|
|||
if status != uc.UC_ERR_OK:
|
||||
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
|
||||
def mem_map(self, address, size, perms=uc.UC_PROT_ALL):
|
||||
status = _uc.uc_mem_map(self._uch, address, size, perms)
|
||||
|
@ -500,49 +520,41 @@ class Uc(object):
|
|||
raise UcError(status)
|
||||
return result.value
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hookcode_cb(self, handle, address, size, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, address, size, data)
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_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):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, access, address, size, value, data)
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hook_intr_cb(self, handle, intno, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, intno, data)
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hook_insn_invalid_cb(self, handle, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
return cb(self, data)
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hook_insn_in_cb(self, handle, port, size, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
return cb(self, port, size, data)
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hook_insn_out_cb(self, handle, port, size, value, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, port, size, value, data)
|
||||
|
||||
@_catch_hook_exception
|
||||
def _hook_insn_syscall_cb(self, handle, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
|
@ -615,7 +627,7 @@ class Uc(object):
|
|||
)
|
||||
|
||||
# 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:
|
||||
raise UcError(status)
|
||||
|
@ -631,7 +643,7 @@ class Uc(object):
|
|||
h = 0
|
||||
|
||||
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)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
@ -664,14 +676,16 @@ class Uc(object):
|
|||
|
||||
|
||||
class UcContext:
|
||||
def __init__(self, h):
|
||||
def __init__(self, h, arch, mode):
|
||||
self._context = uc_context()
|
||||
self._size = _uc.uc_context_size(h)
|
||||
self._to_free = True
|
||||
status = _uc.uc_context_alloc(h, ctypes.byref(self._context))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
self._arch = arch
|
||||
self._mode = mode
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
return self._context
|
||||
|
@ -680,16 +694,34 @@ class UcContext:
|
|||
def size(self):
|
||||
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
|
||||
def __getstate__(self):
|
||||
return (bytes(self), self.size)
|
||||
|
||||
return (bytes(self), self.size, self.arch, self.mode)
|
||||
|
||||
def __setstate__(self, state):
|
||||
self._size = state[1]
|
||||
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.
|
||||
self._to_free = False
|
||||
|
||||
self._arch = state[2]
|
||||
self._mode = state[3]
|
||||
|
||||
def __bytes__(self):
|
||||
return ctypes.string_at(self.context, self.size)
|
||||
|
||||
|
@ -708,6 +740,8 @@ def debug():
|
|||
"sparc": uc.UC_ARCH_SPARC,
|
||||
"m68k": uc.UC_ARCH_M68K,
|
||||
"x86": uc.UC_ARCH_X86,
|
||||
"riscv": uc.UC_ARCH_RISCV,
|
||||
"ppc": uc.UC_ARCH_PPC,
|
||||
}
|
||||
|
||||
all_archs = ""
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
# 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_VERSION_MAJOR = 1
|
||||
UC_VERSION_MAJOR = 2
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_EXTRA = 3
|
||||
|
||||
UC_VERSION_EXTRA = 0
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
|
@ -15,7 +16,8 @@ UC_ARCH_X86 = 4
|
|||
UC_ARCH_PPC = 5
|
||||
UC_ARCH_SPARC = 6
|
||||
UC_ARCH_M68K = 7
|
||||
UC_ARCH_MAX = 8
|
||||
UC_ARCH_RISCV = 8
|
||||
UC_ARCH_MAX = 9
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0
|
||||
UC_MODE_BIG_ENDIAN = 1073741824
|
||||
|
@ -27,7 +29,6 @@ UC_MODE_V8 = 64
|
|||
UC_MODE_ARM926 = 128
|
||||
UC_MODE_ARM946 = 256
|
||||
UC_MODE_ARM1176 = 512
|
||||
UC_MODE_ARMBE8 = 1024
|
||||
UC_MODE_MICRO = 16
|
||||
UC_MODE_MIPS3 = 32
|
||||
UC_MODE_MIPS32R6 = 64
|
||||
|
@ -42,6 +43,8 @@ UC_MODE_QPX = 16
|
|||
UC_MODE_SPARC32 = 4
|
||||
UC_MODE_SPARC64 = 8
|
||||
UC_MODE_V9 = 16
|
||||
UC_MODE_RISCV32 = 4
|
||||
UC_MODE_RISCV64 = 8
|
||||
|
||||
UC_ERR_OK = 0
|
||||
UC_ERR_NOMEM = 1
|
||||
|
|
|
@ -254,7 +254,9 @@ UC_X86_REG_MSR = 248
|
|||
UC_X86_REG_MXCSR = 249
|
||||
UC_X86_REG_FS_BASE = 250
|
||||
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
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
||||
module UnicornEngine
|
||||
UC_API_MAJOR = 1
|
||||
UC_API_MAJOR = 2
|
||||
|
||||
UC_API_MINOR = 0
|
||||
UC_VERSION_MAJOR = 1
|
||||
UC_VERSION_MAJOR = 2
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_EXTRA = 3
|
||||
|
||||
UC_VERSION_EXTRA = 0
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
|
@ -17,7 +18,8 @@ module UnicornEngine
|
|||
UC_ARCH_PPC = 5
|
||||
UC_ARCH_SPARC = 6
|
||||
UC_ARCH_M68K = 7
|
||||
UC_ARCH_MAX = 8
|
||||
UC_ARCH_RISCV = 8
|
||||
UC_ARCH_MAX = 9
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0
|
||||
UC_MODE_BIG_ENDIAN = 1073741824
|
||||
|
@ -29,7 +31,6 @@ module UnicornEngine
|
|||
UC_MODE_ARM926 = 128
|
||||
UC_MODE_ARM946 = 256
|
||||
UC_MODE_ARM1176 = 512
|
||||
UC_MODE_ARMBE8 = 1024
|
||||
UC_MODE_MICRO = 16
|
||||
UC_MODE_MIPS3 = 32
|
||||
UC_MODE_MIPS32R6 = 64
|
||||
|
@ -44,6 +45,8 @@ module UnicornEngine
|
|||
UC_MODE_SPARC32 = 4
|
||||
UC_MODE_SPARC64 = 8
|
||||
UC_MODE_V9 = 16
|
||||
UC_MODE_RISCV32 = 4
|
||||
UC_MODE_RISCV64 = 8
|
||||
|
||||
UC_ERR_OK = 0
|
||||
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_SPARC = 6 ' Sparc architecture
|
||||
UC_ARCH_M68K = 7 ' M68K architecture
|
||||
UC_ARCH_MAX = 8
|
||||
UC_ARCH_RISCV = 8 ' RISCV architecture
|
||||
UC_ARCH_MAX = 9
|
||||
End Enum
|
||||
|
||||
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_SPARC64 = 8 '64-bit mode
|
||||
' UC_MODE_V9 = 16 'SparcV9 mode (currently unsupported)
|
||||
' UC_MODE_RISCV32 = 4 '32-bit mode
|
||||
' UC_MODE_RISCV64 = 8 '64-bit mode
|
||||
End Enum
|
||||
|
||||
Public Enum uc_hook_type 'from /bindings/dotnet/common.fs
|
||||
|
|
37
cmake.sh
37
cmake.sh
|
@ -1,17 +1,40 @@
|
|||
#!/bin/sh
|
||||
|
||||
# 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
|
||||
|
||||
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
|
||||
cmake "${FLAGS}" ..
|
||||
else
|
||||
cmake "${FLAGS}" "-DUNICORN_ARCH=${UNICORN_ARCH}" ..
|
||||
if [ -n "${COMPILER}" ]; then
|
||||
TOOLCHAIN="${TOOLCHAIN} -DCMAKE_C_COMPILER=${COMPILER}"
|
||||
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
|
||||
|
|
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,
|
||||
see [COMPILE-NIX.md](COMPILE-NIX.md)
|
||||
This HOWTO introduces how to build Unicorn2 natively on Linux/Mac/Windows,
|
||||
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
|
||||
[COMPILE-CMAKE.md](COMPILE-CMAKE.md)
|
||||
This builds Unicorn2 on Linux/MacOS. The output is `libunicorn.so` or `libunicorn.dylib`, respectively.
|
||||
|
||||
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
|
||||
- For samples of other bindings, look into directories bindings/<language>/
|
||||
```
|
||||
$ sudo apt install cmake pkg-config
|
||||
```
|
||||
|
||||
#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
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install unicorn
|
||||
Then run the sample `sample_riscv` with:
|
||||
|
||||
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 <assert.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#define G_MAXUINT UINT_MAX
|
||||
#define G_MAXINT INT_MAX
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define g_assert(expr) assert(expr)
|
||||
#define g_assert_not_reached() assert(0)
|
||||
|
||||
/* typedefs for glib related types that may still be referenced */
|
||||
typedef void* gpointer;
|
||||
typedef const void *gconstpointer;
|
||||
typedef int gint;
|
||||
typedef uint32_t guint32;
|
||||
typedef uint64_t guint64;
|
||||
typedef unsigned int guint;
|
||||
typedef char gchar;
|
||||
typedef int gboolean;
|
||||
typedef unsigned long gulong;
|
||||
typedef unsigned long gsize;
|
||||
#include "gtestutils.h"
|
||||
#include "gtypes.h"
|
||||
#include "garray.h"
|
||||
#include "gtree.h"
|
||||
#include "ghash.h"
|
||||
#include "gmem.h"
|
||||
#include "gslice.h"
|
||||
#include "gmessages.h"
|
||||
#include "gpattern.h"
|
||||
#include "grand.h"
|
||||
#include "glist.h"
|
||||
#include "gnode.h"
|
||||
|
||||
typedef gint (*GCompareDataFunc)(gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data);
|
||||
typedef void (*GFunc)(gpointer data, gpointer user_data);
|
||||
typedef gint (*GCompareFunc)(gconstpointer v1, gconstpointer v2);
|
||||
typedef void (*GDestroyNotify)(gpointer data);
|
||||
|
||||
guint g_str_hash(gconstpointer v);
|
||||
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);
|
||||
|
||||
typedef struct _GList {
|
||||
gpointer data;
|
||||
struct _GList *next;
|
||||
struct _GList *prev;
|
||||
} GList;
|
||||
int g_strcmp0(const char *str1, const char *str2);
|
||||
|
||||
GList *g_list_first(GList *list);
|
||||
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);
|
||||
GSList *g_slist_prepend(GSList *list, gpointer data);
|
||||
GSList *g_slist_sort(GSList *list, GCompareFunc compare);
|
||||
|
||||
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);
|
||||
GSList *g_slist_find_custom(GSList *list, gconstpointer data, GCompareFunc func);
|
||||
|
||||
/* replacement for g_malloc dependency */
|
||||
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);
|
||||
|
||||
char *g_strdup(const char *str);
|
||||
char *g_strdup_printf(const char *format, ...);
|
||||
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_new0_(size_t sz, 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,
|
||||
const gchar *delimiter,
|
||||
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
|
|
@ -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 */
|
||||
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||
|
||||
#ifndef UC_QEMU_H
|
||||
#define UC_QEMU_H
|
||||
|
@ -13,25 +14,23 @@ struct uc_struct;
|
|||
#include "exec/memory.h"
|
||||
|
||||
#include "qemu/thread.h"
|
||||
#include "include/qom/cpu.h"
|
||||
#include "hw/core/cpu.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.
|
||||
typedef struct RAMBlock {
|
||||
struct RAMBlock {
|
||||
struct MemoryRegion *mr;
|
||||
uint8_t *host;
|
||||
ram_addr_t offset;
|
||||
ram_addr_t length;
|
||||
ram_addr_t used_length;
|
||||
ram_addr_t max_length;
|
||||
uint32_t flags;
|
||||
char idstr[256];
|
||||
/* Reads can take either the iothread or the ramlist lock.
|
||||
* Writes must take both locks.
|
||||
*/
|
||||
QTAILQ_ENTRY(RAMBlock) next;
|
||||
int fd;
|
||||
} RAMBlock;
|
||||
/* RCU-enabled, writes protected by the ramlist lock */
|
||||
QLIST_ENTRY(RAMBlock) next;
|
||||
size_t page_size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
MemoryRegion *mr;
|
||||
|
@ -40,12 +39,10 @@ typedef struct {
|
|||
hwaddr len;
|
||||
} BounceBuffer;
|
||||
|
||||
// This struct is originally from qemu/include/exec/ramlist.h
|
||||
typedef struct RAMList {
|
||||
/* Protected by the iothread lock. */
|
||||
unsigned long *dirty_memory[DIRTY_MEMORY_NUM];
|
||||
RAMBlock *mru_block;
|
||||
QTAILQ_HEAD(, RAMBlock) blocks;
|
||||
uint32_t version;
|
||||
QLIST_HEAD(, RAMBlock) blocks;
|
||||
} RAMList;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
|
||||
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||
|
||||
|
||||
#ifndef UC_PRIV_H
|
||||
#define UC_PRIV_H
|
||||
|
@ -14,16 +16,17 @@
|
|||
// These are masks of supported modes for each cpu/arch.
|
||||
// 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 \
|
||||
|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_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_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 READ_QWORD(x) ((uint64)x)
|
||||
#define READ_QWORD(x) ((uint64_t)x)
|
||||
#define READ_DWORD(x) (x & 0xffffffff)
|
||||
#define READ_WORD(x) (x & 0xffff)
|
||||
#define READ_BYTE_H(x) ((x & 0xffff) >> 8)
|
||||
|
@ -34,20 +37,19 @@
|
|||
#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);
|
||||
|
||||
// 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_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 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_uc_t)(struct uc_struct*);
|
||||
typedef int (*uc_args_int_uc_t)(struct uc_struct*);
|
||||
|
||||
typedef bool (*uc_args_tcg_enable_t)(struct uc_struct*);
|
||||
typedef void (*uc_args_int_uc_t)(struct uc_struct*);
|
||||
|
||||
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 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?
|
||||
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
|
||||
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
|
||||
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 {
|
||||
int type; // UC_HOOK_*
|
||||
int insn; // instruction for HOOK_INSN
|
||||
|
@ -93,8 +106,12 @@ struct hook {
|
|||
};
|
||||
|
||||
// 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
|
||||
enum uc_hook_idx {
|
||||
typedef enum uc_hook_idx {
|
||||
UC_HOOK_INTR_IDX,
|
||||
UC_HOOK_INSN_IDX,
|
||||
UC_HOOK_CODE_IDX,
|
||||
|
@ -112,7 +129,16 @@ enum uc_hook_idx {
|
|||
UC_HOOK_INSN_INVALID_IDX,
|
||||
|
||||
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 \
|
||||
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!
|
||||
#define MEM_BLOCK_INCR 32
|
||||
|
||||
typedef struct TargetPageBits TargetPageBits;
|
||||
typedef struct TCGContext TCGContext;
|
||||
|
||||
struct uc_struct {
|
||||
uc_arch arch;
|
||||
uc_mode mode;
|
||||
uc_err errnum; // qemu/cpu-exec.c
|
||||
AddressSpace as;
|
||||
AddressSpace address_space_memory;
|
||||
AddressSpace address_space_io;
|
||||
query_t query;
|
||||
reg_read_t reg_read;
|
||||
reg_write_t reg_write;
|
||||
|
@ -160,56 +190,55 @@ struct uc_struct {
|
|||
uc_args_void_t release; // release resource when uc_close()
|
||||
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_memory_map_io_t memory_map_io;
|
||||
|
||||
uc_args_uc_t init_arch, cpu_exec_init_all;
|
||||
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_ram_size_t memory_map;
|
||||
uc_args_uc_ram_size_ptr_t memory_map_ptr;
|
||||
uc_mem_unmap_t memory_unmap;
|
||||
uc_readonly_mem_t readonly_mem;
|
||||
uc_mem_redirect_t mem_redirect;
|
||||
// TODO: remove current_cpu, as it's a flag for something else ("cpu running"?)
|
||||
CPUState *cpu, *current_cpu;
|
||||
uc_cpus_init cpus_init;
|
||||
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;
|
||||
|
||||
MemoryRegion *system_memory; // qemu/exec.c
|
||||
MemoryRegion io_mem_rom; // qemu/exec.c
|
||||
MemoryRegion io_mem_notdirty; // qemu/exec.c
|
||||
MemoryRegion *system_io; // qemu/exec.c
|
||||
MemoryRegion io_mem_unassigned; // qemu/exec.c
|
||||
MemoryRegion io_mem_watch; // 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
|
||||
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.
|
||||
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;
|
||||
/* qemu/accel/tcg/translate-all.c */
|
||||
int v_l1_size;
|
||||
int v_l1_shift;
|
||||
int v_l2_levels;
|
||||
/* code generation context */
|
||||
void *tcg_ctx; // for "TCGContext tcg_ctx" in qemu/translate-all.c
|
||||
TCGContext *tcg_ctx;
|
||||
/* 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(, AddressSpace) address_spaces;
|
||||
MachineState *machine_state;
|
||||
// qom/object.c
|
||||
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;
|
||||
GHashTable *flat_views;
|
||||
bool memory_region_update_pending;
|
||||
|
||||
// linked lists containing hooks per type
|
||||
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_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
|
||||
|
||||
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())
|
||||
|
||||
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;
|
||||
uint32_t mapped_block_count;
|
||||
uint32_t mapped_block_cache_index;
|
||||
void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c)
|
||||
uint32_t target_page_size;
|
||||
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
|
||||
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.
|
||||
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_*()
|
||||
|
@ -259,7 +289,9 @@ struct uc_struct {
|
|||
struct uc_context {
|
||||
size_t context_size; // size of the real internal context structure
|
||||
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
|
||||
};
|
||||
|
||||
|
|
|
@ -137,6 +137,27 @@ typedef enum uc_arm_reg {
|
|||
UC_ARM_REG_MSP,
|
||||
UC_ARM_REG_PSP,
|
||||
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
|
||||
|
||||
//> alias registers
|
||||
|
|
|
@ -64,23 +64,6 @@ typedef unsigned int uint32_t;
|
|||
typedef signed long long int64_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
|
||||
#define _INTPTR_T_DEFINED
|
||||
#ifdef _WIN64
|
||||
|
@ -111,36 +94,7 @@ typedef _W64 unsigned int uintptr_t;
|
|||
#define UINT16_MAX 0xffffui16
|
||||
#define UINT32_MAX 0xffffffffui32
|
||||
#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
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER == MSC_VER_VS2010)
|
||||
#define _INTPTR 2
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
||||
#if defined(_MSC_VER)
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <winsock2.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