Merge branch 'dev' into patch

This commit is contained in:
Bet4 2021-10-17 18:18:09 +08:00 committed by GitHub
commit c400924fe1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1044 additions and 3188 deletions

93
.github/workflows/Crate-publishing.yml vendored Normal file
View File

@ -0,0 +1,93 @@
name: Crate 📦 Distribution
on:
push:
paths-ignore:
- ".gitignore"
- "docs/**"
- "README"
- "CREDITS.TXT"
- "COPYING_GLIB"
- "COPYING.LGPL2"
- "AUTHORS.TXT"
- "CHANGELOG"
- "COPYING"
pull_request:
env:
CI: true
jobs:
build:
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.name }}
strategy:
fail-fast: false
matrix:
config:
- {
os: windows-latest,
arch: x64,
name: 'Windows x86_64'
}
- {
os: windows-latest,
arch: x32,
name: 'Windows x86'
}
- {
os: ubuntu-latest,
arch: x64,
name: 'Ubuntu x86_64'
}
- {
os: macos-latest,
arch: x64,
name: 'macOS x86_64'
}
steps:
- uses: actions/checkout@v2
- name: '🛠️ Set up Rust'
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
default: true
- name: '🛠️ Add msbuild to PATH'
if: contains(matrix.config.name, 'win')
uses: microsoft/setup-msbuild@v1.0.3
with:
vs-version: '16.5'
- name: '🛠️ Win build dependencies'
if: contains(matrix.config.name, 'win')
shell: bash
run: |
choco install ninja cmake
- name: '🚧 Cargo test'
run: |
cd bindings/rust && cargo test
# - name: '📤 Upload artifact'
# uses: actions/upload-artifact@v2
# with:
# path: ${{ github.workspace }}/bindings/python/dist/*
# publish:
# needs: [build]
# runs-on: ubuntu-latest
# if: startsWith(github.ref, 'refs/tags')
# steps:
# - uses: actions/download-artifact@v2
# with:
# name: artifact
# path: dist
# - name: '📦 Publish distribution to PyPI'
# uses: pypa/gh-action-pypi-publish@master
# with:
# user: __token__
# password: ${{ secrets.pypi_pass }}

View File

@ -3,7 +3,6 @@ name: PyPI 📦 Distribution
on:
push:
paths-ignore:
- ".github/**"
- ".gitignore"
- "docs/**"
- "README"

View File

@ -1,10 +1,8 @@
name: Build UC2
on:
push:
tags-ignore:
- "*"
paths-ignore:
- ".github/**"
- ".gitignore"
- "docs/**"
- "README"
@ -16,13 +14,14 @@ on:
- "COPYING"
pull_request:
env:
CI: true
jobs:
Windows:
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.name }} - ${{ matrix.compiler }}
name: ${{ matrix.config.name }}
strategy:
fail-fast: false
matrix:
@ -65,15 +64,22 @@ jobs:
archiver: '7z a',
generators: 'Visual Studio 16 2019'
}
- {
os: windows-latest,
arch: x86,
python-arch: x86,
python-ver: '3.8',
name: 'windows-x86 MSVC 32bit',
msvc-arch: x86,
artifact: 'windows_msvc32.7z',
build_type: 'Debug',
archiver: '7z a',
generators: 'Visual Studio 16 2019'
}
compiler: [ gcc ]
steps:
- uses: actions/checkout@v2
# - name: '🛠️ Python setup'
# uses: actions/setup-python@v2
# with:
# python-version: ${{ matrix.config.python-ver }}
- name: '🛠️ Win MINGW setup'
if: contains(matrix.config.mingw, 'MINGW')
uses: msys2/setup-msys2@v2
@ -87,12 +93,12 @@ jobs:
mingw-w64-${{ matrix.config.mingw-arch }}-${{ matrix.compiler }}
mingw-w64-${{ matrix.config.mingw-arch }}-toolchain
- name: '🛠️ Win MSVC setup'
if: contains(matrix.config.name, 'MSVC')
- name: '🛠️ Win MSVC 64 setup'
if: contains(matrix.config.name, 'MSVC 64')
uses: microsoft/setup-msbuild@v1
- name: '🚧 Win MSVC build'
if: contains(matrix.config.name, 'MSVC')
- name: '🚧 Win MSVC 64 build'
if: contains(matrix.config.name, 'MSVC 64')
shell: bash
run: |
choco install ninja cmake
@ -110,6 +116,32 @@ jobs:
ctest -C ${{ matrix.config.build_type }}
mv Debug instdir
- name: '🛠️ Win MSVC 32 setup'
if: contains(matrix.config.name, 'MSVC 32')
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x86
- name: '🚧 Win MSVC 32 build'
if: contains(matrix.config.name, 'MSVC 32')
shell: bash
run: |
choco install ninja cmake
ninja --version
cmake --version
mkdir build
cmake \
-S . \
-B . \
-A "win32" \
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
-G "${{ matrix.config.generators }}" \
-DCMAKE_INSTALL_PREFIX:PATH=instdir
cmake --build . --config ${{ matrix.config.build_type }}
cmake --install . --strip --config ${{ matrix.config.build_type }}
ctest -C ${{ matrix.config.build_type }}
mv Debug instdir
- name: '🚧 Win MINGW build'
if: contains(matrix.config.mingw, 'MINGW')
shell: msys2 {0}
@ -167,6 +199,17 @@ jobs:
archiver: '7za a',
generators: 'Ninja'
}
- {
os: macos-11,
arch: x86_64,
python-arch: x86_64,
python-ver: '3.8',
name: 'android cmake',
artifact: 'Android-x86_64.7z',
build_type: 'Debug',
archiver: '7za a',
generators: 'Ninja'
}
compiler: [ gcc ]
steps:
- uses: actions/checkout@v2
@ -177,24 +220,81 @@ jobs:
# python-version: ${{ matrix.config.python-ver }}
- name: '🚧 Mac build'
if: contains(matrix.config.os, 'macos')
if: contains(matrix.config.name, 'macos-x64')
shell: bash
run: |
brew install p7zip cmake ninja
ninja --version
cmake --version
mkdir build
mkdir instdir
cmake \
-S . \
-B . \
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
-G "${{ matrix.config.generators }}" \
-DCMAKE_INSTALL_PREFIX:PATH=instdir
cmake --build . --config ${{ matrix.config.build_type }}
cmake --install . --strip
ctest -C ${{ matrix.config.build_type }}
brew install p7zip cmake ninja
ninja --version
cmake --version
mkdir build
mkdir instdir
cmake \
-S . \
-B . \
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
-G "${{ matrix.config.generators }}" \
-DCMAKE_INSTALL_PREFIX:PATH=instdir
cmake --build . --config ${{ matrix.config.build_type }}
cmake --install . --strip
ctest -C ${{ matrix.config.build_type }}
- name: '🚧 Android x86_64 build'
if: contains(matrix.config.name, 'android')
shell: bash
run: |
brew install p7zip cmake ninja
mkdir build
mkdir instdir
cmake . -DCMAKE_TOOLCHAIN_FILE="$ANDROID_HOME/ndk/21.4.7075529/build/cmake/android.toolchain.cmake" \
-DANDROID_PLATFORM=android-28 \
-DANDROID_NDK="$ANDROID_HOME/ndk/21.4.7075529" \
-DANDROID_ABI=${{ matrix.config.arch }} \
-DOLP_SDK_ENABLE_TESTING=NO \
-DOLP_SDK_BUILD_EXAMPLES=ON \
-S . \
-B . \
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
-G "${{ matrix.config.generators }}" \
-DCMAKE_INSTALL_PREFIX:PATH=instdir
cmake --build . --config ${{ matrix.config.build_type }}
cmake --install . --strip
- name: '🚧 AVD Cache'
if: contains(matrix.config.name, 'android')
uses: actions/cache@v2
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-28
- name: '🚧 Create x86_64 tests environment'
if: contains(matrix.config.name, 'android') && steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 28
arch: ${{ matrix.config.arch }}
force-avd-creation: false
disable-animations: false
target: default
profile: Nexus 6
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -verbose -show-kernel
script: echo "Generated AVD snapshot for caching."
- name: '🚧 Android x86_64 tests'
if: contains(matrix.config.name, 'android')
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 28
force-avd-creation: false
disable-animations: true
arch: ${{ matrix.config.arch }}
target: default
profile: Nexus 6
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -verbose -show-kernel
script: bash ./adb.sh
- name: '📦 Pack artifact'
shell: bash
working-directory: instdir
@ -331,4 +431,4 @@ jobs:
uses: actions/upload-artifact@v1
with:
path: ./${{ matrix.config.artifact }}
name: ${{ matrix.config.artifact }}
name: ${{ matrix.config.artifact }}

1
.gitignore vendored
View File

@ -60,6 +60,7 @@ _*.txt
_*.diff
tmp/
bindings/java/unicorn_Unicorn.h
bindings/python/build/
bindings/python/dist/
bindings/python/src/

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "docs/Unicorn_Engine_Documentation"]
path = docs/Unicorn_Engine_Documentation
url = git@github.com:kabeor/Unicorn-Engine-Documentation

View File

@ -90,6 +90,7 @@ else()
endif()
elseif(ANDROID_ABI)
string(FIND "${ANDROID_ABI}" "arm64" UC_RET)
file(WRITE ${CMAKE_BINARY_DIR}/adb.sh "#!/bin/bash\n\n# Auto-generated by CMakeLists.txt\n\nadb shell mkdir -p /data/local/tmp/build\n")
if (${UC_RET} GREATER_EQUAL "0")
set(UNICORN_TARGET_ARCH "aarch64")
@ -1031,6 +1032,9 @@ if (UNICORN_BUILD_SHARED)
add_library(unicorn SHARED
${UNICORN_SRCS}
)
if (ANDROID_ABI)
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb push ./libunicorn.so /data/local/tmp/build/\n")
endif()
else()
add_library(unicorn STATIC
${UNICORN_SRCS}
@ -1167,22 +1171,27 @@ if(UNICORN_FUZZ)
endforeach()
else()
foreach(SAMPLE_FILE ${UNICORN_SAMPLE_FILE})
add_executable(${SAMPLE_FILE}
${CMAKE_CURRENT_SOURCE_DIR}/samples/${SAMPLE_FILE}.c
)
target_link_libraries(${SAMPLE_FILE}
${SAMPLES_LIB}
)
endforeach(SAMPLE_FILE)
add_executable(${SAMPLE_FILE}
${CMAKE_CURRENT_SOURCE_DIR}/samples/${SAMPLE_FILE}.c
)
target_link_libraries(${SAMPLE_FILE}
${SAMPLES_LIB}
)
endforeach(SAMPLE_FILE)
foreach(TEST_FILE ${UNICORN_TEST_FILE})
add_executable(${TEST_FILE}
${CMAKE_CURRENT_SOURCE_DIR}/tests/unit/${TEST_FILE}.c
)
target_link_libraries(${TEST_FILE}
${SAMPLES_LIB}
)
add_test(${TEST_FILE} ${TEST_FILE})
foreach(TEST_FILE ${UNICORN_TEST_FILE})
add_executable(${TEST_FILE}
${CMAKE_CURRENT_SOURCE_DIR}/tests/unit/${TEST_FILE}.c
)
target_link_libraries(${TEST_FILE}
${SAMPLES_LIB}
)
add_test(${TEST_FILE} ${TEST_FILE})
if (ANDROID_ABI)
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb push ${TEST_FILE} /data/local/tmp/build/\n")
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb shell \"chmod +x /data/local/tmp/build/${TEST_FILE}\"\n")
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb shell \'LD_LIBRARY_PATH=/data/local/tmp/build:$LD_LIBRARY_PATH /data/local/tmp/build/${TEST_FILE}\' || exit -1\n")
endif()
endforeach(TEST_FILE)
endif()

View File

@ -79,3 +79,4 @@ 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
Chenxu Wu (kabeor): Documentation

View File

@ -1,9 +1,11 @@
.PHONY: gen_const clean
JAVA_HOME := $(shell jrunscript -e 'java.lang.System.out.println(java.lang.System.getProperty("java.home"));')
JC=javac
JAVA_INC := $(shell realpath $(JAVA_HOME)/../include)
JAVA_HOME := $(shell readlink -f `which $(JC)` | sed "s:/bin/$(JC)::")
JAVA_INC := $(shell realpath $(JAVA_HOME)/include)
JAVA_PLATFORM_INC := $(shell dirname `find $(JAVA_INC) -name jni_md.h`)
@ -28,7 +30,6 @@ LIBS=-lunicorn
LIBDIR=-L../../
INCS=-I$(JAVA_INC) -I$(JAVA_PLATFORM_INC) -I$(UNICORN_INC)
JC=javac
CLASSPATH=./
.SUFFIXES: .java .class
@ -46,7 +47,7 @@ all: lib jar samples
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
unicorn_Unicorn.h: unicorn/Unicorn.java
javah unicorn.Unicorn
javac -h . $<
unicorn_Unicorn.o: unicorn_Unicorn.c unicorn_Unicorn.h
$(CC) -c $(CFLAGS) $(INCS) $< -o $@
@ -63,12 +64,12 @@ jar: jarfiles
jar cf $(JARFILE) unicorn/*.class
install: lib jar
cp libunicorn_java$(LIB_EXT) $(JAVA_HOME)/lib/ext
cp $(JARFILE) $(JAVA_HOME)/lib/ext
cp libunicorn_java$(LIB_EXT) /usr/lib
cp $(JARFILE) /usr/share/java
uninstall:
rm $(JAVA_HOME)/lib/ext/libunicorn_java$(LIB_EXT)
rm $(JAVA_HOME)/lib/ext/$(JARFILE)
rm /usr/lib/libunicorn_java$(LIB_EXT)
rm /usr/share/java/$(JARFILE)
gen_const:
cd .. && python const_generator.py java

View File

@ -30,12 +30,12 @@ import java.util.*;
public class SampleNetworkAuditing {
public static int next_id = 3;
public static long next_id = 3;
public static final int SIZE_REG = 4;
private static LogChain fd_chains = new LogChain();
public static int get_id() {
public static long get_id() {
return next_id++;
}
@ -112,7 +112,7 @@ public class SampleNetworkAuditing {
long mode = edx;
String filename = read_string(uc, filename_addr);
Long dummy_fd = new Long(get_id());
Long dummy_fd = get_id();
uc.reg_write(Unicorn.UC_X86_REG_EAX, dummy_fd);
String msg = String.format("open file (filename=%s flags=%d mode=%d) with fd(%d)", filename, flags, mode, dummy_fd);
@ -144,8 +144,8 @@ public class SampleNetworkAuditing {
long sock_type = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG));
long protocol = toInt(uc.mem_read(args + SIZE_REG * 2, SIZE_REG));
Long dummy_fd = new Long(get_id());
uc.reg_write(Unicorn.UC_X86_REG_EAX, dummy_fd.intValue());
Long dummy_fd = get_id();
uc.reg_write(Unicorn.UC_X86_REG_EAX, dummy_fd);
if (family == 2) { // AF_INET
String msg = String.format("create socket (%s, %s) with fd(%d)", ADDR_FAMILY.get(family), SOCKET_TYPES.get(sock_type), dummy_fd);
@ -401,7 +401,7 @@ public class SampleNetworkAuditing {
mu.mem_write(ADDRESS, code);
// initialize stack
mu.reg_write(Unicorn.UC_X86_REG_ESP, new Long(ADDRESS + 0x200000));
mu.reg_write(Unicorn.UC_X86_REG_ESP, ADDRESS + 0x200000L);
// handle interrupt ourself
mu.hook_add(new MyInterruptHook(), null);

View File

@ -40,9 +40,9 @@ public class Sample_arm {
static void test_arm()
{
Long r0 = new Long(0x1234); // R0 register
Long r2 = new Long(0x6789); // R1 register
Long r3 = new Long(0x3333); // R2 register
Long r0 = 0x1234L; // R0 register
Long r2 = 0x6789L; // R1 register
Long r3 = 0x3333L; // R2 register
Long r1; // R1 register
System.out.print("Emulate ARM code\n");
@ -85,7 +85,7 @@ public class Sample_arm {
static void test_thumb()
{
Long sp = new Long(0x1234); // R0 register
Long sp = 0x1234L; // R0 register
System.out.print("Emulate THUMB code\n");

View File

@ -69,9 +69,9 @@ public class Sample_arm64 {
static void test_arm64()
{
Long x11 = new Long(0x1234); // X11 register
Long x13 = new Long(0x6789); // X13 register
Long x15 = new Long(0x3333); // X15 register
Long x11 = 0x1234L; // X11 register
Long x13 = 0x6789L; // X13 register
Long x15 = 0x3333L; // X15 register
System.out.print("Emulate ARM64 code\n");

View File

@ -68,26 +68,26 @@ public class Sample_m68k {
static void test_m68k()
{
Long d0 = new Long(0x0000); // d0 data register
Long d1 = new Long(0x0000); // d1 data register
Long d2 = new Long(0x0000); // d2 data register
Long d3 = new Long(0x0000); // d3 data register
Long d4 = new Long(0x0000); // d4 data register
Long d5 = new Long(0x0000); // d5 data register
Long d6 = new Long(0x0000); // d6 data register
Long d7 = new Long(0x0000); // d7 data register
Long a0 = new Long(0x0000); // a0 address register
Long a1 = new Long(0x0000); // a1 address register
Long a2 = new Long(0x0000); // a2 address register
Long a3 = new Long(0x0000); // a3 address register
Long a4 = new Long(0x0000); // a4 address register
Long a5 = new Long(0x0000); // a5 address register
Long a6 = new Long(0x0000); // a6 address register
Long a7 = new Long(0x0000); // a6 address register
Long pc = new Long(0x0000); // program counter
Long sr = new Long(0x0000); // status register
Long d0 = 0x0000L; // d0 data register
Long d1 = 0x0000L; // d1 data register
Long d2 = 0x0000L; // d2 data register
Long d3 = 0x0000L; // d3 data register
Long d4 = 0x0000L; // d4 data register
Long d5 = 0x0000L; // d5 data register
Long d6 = 0x0000L; // d6 data register
Long d7 = 0x0000L; // d7 data register
Long a0 = 0x0000L; // a0 address register
Long a1 = 0x0000L; // a1 address register
Long a2 = 0x0000L; // a2 address register
Long a3 = 0x0000L; // a3 address register
Long a4 = 0x0000L; // a4 address register
Long a5 = 0x0000L; // a5 address register
Long a6 = 0x0000L; // a6 address register
Long a7 = 0x0000L; // a6 address register
Long pc = 0x0000L; // program counter
Long sr = 0x0000L; // status register
System.out.print("Emulate M68K code\n");

View File

@ -70,7 +70,7 @@ public class Sample_mips {
static void test_mips_eb()
{
Long r1 = new Long(0x6789); // R1 register
Long r1 = 0x6789L; // R1 register
System.out.print("Emulate MIPS code (big-endian)\n");
@ -107,7 +107,7 @@ public class Sample_mips {
static void test_mips_el()
{
Long r1 = new Long(0x6789); // R1 register
Long r1 = 0x6789L; // R1 register
System.out.print("===========================\n");
System.out.print("Emulate MIPS code (little-endian)\n");

View File

@ -69,9 +69,9 @@ public class Sample_sparc {
static void test_sparc()
{
Long g1 = new Long(0x1230); // G1 register
Long g2 = new Long(0x6789); // G2 register
Long g3 = new Long(0x5555); // G3 register
Long g1 = 0x1230L; // G1 register
Long g2 = 0x6789L; // G2 register
Long g3 = 0x5555L; // G3 register
System.out.print("Emulate SPARC code\n");

View File

@ -171,8 +171,8 @@ public class Sample_x86 {
}
static void test_i386() {
Long r_ecx = new Long(0x1234); // ECX register
Long r_edx = new Long(0x7890); // EDX register
Long r_ecx = 0x1234L; // ECX register
Long r_edx = 0x7890L; // EDX register
System.out.print("Emulate i386 code\n");
@ -234,8 +234,8 @@ public class Sample_x86 {
static void test_i386_inout()
{
Long r_eax = new Long(0x1234); // ECX register
Long r_ecx = new Long(0x6789); // EDX register
Long r_eax = 0x1234L; // ECX register
Long r_ecx = 0x6789L; // EDX register
System.out.print("===================================\n");
System.out.print("Emulate i386 code with IN/OUT instructions\n");
@ -309,8 +309,8 @@ public class Sample_x86 {
// emulate code that loop forever
static void test_i386_loop()
{
Long r_ecx = new Long(0x1234); // ECX register
Long r_edx = new Long(0x7890); // EDX register
Long r_ecx = 0x1234L; // ECX register
Long r_edx = 0x7890L; // EDX register
System.out.print("===================================\n");
System.out.print("Emulate i386 code that loop forever\n");
@ -346,8 +346,8 @@ public class Sample_x86 {
// emulate code that read invalid memory
static void test_i386_invalid_mem_read()
{
Long r_ecx = new Long(0x1234); // ECX register
Long r_edx = new Long(0x7890); // EDX register
Long r_ecx = 0x1234L; // ECX register
Long r_edx = 0x7890L; // EDX register
System.out.print("===================================\n");
System.out.print("Emulate i386 code that read from invalid memory\n");
@ -393,8 +393,8 @@ public class Sample_x86 {
// emulate code that read invalid memory
static void test_i386_invalid_mem_write()
{
Long r_ecx = new Long(0x1234); // ECX register
Long r_edx = new Long(0x7890); // EDX register
Long r_ecx = 0x1234L; // ECX register
Long r_edx = 0x7890L; // EDX register
System.out.print("===================================\n");
System.out.print("Emulate i386 code that write to invalid memory\n");
@ -453,8 +453,8 @@ public class Sample_x86 {
// emulate code that jump to invalid memory
static void test_i386_jump_invalid()
{
Long r_ecx = new Long(0x1234); // ECX register
Long r_edx = new Long(0x7890); // EDX register
Long r_ecx = 0x1234L; // ECX register
Long r_edx = 0x7890L; // EDX register
System.out.print("===================================\n");
System.out.print("Emulate i386 code that jumps to invalid memory\n");
@ -527,22 +527,22 @@ public class Sample_x86 {
u.mem_write(ADDRESS, X86_CODE64);
// initialize machine registers
u.reg_write(Unicorn.UC_X86_REG_RSP, new Long(rsp));
u.reg_write(Unicorn.UC_X86_REG_RAX, new Long(rax));
u.reg_write(Unicorn.UC_X86_REG_RBX, new Long(rbx));
u.reg_write(Unicorn.UC_X86_REG_RCX, new Long(rcx));
u.reg_write(Unicorn.UC_X86_REG_RDX, new Long(rdx));
u.reg_write(Unicorn.UC_X86_REG_RSI, new Long(rsi));
u.reg_write(Unicorn.UC_X86_REG_RDI, new Long(rdi));
u.reg_write(Unicorn.UC_X86_REG_R8, new Long(r8));
u.reg_write(Unicorn.UC_X86_REG_R9, new Long(r9));
u.reg_write(Unicorn.UC_X86_REG_R10, new Long(r10));
u.reg_write(Unicorn.UC_X86_REG_R11, new Long(r11));
u.reg_write(Unicorn.UC_X86_REG_R12, new Long(r12));
u.reg_write(Unicorn.UC_X86_REG_R13, new Long(r13));
u.reg_write(Unicorn.UC_X86_REG_R14, new Long(r14));
u.reg_write(Unicorn.UC_X86_REG_R15, new Long(r15));
u.reg_write(Unicorn.UC_X86_REG_RSP, rsp);
u.reg_write(Unicorn.UC_X86_REG_RAX, rax);
u.reg_write(Unicorn.UC_X86_REG_RBX, rbx);
u.reg_write(Unicorn.UC_X86_REG_RCX, rcx);
u.reg_write(Unicorn.UC_X86_REG_RDX, rdx);
u.reg_write(Unicorn.UC_X86_REG_RSI, rsi);
u.reg_write(Unicorn.UC_X86_REG_RDI, rdi);
u.reg_write(Unicorn.UC_X86_REG_R8, r8);
u.reg_write(Unicorn.UC_X86_REG_R9, r9);
u.reg_write(Unicorn.UC_X86_REG_R10, r10);
u.reg_write(Unicorn.UC_X86_REG_R11, r11);
u.reg_write(Unicorn.UC_X86_REG_R12, r12);
u.reg_write(Unicorn.UC_X86_REG_R13, r13);
u.reg_write(Unicorn.UC_X86_REG_R14, r14);
u.reg_write(Unicorn.UC_X86_REG_R15, r15);
// tracing all basic blocks with customized callback
u.hook_add(new MyBlockHook(), 1, 0, null);
@ -598,9 +598,9 @@ public class Sample_x86 {
static void test_x86_16()
{
Long eax = new Long(7);
Long ebx = new Long(5);
Long esi = new Long(6);
Long eax = 7L;
Long ebx = 5L;
Long esi = 6L;
System.out.print("Emulate x86 16-bit code\n");

View File

@ -49,7 +49,7 @@ public class Sample_x86_mmr {
uc.reg_write(Unicorn.UC_X86_REG_LDTR, ldtr1);
uc.reg_write(Unicorn.UC_X86_REG_GDTR, gdtr1);
uc.reg_write(Unicorn.UC_X86_REG_EAX, new Long(0xdddddddd));
uc.reg_write(Unicorn.UC_X86_REG_EAX, 0xddddddddL);
// read the registers back out
eax = (int)((Long)uc.reg_read(Unicorn.UC_X86_REG_EAX)).longValue();

View File

@ -113,7 +113,7 @@ public class Shellcode {
static void test_i386()
{
Long r_esp = new Long(ADDRESS + 0x200000); // ESP register
Long r_esp = ADDRESS + 0x200000L; // ESP register
System.out.print("Emulate i386 code\n");
@ -158,4 +158,4 @@ public class Shellcode {
}
}
}

View File

@ -25,7 +25,7 @@ import java.util.*;
public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, SparcConst, MipsConst, X86Const {
private long eng;
public long eng;
private int arch;
private int mode;

View File

@ -1,8 +1,8 @@
[package]
name = "unicorn"
version = "1.0.0"
authors = ["Lukas Seidel"]
documentation = ""
name = "unicorn-engine"
version = "2.0.0-rc3"
authors = ["Ziqiao Kong", "Lukas Seidel"]
documentation = "https://github.com/unicorn-engine/unicorn/wiki"
edition = "2018"
include = [
"/.gitmodules",
@ -10,6 +10,7 @@ include = [
"/Cargo.toml",
"/README.md",
"/src/*",
"build.rs"
]
license = "GPL-2.0"
readme = "README.md"

View File

@ -1,17 +1,17 @@
# unicorn-rs
# Unicorn-engine
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.
Checkout Unicorn2 source code at [dev branch](https://github.com/unicorn-engine/unicorn/tree/dev).
```rust
use unicorn::RegisterARM;
use unicorn::unicorn_const::{Arch, Mode, Permission, SECOND_SCALE};
use unicorn_engine::RegisterARM;
use unicorn_engine::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 unicorn = unicorn-engine::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");
@ -26,20 +26,18 @@ fn main() {
```
Further sample code can be found in ```tests/unicorn.rs```.
## Installation
## Usage
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.
Add this to your `Cargo.toml`:
```
[dependencies]
unicorn = { path = "/path/to/bindings/rust", version="1.0.0" }
unicorn-engine = "2.0.0-rc3"
```
## 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.
Thanks to all contributors.

View File

@ -1,20 +1,128 @@
use std::result::Result;
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");
let profile = env::var("PROFILE").unwrap();
let mut version = String::from("dev");
if let Result::Ok(version_env) = env::var("UNICORN_BRANCH") {
version = version_env;
}
let unicorn_dir;
if let Result::Ok(_) = env::var("CI") {
unicorn_dir = format!("../..");
} else {
unicorn_dir = format!("{}/unicorn_git", out_dir);
Command::new("rm").arg("-rf").arg(&unicorn_dir);
Command::new("git")
.arg("clone")
.arg("git@github.com:unicorn-engine/unicorn.git")
.arg("-b")
.arg(version)
.arg(&unicorn_dir)
.output()
.expect("Fail to clone Unicorn repository.");
}
println!("cargo:rerun-if-changed={}", &unicorn_dir);
// We don't use TARGET since we can't cross-build.
if env::consts::OS == "windows" {
// Windows
let mut cmd = Command::new("cmake");
cmd.current_dir(&unicorn_dir)
.arg("-B")
.arg("rust_build")
.arg("-DUNICORN_BUILD_SHARED=off")
.arg("-G")
.arg("Visual Studio 16 2019");
if profile == "debug" {
cmd.arg("-DCMAKE_BUILD_TYPE=Debug");
} else {
cmd.arg("-DCMAKE_BUILD_TYPE=Release");
}
cmd.output()
.expect("Fail to create build directory on Windows.");
let mut platform = "x64";
let mut conf = "Release";
if std::mem::size_of::<usize>() == 4 {
platform = "Win32";
}
if profile == "debug" {
conf = "Debug";
}
Command::new("msbuild")
.current_dir(format!("{}/rust_build", &unicorn_dir))
.arg("unicorn.sln")
.arg("-m")
.arg("-p:Platform=".to_owned() + platform)
.arg("-p:Configuration=".to_owned() + conf)
.output()
.expect("Fail to build unicorn on Win32.");
println!(
"cargo:rustc-link-search={}/rust_build/{}",
unicorn_dir, conf
);
} else {
// Most Unix-like systems
let mut cmd = Command::new("cmake");
cmd.current_dir(&unicorn_dir)
.arg("-B")
.arg("rust_build")
.arg("-DUNICORN_BUILD_SHARED=off");
if profile == "debug" {
cmd.arg("-DCMAKE_BUILD_TYPE=Debug");
} else {
cmd.arg("-DCMAKE_BUILD_TYPE=Release");
}
cmd.output()
.expect("Fail to create build directory on *nix.");
Command::new("make")
.current_dir(format!("{}/rust_build", &unicorn_dir))
.arg("-j6")
.output()
.expect("Fail to build unicorn on *nix.");
println!("cargo:rustc-link-search={}/rust_build", unicorn_dir);
}
// This is a workaround for Unicorn static link since libunicorn.a is also linked again lib*-softmmu.a.
// Static libs is just a bundle of objects files. The link relation defined in CMakeLists is only
// valid within the cmake project scope and cmake would help link again sub static libs automatically.
//
// Lazymio(@wtdcode): Why do I stick to static link? See: https://github.com/rust-lang/cargo/issues/5077
println!("cargo:rustc-link-lib=unicorn");
for arch in [
"x86_64",
"arm",
"armeb",
"aarch64",
"aarch64eb",
"riscv32",
"riscv64",
"mips",
"mipsel",
"mips64",
"mips64el",
"sparc",
"sparc64",
"m68k",
"ppc",
"ppc64",
]
.iter()
{
println!("cargo:rustc-link-lib={}-softmmu", arch);
}
println!("cargo:rustc-link-lib=unicorn-common");
}

View File

@ -123,8 +123,31 @@ pub enum RegisterARM {
MSP = 115,
PSP = 116,
CONTROL = 117,
XPSR = 118,
ENDING = 119,
IAPSR = 118,
EAPSR = 119,
XPSR = 120,
EPSR = 121,
IEPSR = 122,
PRIMASK = 123,
BASEPRI = 124,
BASEPRI_MAX = 125,
FAULTMASK = 126,
APSR_NZCVQ = 127,
APSR_G = 128,
APSR_NZCVQG = 129,
IAPSR_NZCVQ = 130,
IAPSR_G = 131,
IAPSR_NZCVQG = 132,
EAPSR_NZCVQ = 133,
EAPSR_G = 134,
EAPSR_NZCVQG = 135,
XPSR_NZCVQ = 136,
XPSR_G = 137,
XPSR_NZCVQG = 138,
ENDING = 139,
}
impl RegisterARM {
// alias registers
// (assoc) R13 = 12,
// (assoc) R14 = 10,
@ -133,9 +156,6 @@ pub enum RegisterARM {
// (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;

View File

@ -1,4 +1,5 @@
#![allow(non_camel_case_types)]
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// ARM64 registers
#[repr(C)]

View File

@ -6,13 +6,13 @@
//!
//! ```rust
//!
//! use unicorn::RegisterARM;
//! use unicorn::unicorn_const::{Arch, Mode, Permission, SECOND_SCALE};
//! use unicorn_engine::RegisterARM;
//! use unicorn_engine::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 unicorn = unicorn_engine::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");
@ -35,9 +35,10 @@ mod arm64;
mod m68k;
mod mips;
mod ppc;
mod riscv;
mod sparc;
mod x86;
pub use crate::{arm::*, arm64::*, m68k::*, mips::*, ppc::*, sparc::*, x86::*};
pub use crate::{arm::*, arm64::*, m68k::*, mips::*, ppc::*, riscv::*, sparc::*, x86::*};
use ffi::uc_handle;
use std::collections::HashMap;

View File

@ -21,4 +21,5 @@ pub enum RegisterM68K {
D7,
SR,
PC,
ENDING,
}

View File

@ -1,4 +1,5 @@
#![allow(non_camel_case_types)]
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// MIPS registers
#[repr(C)]
@ -155,7 +156,11 @@ pub enum RegisterMIPS {
MPL2 = 136,
CP0_CONFIG3 = 137,
CP0_USERLOCAL = 138,
ENDING = 139,
CP0_STATUS = 139,
ENDING = 140,
}
impl RegisterMIPS {
// alias registers
// (assoc) ZERO = 2,
// (assoc) AT = 3,
@ -198,9 +203,6 @@ pub enum RegisterMIPS {
// (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;

213
bindings/rust/src/riscv.rs Normal file
View File

@ -0,0 +1,213 @@
#![allow(non_camel_case_types)]
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// RISCV registers
#[repr(C)]
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum RegisterRISCV {
INVALID = 0,
// General purpose registers
X0 = 1,
X1 = 2,
X2 = 3,
X3 = 4,
X4 = 5,
X5 = 6,
X6 = 7,
X7 = 8,
X8 = 9,
X9 = 10,
X10 = 11,
X11 = 12,
X12 = 13,
X13 = 14,
X14 = 15,
X15 = 16,
X16 = 17,
X17 = 18,
X18 = 19,
X19 = 20,
X20 = 21,
X21 = 22,
X22 = 23,
X23 = 24,
X24 = 25,
X25 = 26,
X26 = 27,
X27 = 28,
X28 = 29,
X29 = 30,
X30 = 31,
X31 = 32,
// Floating-point registers
F0 = 33,
F1 = 34,
F2 = 35,
F3 = 36,
F4 = 37,
F5 = 38,
F6 = 39,
F7 = 40,
F8 = 41,
F9 = 42,
F10 = 43,
F11 = 44,
F12 = 45,
F13 = 46,
F14 = 47,
F15 = 48,
F16 = 49,
F17 = 50,
F18 = 51,
F19 = 52,
F20 = 53,
F21 = 54,
F22 = 55,
F23 = 56,
F24 = 57,
F25 = 58,
F26 = 59,
F27 = 60,
F28 = 61,
F29 = 62,
F30 = 63,
F31 = 64,
PC = 65,
ENDING = 66,
}
impl RegisterRISCV {
// Alias registers
// (assoc) ZERO = 1,
// (assoc) RA = 2,
// (assoc) SP = 3,
// (assoc) GP = 4,
// (assoc) TP = 5,
// (assoc) T0 = 6,
// (assoc) T1 = 7,
// (assoc) T2 = 8,
// (assoc) S0 = 9,
// (assoc) FP = 9,
// (assoc) S1 = 10,
// (assoc) A0 = 11,
// (assoc) A1 = 12,
// (assoc) A2 = 13,
// (assoc) A3 = 14,
// (assoc) A4 = 15,
// (assoc) A5 = 16,
// (assoc) A6 = 17,
// (assoc) A7 = 18,
// (assoc) S2 = 19,
// (assoc) S3 = 20,
// (assoc) S4 = 21,
// (assoc) S5 = 22,
// (assoc) S6 = 23,
// (assoc) S7 = 24,
// (assoc) S8 = 25,
// (assoc) S9 = 26,
// (assoc) S10 = 27,
// (assoc) S11 = 28,
// (assoc) T3 = 29,
// (assoc) T4 = 30,
// (assoc) T5 = 31,
// (assoc) T6 = 32,
// (assoc) FT0 = 33,
// (assoc) FT1 = 34,
// (assoc) FT2 = 35,
// (assoc) FT3 = 36,
// (assoc) FT4 = 37,
// (assoc) FT5 = 38,
// (assoc) FT6 = 39,
// (assoc) FT7 = 40,
// (assoc) FS0 = 41,
// (assoc) FS1 = 42,
// (assoc) FA0 = 43,
// (assoc) FA1 = 44,
// (assoc) FA2 = 45,
// (assoc) FA3 = 46,
// (assoc) FA4 = 47,
// (assoc) FA5 = 48,
// (assoc) FA6 = 49,
// (assoc) FA7 = 50,
// (assoc) FS2 = 51,
// (assoc) FS3 = 52,
// (assoc) FS4 = 53,
// (assoc) FS5 = 54,
// (assoc) FS6 = 55,
// (assoc) FS7 = 56,
// (assoc) FS8 = 57,
// (assoc) FS9 = 58,
// (assoc) FS10 = 59,
// (assoc) FS11 = 60,
// (assoc) FT8 = 61,
// (assoc) FT9 = 62,
// (assoc) FT10 = 63,
// (assoc) FT11 = 64,
pub const ZERO: RegisterRISCV = RegisterRISCV::X0;
pub const RA: RegisterRISCV = RegisterRISCV::X1;
pub const SP: RegisterRISCV = RegisterRISCV::X2;
pub const GP: RegisterRISCV = RegisterRISCV::X3;
pub const TP: RegisterRISCV = RegisterRISCV::X4;
pub const T0: RegisterRISCV = RegisterRISCV::X5;
pub const T1: RegisterRISCV = RegisterRISCV::X6;
pub const T2: RegisterRISCV = RegisterRISCV::X7;
pub const S0: RegisterRISCV = RegisterRISCV::X8;
pub const FP: RegisterRISCV = RegisterRISCV::X8;
pub const S1: RegisterRISCV = RegisterRISCV::X9;
pub const A0: RegisterRISCV = RegisterRISCV::X10;
pub const A1: RegisterRISCV = RegisterRISCV::X11;
pub const A2: RegisterRISCV = RegisterRISCV::X12;
pub const A3: RegisterRISCV = RegisterRISCV::X13;
pub const A4: RegisterRISCV = RegisterRISCV::X14;
pub const A5: RegisterRISCV = RegisterRISCV::X15;
pub const A6: RegisterRISCV = RegisterRISCV::X16;
pub const A7: RegisterRISCV = RegisterRISCV::X17;
pub const S2: RegisterRISCV = RegisterRISCV::X18;
pub const S3: RegisterRISCV = RegisterRISCV::X19;
pub const S4: RegisterRISCV = RegisterRISCV::X20;
pub const S5: RegisterRISCV = RegisterRISCV::X21;
pub const S6: RegisterRISCV = RegisterRISCV::X22;
pub const S7: RegisterRISCV = RegisterRISCV::X23;
pub const S8: RegisterRISCV = RegisterRISCV::X24;
pub const S9: RegisterRISCV = RegisterRISCV::X25;
pub const S10: RegisterRISCV = RegisterRISCV::X26;
pub const S11: RegisterRISCV = RegisterRISCV::X27;
pub const T3: RegisterRISCV = RegisterRISCV::X28;
pub const T4: RegisterRISCV = RegisterRISCV::X29;
pub const T5: RegisterRISCV = RegisterRISCV::X30;
pub const T6: RegisterRISCV = RegisterRISCV::X31;
pub const FT0: RegisterRISCV = RegisterRISCV::F0;
pub const FT1: RegisterRISCV = RegisterRISCV::F1;
pub const FT2: RegisterRISCV = RegisterRISCV::F2;
pub const FT3: RegisterRISCV = RegisterRISCV::F3;
pub const FT4: RegisterRISCV = RegisterRISCV::F4;
pub const FT5: RegisterRISCV = RegisterRISCV::F5;
pub const FT6: RegisterRISCV = RegisterRISCV::F6;
pub const FT7: RegisterRISCV = RegisterRISCV::F7;
pub const FS0: RegisterRISCV = RegisterRISCV::F8;
pub const FS1: RegisterRISCV = RegisterRISCV::F9;
pub const FA0: RegisterRISCV = RegisterRISCV::F10;
pub const FA1: RegisterRISCV = RegisterRISCV::F11;
pub const FA2: RegisterRISCV = RegisterRISCV::F12;
pub const FA3: RegisterRISCV = RegisterRISCV::F13;
pub const FA4: RegisterRISCV = RegisterRISCV::F14;
pub const FA5: RegisterRISCV = RegisterRISCV::F15;
pub const FA6: RegisterRISCV = RegisterRISCV::F16;
pub const FA7: RegisterRISCV = RegisterRISCV::F17;
pub const FS2: RegisterRISCV = RegisterRISCV::F18;
pub const FS3: RegisterRISCV = RegisterRISCV::F19;
pub const FS4: RegisterRISCV = RegisterRISCV::F20;
pub const FS5: RegisterRISCV = RegisterRISCV::F21;
pub const FS6: RegisterRISCV = RegisterRISCV::F22;
pub const FS7: RegisterRISCV = RegisterRISCV::F23;
pub const FS8: RegisterRISCV = RegisterRISCV::F24;
pub const FS9: RegisterRISCV = RegisterRISCV::F25;
pub const FS10: RegisterRISCV = RegisterRISCV::F26;
pub const FS11: RegisterRISCV = RegisterRISCV::F27;
pub const FT8: RegisterRISCV = RegisterRISCV::F28;
pub const FT9: RegisterRISCV = RegisterRISCV::F29;
pub const FT10: RegisterRISCV = RegisterRISCV::F30;
pub const FT11: RegisterRISCV = RegisterRISCV::F31;
}

View File

@ -1,3 +1,5 @@
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// SPARC registers
#[repr(C)]
#[derive(PartialEq, Debug, Clone, Copy)]
@ -91,4 +93,13 @@ pub enum RegisterSPARC {
Y = 86,
XCC = 87,
PC = 88,
ENDING = 89,
}
impl RegisterSPARC {
// alias registers
// (assoc) O6 = 84,
// (assoc) I6 = 67,
pub const O6: RegisterSPARC = RegisterSPARC::SP;
pub const I6: RegisterSPARC = RegisterSPARC::FP;
}

View File

@ -1,11 +1,11 @@
#![allow(non_camel_case_types)]
use bitflags::bitflags;
pub const API_MAJOR: u64 = 1;
pub const API_MAJOR: u64 = 2;
pub const API_MINOR: u64 = 0;
pub const VERSION_MAJOR: u64 = 1;
pub const VERSION_MAJOR: u64 = 2;
pub const VERSION_MINOR: u64 = 0;
pub const VERSION_EXTRA: u64 = 2;
pub const VERSION_EXTRA: u64 = 0;
pub const SECOND_SCALE: u64 = 1_000_000;
pub const MILISECOND_SCALE: u64 = 1_000;
@ -93,6 +93,7 @@ pub enum Query {
MODE = 1,
PAGE_SIZE = 2,
ARCH = 3,
TIMEOUT = 4,
}
bitflags! {
@ -124,7 +125,8 @@ pub enum Arch {
PPC = 5,
SPARC = 6,
M68K = 7,
MAX = 8,
RISCV = 8,
MAX = 9,
}
bitflags! {
@ -154,5 +156,7 @@ bitflags! {
const SPARC32 = Self::MIPS32.bits;
const SPARC64 = Self::MIPS64.bits;
const V9 = Self::THUMB.bits;
const RISCV32 = Self::MIPS32.bits;
const RISCV64 = Self::MIPS64.bits;
}
}

View File

@ -1,257 +1,245 @@
#![allow(non_camel_case_types)]
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
// 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,
AH = 1,
AL = 2,
AX = 3,
BH = 4,
BL = 5,
BP = 6,
BPL = 7,
BX = 8,
CH = 9,
CL = 10,
CS = 11,
CX = 12,
DH = 13,
DI = 14,
DIL = 15,
DL = 16,
DS = 17,
DX = 18,
EAX = 19,
EBP = 20,
EBX = 21,
ECX = 22,
EDI = 23,
EDX = 24,
EFLAGS = 25,
EIP = 26,
ES = 27,
ESI = 28,
ESP = 29,
FPSW = 30,
FS = 31,
GS = 32,
IP = 33,
RAX = 34,
RBP = 35,
RBX = 36,
RCX = 37,
RDI = 38,
RDX = 39,
RIP = 40,
RSI = 41,
RSP = 42,
SI = 43,
SIL = 44,
SP = 45,
SPL = 46,
SS = 47,
CR0 = 48,
CR1 = 49,
CR2 = 50,
CR3 = 51,
CR4 = 52,
CR8 = 53,
DR0 = 54,
DR1 = 55,
DR2 = 56,
DR3 = 57,
DR4 = 58,
DR5 = 59,
DR6 = 60,
DR7 = 61,
FP0 = 62,
FP1 = 63,
FP2 = 64,
FP3 = 65,
FP4 = 66,
FP5 = 67,
FP6 = 68,
FP7 = 69,
K0 = 70,
K1 = 71,
K2 = 72,
K3 = 73,
K4 = 74,
K5 = 75,
K6 = 76,
K7 = 77,
MM0 = 78,
MM1 = 79,
MM2 = 80,
MM3 = 81,
MM4 = 82,
MM5 = 83,
MM6 = 84,
MM7 = 85,
R8 = 86,
R9 = 87,
R10 = 88,
R11 = 89,
R12 = 90,
R13 = 91,
R14 = 92,
R15 = 93,
ST0 = 94,
ST1 = 95,
ST2 = 96,
ST3 = 97,
ST4 = 98,
ST5 = 99,
ST6 = 100,
ST7 = 101,
XMM0 = 102,
XMM1 = 103,
XMM2 = 104,
XMM3 = 105,
XMM4 = 106,
XMM5 = 107,
XMM6 = 108,
XMM7 = 109,
XMM8 = 110,
XMM9 = 111,
XMM10 = 112,
XMM11 = 113,
XMM12 = 114,
XMM13 = 115,
XMM14 = 116,
XMM15 = 117,
XMM16 = 118,
XMM17 = 119,
XMM18 = 120,
XMM19 = 121,
XMM20 = 122,
XMM21 = 123,
XMM22 = 124,
XMM23 = 125,
XMM24 = 126,
XMM25 = 127,
XMM26 = 128,
XMM27 = 129,
XMM28 = 130,
XMM29 = 131,
XMM30 = 132,
XMM31 = 133,
YMM0 = 134,
YMM1 = 135,
YMM2 = 136,
YMM3 = 137,
YMM4 = 138,
YMM5 = 139,
YMM6 = 140,
YMM7 = 141,
YMM8 = 142,
YMM9 = 143,
YMM10 = 144,
YMM11 = 145,
YMM12 = 146,
YMM13 = 147,
YMM14 = 148,
YMM15 = 149,
YMM16 = 150,
YMM17 = 151,
YMM18 = 152,
YMM19 = 153,
YMM20 = 154,
YMM21 = 155,
YMM22 = 156,
YMM23 = 157,
YMM24 = 158,
YMM25 = 159,
YMM26 = 160,
YMM27 = 161,
YMM28 = 162,
YMM29 = 163,
YMM30 = 164,
YMM31 = 165,
ZMM0 = 166,
ZMM1 = 167,
ZMM2 = 168,
ZMM3 = 169,
ZMM4 = 170,
ZMM5 = 171,
ZMM6 = 172,
ZMM7 = 173,
ZMM8 = 174,
ZMM9 = 175,
ZMM10 = 176,
ZMM11 = 177,
ZMM12 = 178,
ZMM13 = 179,
ZMM14 = 180,
ZMM15 = 181,
ZMM16 = 182,
ZMM17 = 183,
ZMM18 = 184,
ZMM19 = 185,
ZMM20 = 186,
ZMM21 = 187,
ZMM22 = 188,
ZMM23 = 189,
ZMM24 = 190,
ZMM25 = 191,
ZMM26 = 192,
ZMM27 = 193,
ZMM28 = 194,
ZMM29 = 195,
ZMM30 = 196,
ZMM31 = 197,
R8B = 198,
R9B = 199,
R10B = 200,
R11B = 201,
R12B = 202,
R13B = 203,
R14B = 204,
R15B = 205,
R8D = 206,
R9D = 207,
R10D = 208,
R11D = 209,
R12D = 210,
R13D = 211,
R14D = 212,
R15D = 213,
R8W = 214,
R9W = 215,
R10W = 216,
R11W = 217,
R12W = 218,
R13W = 219,
R14W = 220,
R15W = 221,
IDTR = 222,
GDTR = 223,
LDTR = 224,
TR = 225,
FPCW = 226,
FPTAG = 227,
MSR = 228,
MXCSR = 229,
FS_BASE = 230,
GS_BASE = 231,
FLAGS = 232,
RFLAGS = 233,
ENDING = 234,
}
#[repr(C)]

View File

@ -1,11 +1,9 @@
#![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};
use unicorn_engine::unicorn_const::{uc_error, Arch, HookType, MemType, Mode, Permission, SECOND_SCALE};
use unicorn_engine::{InsnSysX86, RegisterARM, RegisterMIPS, RegisterPPC, RegisterX86};
pub static X86_REGISTERS: [RegisterX86; 145] = [
pub static X86_REGISTERS: [RegisterX86; 125] = [
RegisterX86::AH,
RegisterX86::AL,
RegisterX86::AX,
@ -32,7 +30,6 @@ pub static X86_REGISTERS: [RegisterX86; 145] = [
RegisterX86::EDX,
RegisterX86::EFLAGS,
RegisterX86::EIP,
RegisterX86::EIZ,
RegisterX86::ES,
RegisterX86::ESI,
RegisterX86::ESP,
@ -47,7 +44,6 @@ pub static X86_REGISTERS: [RegisterX86; 145] = [
RegisterX86::RDI,
RegisterX86::RDX,
RegisterX86::RIP,
RegisterX86::RIZ,
RegisterX86::RSI,
RegisterX86::RSP,
RegisterX86::SI,
@ -60,17 +56,7 @@ pub static X86_REGISTERS: [RegisterX86; 145] = [
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,
@ -79,14 +65,6 @@ pub static X86_REGISTERS: [RegisterX86; 145] = [
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,
@ -153,13 +131,13 @@ pub static X86_REGISTERS: [RegisterX86; 145] = [
RegisterX86::R15W,
];
type Unicorn<'a> = unicorn::UnicornHandle<'a>;
type Unicorn<'a> = unicorn_engine::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)
let mut unicorn = unicorn_engine::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(()));
@ -210,7 +188,7 @@ fn x86_code_callback() {
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
let mut unicorn = unicorn_engine::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(()));
@ -241,7 +219,7 @@ fn x86_intr_callback() {
let x86_code32: Vec<u8> = vec![0xcd, 0x80]; // INT 0x80;
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
let mut unicorn = unicorn_engine::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(()));
@ -278,9 +256,15 @@ fn x86_mem_callback() {
let callback_mems = mems_cell.clone();
let callback =
move |_: Unicorn<'_>, mem_type: MemType, address: u64, size: usize, value: i64| {
move |uc: Unicorn<'_>, mem_type: MemType, address: u64, size: usize, value: i64| {
let mut mems = callback_mems.borrow_mut();
let mut uc = uc;
mems.push(MemExpectation(mem_type, address, size, value));
if mem_type == MemType::READ_UNMAPPED {
uc.mem_map(address, 0x1000, Permission::ALL).unwrap();
}
};
// mov eax, 0xdeadbeef;
@ -290,7 +274,7 @@ fn x86_mem_callback() {
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)
let mut unicorn = unicorn_engine::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(()));
@ -307,7 +291,7 @@ fn x86_mem_callback() {
10 * SECOND_SCALE,
0x1000
),
Err(uc_error::READ_UNMAPPED)
Ok(())
);
assert_eq!(expects, *mems_cell.borrow());
@ -328,7 +312,7 @@ fn x86_insn_in_callback() {
let x86_code32: Vec<u8> = vec![0xe5, 0x10]; // IN eax, 0x10;
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
let mut unicorn = unicorn_engine::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(()));
@ -365,7 +349,7 @@ fn x86_insn_out_callback() {
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)
let mut unicorn = unicorn_engine::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(()));
@ -407,7 +391,7 @@ fn x86_insn_sys_callback() {
0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x05,
];
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_64)
let mut unicorn = unicorn_engine::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(()));
@ -434,7 +418,7 @@ fn x86_insn_sys_callback() {
fn emulate_arm() {
let arm_code32: Vec<u8> = vec![0x83, 0xb0]; // sub sp, #0xc
let mut unicorn = unicorn::Unicorn::new(Arch::ARM, Mode::THUMB)
let mut unicorn = unicorn_engine::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(()));
@ -475,7 +459,7 @@ fn emulate_arm() {
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)
let mut unicorn = unicorn_engine::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(()));
@ -501,7 +485,7 @@ fn emulate_mips() {
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)
let mut unicorn = unicorn_engine::Unicorn::new(Arch::PPC, Mode::PPC32 | Mode::BIG_ENDIAN)
.expect("failed to initialize unicorn instance");
let mut emu = unicorn.borrow();
assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(()));
@ -526,7 +510,7 @@ fn emulate_ppc() {
#[test]
fn mem_unmapping() {
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
let mut unicorn = unicorn_engine::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(()));
@ -539,7 +523,7 @@ fn mem_map_ptr() {
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)
let mut unicorn = unicorn_engine::Unicorn::new(Arch::X86, Mode::MODE_32)
.expect("failed to initialize unicorn instance");
let mut emu = unicorn.borrow();
@ -619,7 +603,7 @@ fn x86_context_save_and_restore() {
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");
unicorn_engine::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(()));
@ -636,7 +620,7 @@ fn x86_context_save_and_restore() {
/* 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");
unicorn_engine::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() {
@ -653,7 +637,7 @@ fn x86_context_save_and_restore() {
fn x86_block_callback() {
#[derive(PartialEq, Debug)]
struct BlockExpectation(u64, u32);
let expects = vec![BlockExpectation(0x1000, 2), BlockExpectation(0x1000, 2)];
let expects = vec![BlockExpectation(0x1000, 2)];
let blocks: Vec<BlockExpectation> = Vec::new();
let blocks_cell = Rc::new(RefCell::new(blocks));
@ -665,7 +649,7 @@ fn x86_block_callback() {
let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx
let mut unicorn = unicorn::Unicorn::new(Arch::X86, Mode::MODE_32)
let mut unicorn = unicorn_engine::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(()));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -12,6 +12,6 @@ Documention of Unicorn engine.
http://unicorn-engine.org/docs/beyond_qemu.html
* Micro Uncorn-Engine API Documentation in Chinese
* Uncorn-Engine Documentation
https://github.com/kabeor/Micro-Unicorn-Engine-API-Documentation
https://github.com/kabeor/Unicorn-Engine-Documentation

@ -0,0 +1 @@
Subproject commit e1111e1b8b253bf7292ad911f43c125808a95f1e

View File

@ -2018,9 +2018,13 @@ enum {
PPC_MEM_TLBIA = 0x0000000010000000ULL,
PPC_MEM_TLBIE = 0x0000000020000000ULL,
PPC_MEM_TLBSYNC = 0x0000000040000000ULL,
// The enum in msvc is 32bit **signed**.
// https://godbolt.org/z/nYbvWPWET
#ifndef _MSC_VER
/* sync instruction */
PPC_MEM_SYNC = 0x0000000080000000ULL,
#ifndef _MSC_VER
/* eieio instruction */
PPC_MEM_EIEIO = 0x0000000100000000ULL,
@ -2084,6 +2088,7 @@ enum {
/* popcntw and popcntd instructions */
PPC_POPCNTWD = 0x8000000000000000ULL,
#else
#define PPC_MEM_SYNC 0x0000000080000000ULL
#define PPC_MEM_EIEIO 0x0000000100000000ULL
#define PPC_CACHE 0x0000000200000000ULL
#define PPC_CACHE_ICBI 0x0000000400000000ULL

View File

@ -3,6 +3,34 @@
const uint64_t code_start = 0x1000;
const uint64_t code_len = 0x4000;
static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) {
OK(uc_open(arch, mode, uc));
OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL));
OK(uc_mem_write(*uc, code_start, code, size));
}
static void test_ppc32_add() {
uc_engine* uc;
char code[] = "\x7f\x46\x1a\x14"; // ADD 26, 6, 3
int reg;
uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1);
reg = 42;
OK(uc_reg_write(uc, UC_PPC_REG_3, &reg));
reg = 1337;
OK(uc_reg_write(uc, UC_PPC_REG_6, &reg));
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
OK(uc_reg_read(uc, UC_PPC_REG_26, &reg));
TEST_CHECK(reg == 1379);
OK(uc_close(uc));
}
TEST_LIST = {
{ NULL, NULL }
{ "test_ppc32_add", test_ppc32_add },
{ NULL, NULL}
};