Compare commits
110 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
66df39ebc9 | ||
|
1e457ecc66 | ||
|
b2f253d732 | ||
|
fb667f5cdc | ||
|
19f8991cbb | ||
|
473405797d | ||
|
848d52033e | ||
|
3f56323fef | ||
|
b22d4cfbb2 | ||
|
0f0bf3ed83 | ||
|
acc0d6cc9b | ||
|
3db98ac1be | ||
|
cae6f80e5e | ||
|
ac30245e18 | ||
|
961fed7b11 | ||
|
e0c89b7f2c | ||
|
38ddaf585f | ||
|
036306579a | ||
|
5a6344b8d8 | ||
|
297a78990d | ||
|
5b3a27721e | ||
|
6b091b755a | ||
|
8ce974b519 | ||
|
d685bedac4 | ||
|
6b457f23ba | ||
|
07958cd846 | ||
|
e120cd03b4 | ||
|
db01ecd4be | ||
|
f275ac6a9b | ||
|
b5917989b3 | ||
|
cfaa329d36 | ||
|
33bd9eadae | ||
|
ac05215a9c | ||
|
f3b1d9fd20 | ||
|
d531096586 | ||
|
b6b92391d6 | ||
|
c25c9d6be0 | ||
|
b0c74bbee2 | ||
|
1ee37cc026 | ||
|
84c6f0d82f | ||
|
df8237175f | ||
|
68f2bdc641 | ||
|
09d42b408a | ||
|
5605522d15 | ||
|
411648eb0c | ||
|
c09adf5b7b | ||
|
a8f724010b | ||
|
6fc4fc41ec | ||
|
a51715734a | ||
|
4ba2b30d18 | ||
|
37e325643b | ||
|
cc586bdba6 | ||
|
7bd93c0d74 | ||
|
b33c0afa63 | ||
|
991d2432b3 | ||
|
42bc8b1768 | ||
|
a23ce3c27f | ||
|
0cfe8b9bad | ||
|
d3e55b1c2d | ||
|
fdb6494934 | ||
|
1a68ae656f | ||
|
b27af3398d | ||
|
7292e5d6e4 | ||
|
eeb6208fb3 | ||
|
857b155bb8 | ||
|
c5bae30b1d | ||
|
b69126612d | ||
|
e33fcc2f30 | ||
|
9bfa40184c | ||
|
10cac9d34e | ||
|
b4894ce43e | ||
|
1b4fb66138 | ||
|
132d97dfea | ||
|
f77bdb3c7e | ||
|
90ed828e90 | ||
|
8cbbf3df42 | ||
|
ad1d9156f3 | ||
|
02047d7645 | ||
|
d5d513d9f1 | ||
|
17e7c80eba | ||
|
5b25f3f53e | ||
|
7e66419c03 | ||
|
0e8b6a8bba | ||
|
63cb1cdd58 | ||
|
e55b25c744 | ||
|
a5ab143189 | ||
|
fd44c670cb | ||
|
5c55aa2d56 | ||
|
b3da5d0761 | ||
|
425efda77e | ||
|
65188be06f | ||
|
c12934a770 | ||
|
ea26926b60 | ||
|
7e413d2fcf | ||
|
92ecc28491 | ||
|
a5bc710d08 | ||
|
279483ec29 | ||
|
76a3ebdc03 | ||
|
bdbba45dcf | ||
|
1ec0c0a769 | ||
|
a6c9b41c68 | ||
|
c316b866ec | ||
|
8a30e1ac0d | ||
|
93fc10de8d | ||
|
d2c8d152ba | ||
|
ef1fffccfe | ||
|
fe559ea3b1 | ||
|
f37568c186 | ||
|
b3891003fe | ||
|
7ef4460c3a |
4
.gitignore
vendored
4
.gitignore
vendored
@ -12,8 +12,6 @@
|
||||
*.jar
|
||||
*~
|
||||
|
||||
qemu/config-all-devices.mak
|
||||
|
||||
qemu/aarch64-softmmu/
|
||||
qemu/aarch64eb-softmmu/
|
||||
qemu/arm-softmmu/
|
||||
@ -67,6 +65,8 @@ 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
|
||||
|
||||
|
||||
|
125
CMakeLists.txt
125
CMakeLists.txt
@ -19,13 +19,13 @@ project(unicorn C)
|
||||
|
||||
set(UNICORN_VERSION_MAJOR 1)
|
||||
set(UNICORN_VERSION_MINOR 0)
|
||||
set(UNICORN_VERSION_PATCH 2)
|
||||
set(UNICORN_VERSION_PATCH 3)
|
||||
|
||||
option(UNICORN_BUILD_SHARED "Build shared instead of static library" ON)
|
||||
|
||||
if (NOT UNICORN_ARCH)
|
||||
# build all architectures
|
||||
set(UNICORN_ARCH "x86 arm aarch64 m68k mips sparc")
|
||||
set(UNICORN_ARCH "x86 arm aarch64 m68k mips sparc ppc")
|
||||
endif()
|
||||
|
||||
string(TOUPPER ${UNICORN_ARCH} UNICORN_ARCH)
|
||||
@ -159,6 +159,9 @@ else()
|
||||
if (UNICORN_HAS_SPARC)
|
||||
set (EXTRA_CFLAGS "${EXTRA_CFLAGS}-DUNICORN_HAS_SPARC ")
|
||||
endif()
|
||||
if (UNICORN_HAS_PPC)
|
||||
set (EXTRA_CFLAGS "${EXTRA_CFLAGS}-DUNICORN_HAS_PPC ")
|
||||
endif()
|
||||
set (EXTRA_CFLAGS "${EXTRA_CFLAGS}-fPIC -fvisibility=hidden")
|
||||
|
||||
set(TARGET_LIST "--target-list=")
|
||||
@ -180,6 +183,9 @@ else()
|
||||
if (UNICORN_HAS_SPARC)
|
||||
set (TARGET_LIST "${TARGET_LIST}sparc-softmmu, sparc64-softmmu, ")
|
||||
endif()
|
||||
if (UNICORN_HAS_PPC)
|
||||
set (TARGET_LIST "${TARGET_LIST}ppc-softmmu, ")
|
||||
endif()
|
||||
set (TARGET_LIST "${TARGET_LIST} ")
|
||||
|
||||
# GEN config-host.mak & target directories
|
||||
@ -252,6 +258,12 @@ else()
|
||||
OUTPUT_FILE ${CMAKE_BINARY_DIR}/sparc64-softmmu/config-target.h
|
||||
)
|
||||
endif()
|
||||
if (UNICORN_HAS_PPC)
|
||||
execute_process(COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/qemu/scripts/create_config
|
||||
INPUT_FILE ${CMAKE_BINARY_DIR}/ppc-softmmu/config-target.mak
|
||||
OUTPUT_FILE ${CMAKE_BINARY_DIR}/ppc-softmmu/config-target.h
|
||||
)
|
||||
endif()
|
||||
add_compile_options(
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/tcg/${UNICORN_TARGET_ARCH}
|
||||
-D_GNU_SOURCE
|
||||
@ -270,9 +282,6 @@ add_library(x86_64-softmmu
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/i386/pc.c
|
||||
qemu/hw/i386/pc_piix.c
|
||||
qemu/hw/intc/apic.c
|
||||
qemu/hw/intc/apic_common.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -322,8 +331,6 @@ add_library(arm-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/arm/tosa.c
|
||||
qemu/hw/arm/virt.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -366,8 +373,6 @@ add_library(armeb-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/arm/tosa.c
|
||||
qemu/hw/arm/virt.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -412,8 +417,6 @@ add_library(aarch64-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/arm/tosa.c
|
||||
qemu/hw/arm/virt.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -459,8 +462,6 @@ add_library(aarch64eb-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/arm/tosa.c
|
||||
qemu/hw/arm/virt.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -508,7 +509,6 @@ add_library(m68k-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/m68k/dummy_m68k.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -549,9 +549,7 @@ add_library(mips-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/mips/addr.c
|
||||
qemu/hw/mips/cputimer.c
|
||||
qemu/hw/mips/mips_r4k.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -593,9 +591,7 @@ add_library(mipsel-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/mips/addr.c
|
||||
qemu/hw/mips/cputimer.c
|
||||
qemu/hw/mips/mips_r4k.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -637,9 +633,7 @@ add_library(mips64-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/mips/addr.c
|
||||
qemu/hw/mips/cputimer.c
|
||||
qemu/hw/mips/mips_r4k.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -681,9 +675,7 @@ add_library(mips64el-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/mips/addr.c
|
||||
qemu/hw/mips/cputimer.c
|
||||
qemu/hw/mips/mips_r4k.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -727,7 +719,6 @@ add_library(sparc-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/sparc/leon3.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -771,7 +762,6 @@ add_library(sparc64-softmmu
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/sparc64/sun4u.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
@ -811,40 +801,75 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_PPC)
|
||||
add_library(ppc-softmmu
|
||||
qemu/cpu-exec.c
|
||||
qemu/cpus.c
|
||||
qemu/cputlb.c
|
||||
qemu/exec.c
|
||||
qemu/fpu/softfloat.c
|
||||
qemu/hw/ppc/ppc.c
|
||||
qemu/hw/ppc/ppc_booke.c
|
||||
qemu/libdecnumber/decContext.c
|
||||
qemu/libdecnumber/decNumber.c
|
||||
qemu/libdecnumber/dpd/decimal128.c
|
||||
qemu/libdecnumber/dpd/decimal32.c
|
||||
qemu/libdecnumber/dpd/decimal64.c
|
||||
qemu/ioport.c
|
||||
qemu/memory.c
|
||||
qemu/memory_mapping.c
|
||||
qemu/target-ppc/cpu-models.c
|
||||
qemu/target-ppc/mmu_helper.c
|
||||
qemu/target-ppc/mmu-hash32.c
|
||||
qemu/target-ppc/dfp_helper.c
|
||||
qemu/target-ppc/excp_helper.c
|
||||
qemu/target-ppc/fpu_helper.c
|
||||
qemu/target-ppc/int_helper.c
|
||||
qemu/target-ppc/timebase_helper.c
|
||||
qemu/target-ppc/misc_helper.c
|
||||
qemu/target-ppc/mem_helper.c
|
||||
qemu/target-ppc/translate.c
|
||||
qemu/target-ppc/unicorn.c
|
||||
qemu/tcg/optimize.c
|
||||
qemu/tcg/tcg.c
|
||||
qemu/translate-all.c
|
||||
)
|
||||
if (NOT UNICORN_BUILD_SHARED)
|
||||
target_link_libraries(ppc-softmmu unicorn)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
target_compile_options(ppc-softmmu PRIVATE
|
||||
-DNEED_CPU_H
|
||||
/FIppc.h
|
||||
/I${CMAKE_CURRENT_SOURCE_DIR}/msvc/unicorn/ppc-softmmu
|
||||
/I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target-ppc
|
||||
)
|
||||
else()
|
||||
target_compile_options(ppc-softmmu PRIVATE
|
||||
-DNEED_CPU_H
|
||||
-include ppc.h
|
||||
-I${CMAKE_BINARY_DIR}/ppc-softmmu
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target-ppc
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
set(UNICORN_SRCS_COMMON
|
||||
list.c
|
||||
qemu/accel.c
|
||||
qemu/glib_compat.c
|
||||
qemu/hw/core/machine.c
|
||||
qemu/hw/core/qdev.c
|
||||
qemu/qapi/qapi-dealloc-visitor.c
|
||||
qemu/qapi/qapi-visit-core.c
|
||||
qemu/qapi/qmp-input-visitor.c
|
||||
qemu/qapi/qmp-output-visitor.c
|
||||
qemu/qapi/string-input-visitor.c
|
||||
qemu/qemu-log.c
|
||||
qemu/qemu-timer.c
|
||||
qemu/qobject/qbool.c
|
||||
qemu/qobject/qdict.c
|
||||
qemu/qobject/qerror.c
|
||||
qemu/qobject/qfloat.c
|
||||
qemu/qobject/qint.c
|
||||
qemu/qobject/qlist.c
|
||||
qemu/qobject/qstring.c
|
||||
qemu/qom/container.c
|
||||
qemu/qom/cpu.c
|
||||
qemu/qom/object.c
|
||||
qemu/qom/qom-qobject.c
|
||||
qemu/tcg-runtime.c
|
||||
qemu/util/aes.c
|
||||
qemu/util/bitmap.c
|
||||
qemu/util/bitops.c
|
||||
qemu/util/crc32c.c
|
||||
qemu/util/cutils.c
|
||||
qemu/util/error.c
|
||||
qemu/util/getauxval.c
|
||||
qemu/util/host-utils.c
|
||||
qemu/util/module.c
|
||||
qemu/util/qemu-timer-common.c
|
||||
qemu/vl.c
|
||||
uc.c
|
||||
@ -855,9 +880,6 @@ if (MSVC)
|
||||
${UNICORN_SRCS_COMMON}
|
||||
qemu/util/oslib-win32.c
|
||||
qemu/util/qemu-thread-win32.c
|
||||
qemu/util/qemu-error.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/msvc/unicorn/qapi-types.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/msvc/unicorn/qapi-visit.c
|
||||
)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
enable_language(ASM_MASM)
|
||||
@ -868,8 +890,6 @@ else()
|
||||
${UNICORN_SRCS_COMMON}
|
||||
qemu/util/oslib-posix.c
|
||||
qemu/util/qemu-thread-posix.c
|
||||
qemu/qapi-types.c
|
||||
qemu/qapi-visit.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -889,7 +909,7 @@ if (UNICORN_HAS_X86)
|
||||
set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_x86 sample_x86_32_gdt_and_seg_regs sample_batch_reg mem_apis shellcode)
|
||||
endif()
|
||||
if (UNICORN_HAS_ARM)
|
||||
set(UNICORN_COMPILE_OPTIONS ${UNICORN_COMPILE_OPTIONS} -DUNICORN_HAS_ARM)
|
||||
set(UNICORN_COMPILE_OPTIONS ${UNICORN_COMPILE_OPTIONS} -DUNICORN_HAS_ARM -DUNICORN_HAS_ARMEB)
|
||||
set(UNICORN_LINK_LIBRARIES ${UNICORN_LINK_LIBRARIES} arm-softmmu armeb-softmmu)
|
||||
set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_arm sample_armeb)
|
||||
endif()
|
||||
@ -913,6 +933,11 @@ if (UNICORN_HAS_SPARC)
|
||||
set(UNICORN_LINK_LIBRARIES ${UNICORN_LINK_LIBRARIES} sparc-softmmu sparc64-softmmu)
|
||||
set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_sparc)
|
||||
endif()
|
||||
if (UNICORN_HAS_PPC)
|
||||
set(UNICORN_COMPILE_OPTIONS ${UNICORN_COMPILE_OPTIONS} -DUNICORN_HAS_PPC)
|
||||
set(UNICORN_LINK_LIBRARIES ${UNICORN_LINK_LIBRARIES} ppc-softmmu)
|
||||
set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_ppc)
|
||||
endif()
|
||||
|
||||
target_compile_options(unicorn PRIVATE
|
||||
${UNICORN_COMPILE_OPTIONS}
|
||||
|
@ -72,4 +72,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.
|
||||
|
33
Makefile
33
Makefile
@ -18,7 +18,7 @@ UNAME_S := $(shell uname -s)
|
||||
SMP_MFLAGS := -j4
|
||||
|
||||
UC_GET_OBJ = $(shell for i in \
|
||||
$$(grep '$(1)' $(2) | \
|
||||
$$(grep '$(1)' $(2) | sed '/^\#/d' | \
|
||||
grep '\.o' | cut -d '=' -f 2); do \
|
||||
echo $$i | grep '\.o' > /dev/null 2>&1; \
|
||||
if [ $$? = 0 ]; then \
|
||||
@ -26,9 +26,6 @@ UC_GET_OBJ = $(shell for i in \
|
||||
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)),)
|
||||
@ -39,25 +36,19 @@ 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_M68K = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/m68k-softmmu/)
|
||||
UC_TARGET_OBJ_M68K += $(call UC_GET_OBJ,obj-,qemu/target-m68k/Makefile.objs, qemu/m68k-softmmu/target-m68k/)
|
||||
|
||||
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))
|
||||
@ -73,15 +64,17 @@ UC_TARGET_OBJ_MIPS64 = $(subst /mips-softmmu/,/mips64-softmmu/,$(UC_TARGET_OBJ_M
|
||||
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/)
|
||||
|
||||
UC_TARGET_OBJ_PPC = $(call UC_GET_OBJ,obj-,qemu/Makefile.target, qemu/ppc-softmmu/)
|
||||
UC_TARGET_OBJ_PPC += $(call UC_GET_OBJ,obj-,qemu/hw/ppc/Makefile.objs, qemu/ppc-softmmu/hw/ppc/)
|
||||
UC_TARGET_OBJ_PPC += $(call UC_GET_OBJ,obj-y,qemu/target-ppc/Makefile.objs, qemu/ppc-softmmu/target-ppc/)
|
||||
|
||||
ifneq (,$(findstring x86,$(UNICORN_ARCHS)))
|
||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_X86)
|
||||
UNICORN_CFLAGS += -DUNICORN_HAS_X86
|
||||
@ -122,6 +115,14 @@ ifneq (,$(findstring mips,$(UNICORN_ARCHS)))
|
||||
UNICORN_TARGETS += mips64-softmmu,
|
||||
UNICORN_TARGETS += mips64el-softmmu,
|
||||
endif
|
||||
ifneq (,$(findstring ppc,$(UNICORN_ARCHS)))
|
||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_PPC)
|
||||
# UC_TARGET_OBJ += $(call GENOBJ,ppc64-softmmu)
|
||||
UNICORN_CFLAGS += -DUNICORN_HAS_PPC
|
||||
# UNICORN_CFLAGS += -DUNICORN_HAS_PPC64
|
||||
UNICORN_TARGETS += ppc-softmmu,
|
||||
# UNICORN_TARGETS += ppc64-softmmu,
|
||||
endif
|
||||
ifneq (,$(findstring sparc,$(UNICORN_ARCHS)))
|
||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_SPARC)
|
||||
UC_TARGET_OBJ += $(UC_TARGET_OBJ_SPARC64)
|
||||
@ -386,7 +387,7 @@ dist:
|
||||
# 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)
|
||||
sparc sparc64 x86_64 ppc)
|
||||
$(foreach var,$(TARGETS),\
|
||||
$(shell python qemu/header_gen.py $(var) > qemu/$(var).h;))
|
||||
@echo "Generated headers for $(TARGETS)."
|
||||
|
@ -11,7 +11,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, 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,4 +1,4 @@
|
||||
This directory contains bindings & test code for Python, Java, Go and .NET.
|
||||
This directory contains bindings & test code for Python, Java, Go, .NET and Rust.
|
||||
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,13 +10,14 @@ 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)
|
||||
- Unicorn-Rs: Rust binding (by Sébastien Duquette, unmaintained)
|
||||
https://github.com/ekse/unicorn-rs
|
||||
|
||||
- UnicornEngine: Perl binding (by Vikas Naresh Kumar)
|
||||
|
@ -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', 'unicorn.h' ]
|
||||
|
||||
template = {
|
||||
'python': {
|
||||
@ -21,6 +21,7 @@ template = {
|
||||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '#',
|
||||
'comment_close': '',
|
||||
@ -37,6 +38,7 @@ template = {
|
||||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '#',
|
||||
'comment_close': '',
|
||||
@ -53,6 +55,7 @@ template = {
|
||||
'x86.h': 'x86',
|
||||
'sparc.h': 'sparc',
|
||||
'm68k.h': 'm68k',
|
||||
'ppc.h': 'ppc',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
@ -69,6 +72,7 @@ template = {
|
||||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'ppc',
|
||||
'unicorn.h': 'Unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
@ -85,6 +89,7 @@ template = {
|
||||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'ppc',
|
||||
'unicorn.h': 'Common',
|
||||
'comment_open': ' //',
|
||||
'comment_close': '',
|
||||
@ -101,6 +106,7 @@ template = {
|
||||
'x86.h': 'X86',
|
||||
'sparc.h': 'Sparc',
|
||||
'm68k.h': 'M68k',
|
||||
'ppc.h': 'ppc',
|
||||
'unicorn.h': 'Unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
|
@ -12,7 +12,7 @@ module Common =
|
||||
let UC_VERSION_MAJOR = 1
|
||||
|
||||
let UC_VERSION_MINOR = 0
|
||||
let UC_VERSION_EXTRA = 2
|
||||
let UC_VERSION_EXTRA = 3
|
||||
let UC_SECOND_SCALE = 1000000
|
||||
let UC_MILISECOND_SCALE = 1000
|
||||
let UC_ARCH_ARM = 1
|
||||
|
48
bindings/dotnet/UnicornManaged/Const/ppc.fs
Normal file
48
bindings/dotnet/UnicornManaged/Const/ppc.fs
Normal file
@ -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
|
||||
|
43
bindings/go/unicorn/ppc_const.go
Normal file
43
bindings/go/unicorn/ppc_const.go
Normal file
@ -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
|
||||
)
|
@ -7,7 +7,7 @@ const (
|
||||
VERSION_MAJOR = 1
|
||||
|
||||
VERSION_MINOR = 0
|
||||
VERSION_EXTRA = 2
|
||||
VERSION_EXTRA = 3
|
||||
SECOND_SCALE = 1000000
|
||||
MILISECOND_SCALE = 1000
|
||||
ARCH_ARM = 1
|
||||
|
@ -9,7 +9,7 @@ public interface UnicornConst {
|
||||
public static final int UC_VERSION_MAJOR = 1;
|
||||
|
||||
public static final int UC_VERSION_MINOR = 0;
|
||||
public static final int UC_VERSION_EXTRA = 2;
|
||||
public static final int UC_VERSION_EXTRA = 3;
|
||||
public static final int UC_SECOND_SCALE = 1000000;
|
||||
public static final int UC_MILISECOND_SCALE = 1000;
|
||||
public static final int UC_ARCH_ARM = 1;
|
||||
|
46
bindings/java/unicorn/ppcConst.java
Normal file
46
bindings/java/unicorn/ppcConst.java
Normal file
@ -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;
|
||||
|
||||
}
|
@ -10,7 +10,7 @@ const UC_API_MAJOR = 1;
|
||||
UC_VERSION_MAJOR = 1;
|
||||
|
||||
UC_VERSION_MINOR = 0;
|
||||
UC_VERSION_EXTRA = 2;
|
||||
UC_VERSION_EXTRA = 3;
|
||||
UC_SECOND_SCALE = 1000000;
|
||||
UC_MILISECOND_SCALE = 1000;
|
||||
UC_ARCH_ARM = 1;
|
||||
|
48
bindings/pascal/unicorn/ppcConst.pas
Normal file
48
bindings/pascal/unicorn/ppcConst.pas
Normal file
@ -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.
|
65
bindings/python/sample_ppc.py
Executable file
65
bindings/python/sample_ppc.py
Executable file
@ -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()
|
||||
|
@ -264,6 +264,24 @@ Unicorn offers some unparalleled features:
|
||||
Further information is available at https://www.unicorn-engine.org
|
||||
'''
|
||||
|
||||
long_desc = '''
|
||||
Unicorn is a lightweight, multi-platform, multi-architecture CPU emulator framework
|
||||
based on [QEMU](http://qemu.org).
|
||||
|
||||
Unicorn offers some unparalleled features:
|
||||
|
||||
- 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)
|
||||
- High performance via Just-In-Time compilation
|
||||
- Support for fine-grained instrumentation at various levels
|
||||
- Thread-safety by design
|
||||
- Distributed under free software license GPLv2
|
||||
|
||||
Further information is available at http://www.unicorn-engine.org
|
||||
'''
|
||||
|
||||
setup(
|
||||
provides=['unicorn'],
|
||||
packages=['unicorn'],
|
||||
|
40
bindings/python/unicorn/ppc_const.py
Normal file
40
bindings/python/unicorn/ppc_const.py
Normal file
@ -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
|
@ -5,7 +5,7 @@ UC_API_MINOR = 0
|
||||
UC_VERSION_MAJOR = 1
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_EXTRA = 2
|
||||
UC_VERSION_EXTRA = 3
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
|
43
bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb
Normal file
43
bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb
Normal file
@ -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
|
@ -7,7 +7,7 @@ module UnicornEngine
|
||||
UC_VERSION_MAJOR = 1
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_EXTRA = 2
|
||||
UC_VERSION_EXTRA = 3
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
|
339
bindings/rust/COPYING
Normal file
339
bindings/rust/COPYING
Normal file
@ -0,0 +1,339 @@
|
||||
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.
|
27
bindings/rust/Cargo.toml
Normal file
27
bindings/rust/Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
||||
[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"
|
49
bindings/rust/README.md
Normal file
49
bindings/rust/README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# 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, 0).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```.
|
||||
|
||||
In addition, the bindings offer some basic utility functionalities, such as
|
||||
a simple heap allocator utilizing Unicorn hooks for sanitization or easily accessible debug prints.
|
||||
These are WIP and only tested in ARM LITTLE_ENDIAN mode.
|
||||
|
||||
## 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.
|
||||
|
20
bindings/rust/build.rs
Normal file
20
bindings/rust/build.rs
Normal file
@ -0,0 +1,20 @@
|
||||
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");
|
||||
}
|
146
bindings/rust/src/arm.rs
Normal file
146
bindings/rust/src/arm.rs
Normal file
@ -0,0 +1,146 @@
|
||||
#![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;
|
||||
}
|
268
bindings/rust/src/arm64.rs
Normal file
268
bindings/rust/src/arm64.rs
Normal file
@ -0,0 +1,268 @@
|
||||
// ARM64 registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterARM64 {
|
||||
INVALID = 0,
|
||||
FP = 1,
|
||||
LR = 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,
|
||||
IP1 = 215,
|
||||
IP0 = 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,
|
||||
}
|
230
bindings/rust/src/ffi.rs
Normal file
230
bindings/rust/src/ffi.rs
Normal file
@ -0,0 +1,230 @@
|
||||
#![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_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<D> {
|
||||
pub unicorn: *mut crate::UnicornInner<D>,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle<D>, u64, u32)>,
|
||||
}
|
||||
|
||||
pub struct BlockHook<D> {
|
||||
pub unicorn: *mut crate::UnicornInner<D>,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle<D>, u64, u32)>,
|
||||
}
|
||||
|
||||
pub struct MemHook<D> {
|
||||
pub unicorn: *mut crate::UnicornInner<D>,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle<D>, MemType, u64, usize, i64)>,
|
||||
}
|
||||
|
||||
pub struct InterruptHook<D> {
|
||||
pub unicorn: *mut crate::UnicornInner<D>,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle<D>, u32)>,
|
||||
}
|
||||
|
||||
pub struct InstructionInHook<D> {
|
||||
pub unicorn: *mut crate::UnicornInner<D>,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle<D>, u32, usize)>,
|
||||
}
|
||||
|
||||
pub struct InstructionOutHook<D> {
|
||||
pub unicorn: *mut crate::UnicornInner<D>,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle<D>, u32, usize, u32)>,
|
||||
}
|
||||
|
||||
pub struct InstructionSysHook<D> {
|
||||
pub unicorn: *mut crate::UnicornInner<D>,
|
||||
pub callback: Box<dyn FnMut(crate::UnicornHandle<D>)>,
|
||||
}
|
||||
|
||||
pub extern "C" fn code_hook_proxy<D>(
|
||||
uc: uc_handle,
|
||||
address: u64,
|
||||
size: u32,
|
||||
user_data: *mut CodeHook<D>,
|
||||
) {
|
||||
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<D>(
|
||||
uc: uc_handle,
|
||||
address: u64,
|
||||
size: u32,
|
||||
user_data: *mut BlockHook<D>,
|
||||
) {
|
||||
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<D>(
|
||||
uc: uc_handle,
|
||||
mem_type: MemType,
|
||||
address: u64,
|
||||
size: u32,
|
||||
value: i64,
|
||||
user_data: *mut MemHook<D>,
|
||||
) {
|
||||
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<D>(uc: uc_handle, value: u32, user_data: *mut InterruptHook<D>) {
|
||||
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<D>(
|
||||
uc: uc_handle,
|
||||
port: u32,
|
||||
size: usize,
|
||||
user_data: *mut InstructionInHook<D>,
|
||||
) {
|
||||
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<D>(
|
||||
uc: uc_handle,
|
||||
port: u32,
|
||||
size: usize,
|
||||
value: u32,
|
||||
user_data: *mut InstructionOutHook<D>,
|
||||
) {
|
||||
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<D>(uc: uc_handle, user_data: *mut InstructionSysHook<D>) {
|
||||
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) },
|
||||
});
|
||||
}
|
804
bindings/rust/src/lib.rs
Normal file
804
bindings/rust/src/lib.rs
Normal file
@ -0,0 +1,804 @@
|
||||
//! 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, 0).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;
|
||||
pub mod utils;
|
||||
|
||||
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_free(self.context) };
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// A Unicorn emulator instance.
|
||||
pub struct Unicorn<D> {
|
||||
inner: Pin<Box<UnicornInner<D>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Handle used to safely access exposed functions and data of a Unicorn instance.
|
||||
pub struct UnicornHandle<'a, D> {
|
||||
inner: Pin<&'a mut UnicornInner<D>>,
|
||||
}
|
||||
|
||||
/// Internal Management struct
|
||||
pub struct UnicornInner<D> {
|
||||
pub uc: uc_handle,
|
||||
pub arch: Arch,
|
||||
pub code_hooks: HashMap<*mut libc::c_void, Box<ffi::CodeHook<D>>>,
|
||||
pub block_hooks: HashMap<*mut libc::c_void, Box<ffi::BlockHook<D>>>,
|
||||
pub mem_hooks: HashMap<*mut libc::c_void, Box<ffi::MemHook<D>>>,
|
||||
pub intr_hooks: HashMap<*mut libc::c_void, Box<ffi::InterruptHook<D>>>,
|
||||
pub insn_in_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionInHook<D>>>,
|
||||
pub insn_out_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionOutHook<D>>>,
|
||||
pub insn_sys_hooks: HashMap<*mut libc::c_void, Box<ffi::InstructionSysHook<D>>>,
|
||||
pub data: D,
|
||||
_pin: PhantomPinned,
|
||||
}
|
||||
|
||||
impl<D> Unicorn<D> {
|
||||
/// Create a new instance of the unicorn engine for the specified architecture
|
||||
/// and hardware mode.
|
||||
pub fn new(arch: Arch, mode: Mode, data: D) -> Result<Unicorn<D>, 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(),
|
||||
data: data,
|
||||
_pin: std::marker::PhantomPinned,
|
||||
}),
|
||||
})
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow<'a>(&'a mut self) -> UnicornHandle<'a, D> {
|
||||
UnicornHandle {
|
||||
inner: self.inner.as_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> Drop for Unicorn<D> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::uc_close(self.inner.uc) };
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> UnicornInner<D> {
|
||||
pub fn get_data(self: Pin<&mut Self>) -> &mut D {
|
||||
unsafe { &mut self.get_unchecked_mut().data }
|
||||
}
|
||||
}
|
||||
impl<D> std::fmt::Debug for UnicornInner<D> {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(formatter, "Unicorn {{ uc: {:p} }}", self.uc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, D> UnicornHandle<'a, D> {
|
||||
/// Return whatever data was passed during initialization.
|
||||
///
|
||||
/// For an example, have a look at utils::init_emu_with_heap where
|
||||
/// a struct is passed which is used for a custom allocator.
|
||||
pub fn get_data(&self) -> &D {
|
||||
&self.inner.data
|
||||
}
|
||||
|
||||
/// Return a mutable reference to whatever data was passed during initialization.
|
||||
pub fn get_data_mut(&mut self) -> &mut D {
|
||||
unsafe { &mut self.inner.as_mut().get_unchecked_mut().data }
|
||||
}
|
||||
|
||||
/// 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<D>, 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::<D> 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<D>, 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::<D> 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<D>, 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::<D> 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<D>, 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::<D> 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<D>, 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::<D> 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<D>, 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::<D> 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<D>),
|
||||
{
|
||||
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::<D> 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_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)
|
||||
}
|
||||
}
|
||||
}
|
24
bindings/rust/src/m68k.rs
Normal file
24
bindings/rust/src/m68k.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// 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,
|
||||
}
|
156
bindings/rust/src/mips.rs
Normal file
156
bindings/rust/src/mips.rs
Normal file
@ -0,0 +1,156 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// MIPS registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum RegisterMIPS {
|
||||
INVALID = 0,
|
||||
|
||||
// General purpose registers
|
||||
PC = 1,
|
||||
ZERO = 2,
|
||||
AT = 3,
|
||||
V0 = 4,
|
||||
V1 = 5,
|
||||
A0 = 6,
|
||||
A1 = 7,
|
||||
A2 = 8,
|
||||
A3 = 9,
|
||||
T0 = 10,
|
||||
T1 = 11,
|
||||
T2 = 12,
|
||||
T3 = 13,
|
||||
T4 = 14,
|
||||
T5 = 15,
|
||||
T6 = 16,
|
||||
T7 = 17,
|
||||
S0 = 18,
|
||||
S1 = 19,
|
||||
S2 = 20,
|
||||
S3 = 21,
|
||||
S4 = 22,
|
||||
S5 = 23,
|
||||
S6 = 24,
|
||||
S7 = 25,
|
||||
T8 = 26,
|
||||
T9 = 27,
|
||||
K0 = 28,
|
||||
K1 = 29,
|
||||
GP = 30,
|
||||
SP = 31,
|
||||
FP = 32,
|
||||
RA = 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,
|
||||
}
|
42
bindings/rust/src/ppc.rs
Normal file
42
bindings/rust/src/ppc.rs
Normal file
@ -0,0 +1,42 @@
|
||||
#![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,
|
||||
}
|
94
bindings/rust/src/sparc.rs
Normal file
94
bindings/rust/src/sparc.rs
Normal file
@ -0,0 +1,94 @@
|
||||
// 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,
|
||||
}
|
158
bindings/rust/src/unicorn_const.rs
Normal file
158
bindings/rust/src/unicorn_const.rs
Normal file
@ -0,0 +1,158 @@
|
||||
#![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;
|
||||
}
|
||||
}
|
424
bindings/rust/src/utils.rs
Normal file
424
bindings/rust/src/utils.rs
Normal file
@ -0,0 +1,424 @@
|
||||
#![allow(non_snake_case)]
|
||||
extern crate libc;
|
||||
|
||||
use super::arm::RegisterARM;
|
||||
use super::arm64::RegisterARM64;
|
||||
use super::m68k::RegisterM68K;
|
||||
use super::mips::RegisterMIPS;
|
||||
use super::sparc::RegisterSPARC;
|
||||
use super::x86::RegisterX86;
|
||||
use super::{uc_error, Arch, HookType, MemType, Mode, Permission};
|
||||
use capstone::prelude::*;
|
||||
use libc::{c_void, mmap, size_t, MAP_ANON, MAP_PRIVATE, PROT_READ, PROT_WRITE};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::ptr;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Chunk {
|
||||
pub offset: u64,
|
||||
pub len: size_t,
|
||||
pub freed: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Heap {
|
||||
pub real_base: *mut c_void,
|
||||
pub uc_base: u64,
|
||||
pub len: size_t,
|
||||
pub grow_dynamically: bool,
|
||||
pub chunk_map: HashMap<u64, Chunk>,
|
||||
pub top: u64,
|
||||
pub unalloc_hook: super::ffi::uc_hook,
|
||||
}
|
||||
|
||||
/// Hooks (parts of the) code segment to display register info and the current instruction.
|
||||
pub fn add_debug_prints_ARM<D>(uc: &mut super::UnicornHandle<D>, code_start: u64, code_end: u64) {
|
||||
let cs_arm: Capstone = Capstone::new()
|
||||
.arm()
|
||||
.mode(arch::arm::ArchMode::Arm)
|
||||
.detail(true)
|
||||
.build()
|
||||
.expect("failed to create capstone for ARM");
|
||||
|
||||
let cs_thumb: Capstone = Capstone::new()
|
||||
.arm()
|
||||
.mode(arch::arm::ArchMode::Thumb)
|
||||
.detail(true)
|
||||
.build()
|
||||
.expect("failed to create capstone for thumb");
|
||||
|
||||
let callback = Box::new(move |uc: super::UnicornHandle<D>, addr: u64, size: u32| {
|
||||
let sp = uc
|
||||
.reg_read(RegisterARM::SP as i32)
|
||||
.expect("failed to read SP");
|
||||
let lr = uc
|
||||
.reg_read(RegisterARM::LR as i32)
|
||||
.expect("failed to read LR");
|
||||
let r0 = uc
|
||||
.reg_read(RegisterARM::R0 as i32)
|
||||
.expect("failed to read r0");
|
||||
let r1 = uc
|
||||
.reg_read(RegisterARM::R1 as i32)
|
||||
.expect("failed to read r1");
|
||||
let r2 = uc
|
||||
.reg_read(RegisterARM::R2 as i32)
|
||||
.expect("failed to read r2");
|
||||
let r3 = uc
|
||||
.reg_read(RegisterARM::R3 as i32)
|
||||
.expect("failed to read r3");
|
||||
let r4 = uc
|
||||
.reg_read(RegisterARM::R4 as i32)
|
||||
.expect("failed to read r4");
|
||||
let r5 = uc
|
||||
.reg_read(RegisterARM::R5 as i32)
|
||||
.expect("failed to read r5");
|
||||
let r6 = uc
|
||||
.reg_read(RegisterARM::R6 as i32)
|
||||
.expect("failed to read r6");
|
||||
let r7 = uc
|
||||
.reg_read(RegisterARM::R7 as i32)
|
||||
.expect("failed to read r7");
|
||||
let r8 = uc
|
||||
.reg_read(RegisterARM::R8 as i32)
|
||||
.expect("failed to read r8");
|
||||
let r9 = uc
|
||||
.reg_read(RegisterARM::R9 as i32)
|
||||
.expect("failed to read r9");
|
||||
let r10 = uc
|
||||
.reg_read(RegisterARM::R10 as i32)
|
||||
.expect("failed to read r10");
|
||||
let r11 = uc
|
||||
.reg_read(RegisterARM::R11 as i32)
|
||||
.expect("failed to read r11");
|
||||
println!("________________________________________________________________________\n");
|
||||
println!(
|
||||
"$r0: {:#010x} $r1: {:#010x} $r2: {:#010x} $r3: {:#010x}",
|
||||
r0, r1, r2, r3
|
||||
);
|
||||
println!(
|
||||
"$r4: {:#010x} $r5: {:#010x} $r6: {:#010x} $r7: {:#010x}",
|
||||
r4, r5, r6, r7
|
||||
);
|
||||
println!(
|
||||
"$r8: {:#010x} $r9: {:#010x} $r10: {:#010x} $r11: {:#010x}",
|
||||
r8, r9, r10, r11
|
||||
);
|
||||
println!("$sp: {:#010x} $lr: {:#010x}\n", sp, lr);
|
||||
|
||||
// decide which mode (ARM/Thumb) to use for disasm
|
||||
let cpsr = uc
|
||||
.reg_read(RegisterARM::CPSR as i32)
|
||||
.expect("failed to read CPSR");
|
||||
let mut buf = vec![0; size as usize];
|
||||
uc.mem_read(addr, &mut buf)
|
||||
.expect("failed to read opcode from memory");
|
||||
let ins = if cpsr & 0x20 != 0 {
|
||||
cs_thumb.disasm_all(&buf, size as u64)
|
||||
} else {
|
||||
cs_arm.disasm_all(&buf, size as u64)
|
||||
}
|
||||
.expect(&format!("failed to disasm at addr {:#010x}", addr));
|
||||
println!("$pc: {:#010x}", addr);
|
||||
println!("{}", ins);
|
||||
});
|
||||
|
||||
uc.add_code_hook(code_start, code_end, callback)
|
||||
.expect("failed to set debug hook");
|
||||
}
|
||||
|
||||
/// Returns a new Unicorn instance with an initialized heap and active sanitizer.
|
||||
///
|
||||
/// Introduces an accessible way of dynamic memory allocation for emulation and helps
|
||||
/// detecting common memory corruption bugs.
|
||||
/// The allocator makes heavy use of Unicorn hooks for sanitization/ crash amplification
|
||||
/// and thus introduces some overhead.
|
||||
pub fn init_emu_with_heap(
|
||||
arch: Arch,
|
||||
mut size: u32,
|
||||
base_addr: u64,
|
||||
grow: bool,
|
||||
) -> Result<super::Unicorn<RefCell<Heap>>, uc_error> {
|
||||
let heap = RefCell::new(Heap {
|
||||
real_base: 0 as _,
|
||||
uc_base: 0,
|
||||
len: 0,
|
||||
grow_dynamically: false,
|
||||
chunk_map: HashMap::new(),
|
||||
top: 0,
|
||||
unalloc_hook: 0 as _,
|
||||
});
|
||||
|
||||
let mut unicorn = super::Unicorn::new(arch, Mode::LITTLE_ENDIAN, heap)?;
|
||||
let mut uc = unicorn.borrow(); // get handle
|
||||
|
||||
// uc memory regions have to be 8 byte aligned
|
||||
if size % 8 != 0 {
|
||||
size = ((size / 8) + 1) * 8;
|
||||
}
|
||||
|
||||
// init heap management struct for later use within unicorn
|
||||
let null_ptr = ptr::null_mut();
|
||||
unsafe {
|
||||
// manually mmap space for heap to know location
|
||||
let arena_ptr = mmap(
|
||||
null_ptr,
|
||||
size as usize,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_PRIVATE,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
uc.mem_map_ptr(
|
||||
base_addr,
|
||||
size as usize,
|
||||
Permission::READ | Permission::WRITE,
|
||||
arena_ptr,
|
||||
)?;
|
||||
let h = uc.add_mem_hook(
|
||||
HookType::MEM_VALID,
|
||||
base_addr,
|
||||
base_addr + size as u64,
|
||||
Box::new(heap_unalloc),
|
||||
)?;
|
||||
let chunks = HashMap::new();
|
||||
let heap: &mut Heap = &mut *uc.get_data().borrow_mut();
|
||||
heap.real_base = arena_ptr; // heap pointer in process mem
|
||||
heap.uc_base = base_addr;
|
||||
heap.len = size as usize;
|
||||
/*
|
||||
let the heap grow dynamically
|
||||
(ATTENTION: There are no guarantees that the heap segment will be continuous in process mem any more)
|
||||
*/
|
||||
heap.grow_dynamically = grow;
|
||||
heap.chunk_map = chunks;
|
||||
heap.top = base_addr; // pointer to top of heap in unicorn mem, increases on allocations
|
||||
heap.unalloc_hook = h; // hook ID, needed to rearrange hooks on allocations
|
||||
}
|
||||
|
||||
return Ok(unicorn);
|
||||
}
|
||||
|
||||
/// `malloc` for the utils allocator.
|
||||
///
|
||||
/// Returns a pointer into memory used as heap and applies
|
||||
/// canary hooks to detect out-of-bounds accesses.
|
||||
/// Grows the heap if necessary and if it is configured to, otherwise
|
||||
/// return WRITE_UNMAPPED if there is no space left.
|
||||
pub fn uc_alloc(
|
||||
uc: &mut super::UnicornHandle<RefCell<Heap>>,
|
||||
mut size: u64,
|
||||
) -> Result<u64, uc_error> {
|
||||
// 8 byte aligned
|
||||
if size % 8 != 0 {
|
||||
size = ((size / 8) + 1) * 8;
|
||||
}
|
||||
let addr = uc.get_data().borrow_mut().top;
|
||||
let mut len = uc.get_data().borrow_mut().len;
|
||||
let uc_base = uc.get_data().borrow_mut().uc_base;
|
||||
|
||||
if addr + size >= uc_base + len as u64 {
|
||||
if !uc.get_data().borrow_mut().grow_dynamically {
|
||||
return Err(uc_error::WRITE_UNMAPPED);
|
||||
} else {
|
||||
// grow heap
|
||||
let mut increase_by = len / 2;
|
||||
if increase_by % 8 != 0 {
|
||||
increase_by = ((increase_by / 8) + 1) * 8;
|
||||
}
|
||||
uc.mem_map(
|
||||
uc_base + len as u64,
|
||||
increase_by,
|
||||
Permission::READ | Permission::WRITE,
|
||||
)?;
|
||||
uc.get_data().borrow_mut().len += increase_by;
|
||||
len = uc.get_data().borrow_mut().len;
|
||||
}
|
||||
}
|
||||
|
||||
// canary hooks
|
||||
uc.add_mem_hook(HookType::MEM_WRITE, addr, addr + 3, Box::new(heap_bo))?;
|
||||
uc.add_mem_hook(HookType::MEM_READ, addr, addr + 3, Box::new(heap_oob))?;
|
||||
uc.add_mem_hook(
|
||||
HookType::MEM_WRITE,
|
||||
addr + 4 + size,
|
||||
addr + 4 + size + 3,
|
||||
Box::new(heap_bo),
|
||||
)?;
|
||||
uc.add_mem_hook(
|
||||
HookType::MEM_READ,
|
||||
addr + 4 + size,
|
||||
addr + 4 + size + 3,
|
||||
Box::new(heap_oob),
|
||||
)?;
|
||||
|
||||
// add new chunk
|
||||
let curr_offset = addr + 4 - uc_base;
|
||||
let curr_chunk = Chunk {
|
||||
offset: curr_offset,
|
||||
len: size as size_t,
|
||||
freed: false,
|
||||
};
|
||||
uc.get_data()
|
||||
.borrow_mut()
|
||||
.chunk_map
|
||||
.insert(addr + 4, curr_chunk);
|
||||
let new_top = uc.get_data().borrow_mut().top + size + 8; // canary*2
|
||||
#[cfg(debug_assertions)]
|
||||
println!(
|
||||
"[+] New Allocation from {:#010x} to {:#010x} (size: {})",
|
||||
uc.get_data().borrow().top,
|
||||
uc.get_data().borrow().top + size - 1 + 8,
|
||||
size
|
||||
);
|
||||
uc.get_data().borrow_mut().top = new_top;
|
||||
|
||||
// adjust oob hooks
|
||||
let old_h = uc.get_data().borrow_mut().unalloc_hook;
|
||||
uc.remove_hook(old_h)?;
|
||||
let new_h = uc.add_mem_hook(
|
||||
HookType::MEM_VALID,
|
||||
new_top,
|
||||
uc_base + len as u64,
|
||||
Box::new(heap_unalloc),
|
||||
)?;
|
||||
uc.get_data().borrow_mut().unalloc_hook = new_h;
|
||||
|
||||
return Ok(addr + 4);
|
||||
}
|
||||
|
||||
/// `free` for the utils allocator.
|
||||
///
|
||||
/// Marks the chunk to be freed to detect double-frees later on
|
||||
/// and places sanitization hooks over the freed region to detect
|
||||
/// use-after-frees.
|
||||
pub fn uc_free(uc: &mut super::UnicornHandle<RefCell<Heap>>, ptr: u64) -> Result<(), uc_error> {
|
||||
#[cfg(debug_assertions)]
|
||||
println!("[-] Freeing {:#010x}", ptr);
|
||||
|
||||
if ptr != 0x0 {
|
||||
#[allow(unused_assignments)]
|
||||
let mut chunk_size = 0;
|
||||
{
|
||||
let mut heap = uc.get_data().borrow_mut();
|
||||
let curr_chunk = heap
|
||||
.chunk_map
|
||||
.get_mut(&ptr)
|
||||
.expect("failed to find requested chunk on heap");
|
||||
chunk_size = curr_chunk.len as u64;
|
||||
curr_chunk.freed = true;
|
||||
}
|
||||
uc.add_mem_hook(
|
||||
HookType::MEM_VALID,
|
||||
ptr,
|
||||
ptr + chunk_size - 1,
|
||||
Box::new(heap_uaf),
|
||||
)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn heap_unalloc(
|
||||
uc: super::UnicornHandle<RefCell<Heap>>,
|
||||
_mem_type: MemType,
|
||||
addr: u64,
|
||||
_size: usize,
|
||||
_val: i64,
|
||||
) {
|
||||
let arch = uc.get_arch();
|
||||
let reg = match arch {
|
||||
Arch::X86 => RegisterX86::RIP as i32,
|
||||
Arch::ARM => RegisterARM::PC as i32,
|
||||
Arch::ARM64 => RegisterARM64::PC as i32,
|
||||
Arch::MIPS => RegisterMIPS::PC as i32,
|
||||
Arch::SPARC => RegisterSPARC::PC as i32,
|
||||
Arch::M68K => RegisterM68K::PC as i32,
|
||||
_ => panic!("Arch not yet supported by unicorn::utils module"),
|
||||
};
|
||||
let pc = uc.reg_read(reg).expect("failed to read pc");
|
||||
panic!("ERROR: unicorn-rs Sanitizer: Heap out-of-bounds access of unallocated memory on addr {:#0x}, $pc: {:#010x}",
|
||||
addr, pc);
|
||||
}
|
||||
|
||||
fn heap_oob(
|
||||
uc: super::UnicornHandle<RefCell<Heap>>,
|
||||
_mem_type: MemType,
|
||||
addr: u64,
|
||||
_size: usize,
|
||||
_val: i64,
|
||||
) {
|
||||
let arch = uc.get_arch();
|
||||
let reg = match arch {
|
||||
Arch::X86 => RegisterX86::RIP as i32,
|
||||
Arch::ARM => RegisterARM::PC as i32,
|
||||
Arch::ARM64 => RegisterARM64::PC as i32,
|
||||
Arch::MIPS => RegisterMIPS::PC as i32,
|
||||
Arch::SPARC => RegisterSPARC::PC as i32,
|
||||
Arch::M68K => RegisterM68K::PC as i32,
|
||||
_ => panic!("Arch not yet supported by unicorn::utils module"),
|
||||
};
|
||||
let pc = uc.reg_read(reg).expect("failed to read pc");
|
||||
panic!(
|
||||
"ERROR: unicorn-rs Sanitizer: Heap out-of-bounds read on addr {:#0x}, $pc: {:#010x}",
|
||||
addr, pc
|
||||
);
|
||||
}
|
||||
|
||||
fn heap_bo(
|
||||
uc: super::UnicornHandle<RefCell<Heap>>,
|
||||
_mem_type: MemType,
|
||||
addr: u64,
|
||||
_size: usize,
|
||||
_val: i64,
|
||||
) {
|
||||
let arch = uc.get_arch();
|
||||
let reg = match arch {
|
||||
Arch::X86 => RegisterX86::RIP as i32,
|
||||
Arch::ARM => RegisterARM::PC as i32,
|
||||
Arch::ARM64 => RegisterARM64::PC as i32,
|
||||
Arch::MIPS => RegisterMIPS::PC as i32,
|
||||
Arch::SPARC => RegisterSPARC::PC as i32,
|
||||
Arch::M68K => RegisterM68K::PC as i32,
|
||||
_ => panic!("Arch not yet supported by unicorn::utils module"),
|
||||
};
|
||||
let pc = uc.reg_read(reg).expect("failed to read pc");
|
||||
panic!(
|
||||
"ERROR: unicorn-rs Sanitizer: Heap buffer-overflow on addr {:#0x}, $pc: {:#010x}",
|
||||
addr, pc
|
||||
);
|
||||
}
|
||||
|
||||
fn heap_uaf(
|
||||
uc: super::UnicornHandle<RefCell<Heap>>,
|
||||
_mem_type: MemType,
|
||||
addr: u64,
|
||||
_size: usize,
|
||||
_val: i64,
|
||||
) {
|
||||
let arch = uc.get_arch();
|
||||
let reg = match arch {
|
||||
Arch::X86 => RegisterX86::RIP as i32,
|
||||
Arch::ARM => RegisterARM::PC as i32,
|
||||
Arch::ARM64 => RegisterARM64::PC as i32,
|
||||
Arch::MIPS => RegisterMIPS::PC as i32,
|
||||
Arch::SPARC => RegisterSPARC::PC as i32,
|
||||
Arch::M68K => RegisterM68K::PC as i32,
|
||||
_ => panic!("Arch not yet supported by unicorn::utils module"),
|
||||
};
|
||||
let pc = uc.reg_read(reg).expect("failed to read pc");
|
||||
panic!(
|
||||
"ERROR: unicorn-rs Sanitizer: Heap use-after-free on addr {:#0x}, $pc: {:#010x}",
|
||||
addr, pc
|
||||
);
|
||||
}
|
||||
|
||||
pub fn vmmap<D>(uc: &mut super::UnicornHandle<D>) {
|
||||
let regions = uc
|
||||
.mem_regions()
|
||||
.expect("failed to retrieve memory mappings");
|
||||
println!("Regions : {}", regions.len());
|
||||
|
||||
for region in ®ions {
|
||||
println!("{:#010x?}", region);
|
||||
}
|
||||
}
|
281
bindings/rust/src/x86.rs
Normal file
281
bindings/rust/src/x86.rs
Normal file
@ -0,0 +1,281 @@
|
||||
// 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,
|
||||
}
|
683
bindings/rust/tests/unicorn.rs
Normal file
683
bindings/rust/tests/unicorn.rs
Normal file
@ -0,0 +1,683 @@
|
||||
#![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, u32>;
|
||||
|
||||
#[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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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, 0)
|
||||
.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(()));
|
||||
}
|
@ -13,7 +13,7 @@ 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
|
||||
UNICORN_ARCHS ?= x86 m68k arm aarch64 mips sparc ppc
|
||||
|
||||
|
||||
################################################################################
|
||||
|
@ -1797,9 +1797,9 @@ uc_err uc_emu_stop(uc_engine *uc)
|
||||
|
||||
uc->stop_request = true;
|
||||
|
||||
if (uc->current_cpu) {
|
||||
if (uc->cpu) {
|
||||
// 退出当前线程
|
||||
cpu_exit(uc->current_cpu);
|
||||
cpu_exit(uc->cpu);
|
||||
}
|
||||
|
||||
return UC_ERR_OK;
|
||||
|
@ -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,7 +14,7 @@ struct uc_struct;
|
||||
#include "exec/memory.h"
|
||||
|
||||
#include "qemu/thread.h"
|
||||
#include "include/qom/cpu.h"
|
||||
#include "qom/cpu.h"
|
||||
|
||||
#include "vl.h"
|
||||
|
||||
@ -25,12 +26,10 @@ typedef struct RAMBlock {
|
||||
ram_addr_t offset;
|
||||
ram_addr_t 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;
|
||||
|
||||
typedef struct {
|
||||
@ -41,11 +40,8 @@ typedef struct {
|
||||
} BounceBuffer;
|
||||
|
||||
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;
|
||||
} 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
|
||||
@ -34,14 +36,6 @@
|
||||
#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
|
||||
@ -73,6 +67,8 @@ 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 *);
|
||||
|
||||
// which interrupt should make emulation stop?
|
||||
typedef bool (*uc_args_int_t)(int intno);
|
||||
|
||||
@ -145,6 +141,8 @@ 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 TCGContext TCGContext;
|
||||
|
||||
struct uc_struct {
|
||||
uc_arch arch;
|
||||
uc_mode mode;
|
||||
@ -170,8 +168,8 @@ struct uc_struct {
|
||||
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;
|
||||
CPUState *cpu;
|
||||
|
||||
uc_insn_hook_validate insn_hook_validate;
|
||||
|
||||
@ -179,37 +177,18 @@ struct uc_struct {
|
||||
MemoryRegion io_mem_rom; // qemu/exec.c
|
||||
MemoryRegion io_mem_notdirty; // qemu/exec.c
|
||||
MemoryRegion io_mem_unassigned; // qemu/exec.c
|
||||
MemoryRegion io_mem_watch; // qemu/exec.c
|
||||
RAMList ram_list; // qemu/exec.c
|
||||
BounceBuffer bounce; // qemu/cpu-exec.c
|
||||
volatile sig_atomic_t exit_request; // qemu/cpu-exec.c
|
||||
bool global_dirty_log; // qemu/memory.c
|
||||
/* 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
|
||||
size_t l1_map_size;
|
||||
/* 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;
|
||||
|
||||
// linked lists containing hooks per type
|
||||
struct list hook[UC_HOOK_MAX];
|
||||
@ -221,8 +200,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?
|
||||
|
62
include/unicorn/ppc.h
Normal file
62
include/unicorn/ppc.h
Normal file
@ -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
|
@ -32,6 +32,7 @@ typedef size_t uc_hook;
|
||||
#include "arm64.h"
|
||||
#include "mips.h"
|
||||
#include "sparc.h"
|
||||
#include "ppc.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
|
||||
@ -71,7 +72,7 @@ typedef size_t uc_hook;
|
||||
// Unicorn package version
|
||||
#define UC_VERSION_MAJOR UC_API_MAJOR
|
||||
#define UC_VERSION_MINOR UC_API_MINOR
|
||||
#define UC_VERSION_EXTRA 2
|
||||
#define UC_VERSION_EXTRA 3
|
||||
|
||||
|
||||
/*
|
||||
@ -92,7 +93,7 @@ typedef enum uc_arch {
|
||||
UC_ARCH_ARM64, // ARM-64, also called AArch64
|
||||
UC_ARCH_MIPS, // Mips architecture
|
||||
UC_ARCH_X86, // X86 architecture (including x86 & x86-64)
|
||||
UC_ARCH_PPC, // PowerPC architecture (currently unsupported)
|
||||
UC_ARCH_PPC, // PowerPC architecture
|
||||
UC_ARCH_SPARC, // Sparc architecture
|
||||
UC_ARCH_M68K, // M68K architecture
|
||||
UC_ARCH_MAX,
|
||||
@ -127,7 +128,7 @@ typedef enum uc_mode {
|
||||
UC_MODE_64 = 1 << 3, // 64-bit mode
|
||||
|
||||
// ppc
|
||||
UC_MODE_PPC32 = 1 << 2, // 32-bit mode (currently unsupported)
|
||||
UC_MODE_PPC32 = 1 << 2, // 32-bit mode
|
||||
UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported)
|
||||
UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported)
|
||||
|
||||
|
175
msvc/samples/sample_ppc/sample_ppc.vcxproj
Normal file
175
msvc/samples/sample_ppc/sample_ppc.vcxproj
Normal file
@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>sample_ppc</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;__i386__</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../../../include</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);unicorn_static.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;__i386__</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../../../include</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);unicorn_static.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;__i386__</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../../../include</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);unicorn_static.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;__i386__</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../../../include</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);unicorn_static.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\samples\sample_ppc.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
6
msvc/samples/sample_ppc/sample_ppc.vcxproj.filters
Normal file
6
msvc/samples/sample_ppc/sample_ppc.vcxproj.filters
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\samples\sample_ppc.c" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicorn", "unicorn\unicorn\unicorn.vcxproj", "{ACB78BBB-E8F4-4EAD-B981-9C6155DE100B}"
|
||||
@ -14,6 +14,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicorn", "unicorn\unicorn\
|
||||
{17077E86-AE7C-41AF-86ED-2BAC03B019BC} = {17077E86-AE7C-41AF-86ED-2BAC03B019BC}
|
||||
{4478909E-6983-425C-9D9F-558CF258E61E} = {4478909E-6983-425C-9D9F-558CF258E61E}
|
||||
{340D86A5-E53C-490B-880A-8EB1F5BDE947} = {340D86A5-E53C-490B-880A-8EB1F5BDE947}
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F} = {4403A7BB-E2C5-443F-8711-EDF338E7D44F}
|
||||
{F67EB1EA-DCFA-4758-A2AA-4B570BA78036} = {F67EB1EA-DCFA-4758-A2AA-4B570BA78036}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
@ -30,6 +31,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicorn_static", "unicorn\u
|
||||
{17077E86-AE7C-41AF-86ED-2BAC03B019BC} = {17077E86-AE7C-41AF-86ED-2BAC03B019BC}
|
||||
{4478909E-6983-425C-9D9F-558CF258E61E} = {4478909E-6983-425C-9D9F-558CF258E61E}
|
||||
{340D86A5-E53C-490B-880A-8EB1F5BDE947} = {340D86A5-E53C-490B-880A-8EB1F5BDE947}
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F} = {4403A7BB-E2C5-443F-8711-EDF338E7D44F}
|
||||
{F67EB1EA-DCFA-4758-A2AA-4B570BA78036} = {F67EB1EA-DCFA-4758-A2AA-4B570BA78036}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
@ -121,6 +123,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_arm64eb", "samples\s
|
||||
{B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96} = {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ppc-softmmu", "unicorn\ppc-softmmu\ppc-softmmu.vcxproj", "{4403A7BB-E2C5-443F-8711-EDF338E7D44F}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_ppc", "samples\sample_ppc\sample_ppc.vcxproj", "{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96} = {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@ -337,6 +346,22 @@ Global
|
||||
{1A42A5E3-82A7-4EE4-B7D2-8265B147F124}.Release|Win32.Build.0 = Release|Win32
|
||||
{1A42A5E3-82A7-4EE4-B7D2-8265B147F124}.Release|x64.ActiveCfg = Release|x64
|
||||
{1A42A5E3-82A7-4EE4-B7D2-8265B147F124}.Release|x64.Build.0 = Release|x64
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F}.Debug|x64.Build.0 = Debug|x64
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F}.Release|Win32.Build.0 = Release|Win32
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F}.Release|x64.ActiveCfg = Release|x64
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F}.Release|x64.Build.0 = Release|x64
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}.Debug|x64.Build.0 = Debug|x64
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}.Release|Win32.Build.0 = Release|Win32
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}.Release|x64.ActiveCfg = Release|x64
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -366,5 +391,10 @@ Global
|
||||
{F113B460-4B21-4014-9A15-D472FAA9E3F9} = {F8E85E25-4D67-4A6B-A976-C920790B8798}
|
||||
{1945F27B-ABB3-47F9-9268-A42F73C8B992} = {F8E85E25-4D67-4A6B-A976-C920790B8798}
|
||||
{1A42A5E3-82A7-4EE4-B7D2-8265B147F124} = {F8E85E25-4D67-4A6B-A976-C920790B8798}
|
||||
{4403A7BB-E2C5-443F-8711-EDF338E7D44F} = {857A09AF-FE20-461C-B66F-D779422AD46B}
|
||||
{6A26C1E4-8C93-40D5-8BA6-B47180BE2CBC} = {F8E85E25-4D67-4A6B-A976-C920790B8798}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {11903E9E-FA50-454E-9F04-70742B6F40B7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
6
msvc/unicorn/ppc-softmmu/config-target.h
Normal file
6
msvc/unicorn/ppc-softmmu/config-target.h
Normal file
@ -0,0 +1,6 @@
|
||||
/* Automatically generated by create_config - do not modify */
|
||||
#define TARGET_PPC 1
|
||||
#define TARGET_NAME "ppc"
|
||||
#define TARGET_PPC 1
|
||||
#define TARGET_WORDS_BIGENDIAN 1
|
||||
#define CONFIG_SOFTMMU 1
|
236
msvc/unicorn/ppc-softmmu/ppc-softmmu.vcxproj
Normal file
236
msvc/unicorn/ppc-softmmu/ppc-softmmu.vcxproj
Normal file
@ -0,0 +1,236 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\qemu\fpu\softfloat-macros.h" />
|
||||
<ClInclude Include="..\..\..\qemu\fpu\softfloat-specialize.h" />
|
||||
<ClInclude Include="..\..\..\qemu\tcg\i386\tcg-target.h" />
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-be-ldst.h" />
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-be-null.h" />
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-op.h" />
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-opc.h" />
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-runtime.h" />
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\cpu-models.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\cpu-qom.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\cpu.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\helper.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\helper_regs.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\mmu-hash32.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\mmu-hash64.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\unicorn.h" />
|
||||
<ClInclude Include="..\..\..\qemu\ppc.h" />
|
||||
<ClInclude Include="..\config-host.h" />
|
||||
<ClInclude Include="config-target.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\qemu\cpu-exec.c" />
|
||||
<ClCompile Include="..\..\..\qemu\cpus.c" />
|
||||
<ClCompile Include="..\..\..\qemu\cputlb.c" />
|
||||
<ClCompile Include="..\..\..\qemu\exec.c" />
|
||||
<ClCompile Include="..\..\..\qemu\fpu\softfloat.c" />
|
||||
<ClCompile Include="..\..\..\qemu\hw\ppc\e500plat.c" />
|
||||
<ClCompile Include="..\..\..\qemu\hw\ppc\ppc_booke.c" />
|
||||
<ClCompile Include="..\..\..\qemu\hw\ppc\ppc.c" />
|
||||
<ClCompile Include="..\..\..\qemu\ioport.c" />
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\decContext.c" />
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\decNumber.c" />
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\dpd\decimal128.c" />
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\dpd\decimal32.c" />
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\dpd\decimal64.c" />
|
||||
<ClCompile Include="..\..\..\qemu\memory_mapping.c" />
|
||||
<ClCompile Include="..\..\..\qemu\memory.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\cpu-models.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\dfp_helper.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\excp_helper.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\fpu_helper.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\int_helper.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\mem_helper.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\misc_helper.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\mmu-hash32.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\mmu_helper.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\timebase_helper.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\translate.c" />
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\unicorn.c" />
|
||||
<ClCompile Include="..\..\..\qemu\tcg\optimize.c" />
|
||||
<ClCompile Include="..\..\..\qemu\tcg\tcg.c" />
|
||||
<ClCompile Include="..\..\..\qemu\translate-all.c" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4403A7BB-E2C5-443F-8711-EDF338E7D44F}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ppcsoftmmu</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;__i386__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..;../../../qemu;../../../qemu/include;../../../qemu/tcg;../../../qemu/tcg/i386;../../../qemu/target-ppc;../../../include</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<ForcedIncludeFiles>ppc.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>..\prebuild_script.bat</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;__x86_64__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..;../../../qemu;../../../qemu/include;../../../qemu/tcg;../../../qemu/tcg/i386;../../../qemu/target-ppc;../../../include</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<ForcedIncludeFiles>ppc.h</ForcedIncludeFiles>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>..\prebuild_script.bat</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;__i386__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..;../../../qemu;../../../qemu/include;../../../qemu/tcg;../../../qemu/tcg/i386;../../../qemu/target-ppc;../../../include</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<ForcedIncludeFiles>ppc.h</ForcedIncludeFiles>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>..\prebuild_script.bat</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;__x86_64__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..;../../../qemu;../../../qemu/include;../../../qemu/tcg;../../../qemu/tcg/i386;../../../qemu/target-ppc;../../../include</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<ForcedIncludeFiles>ppc.h</ForcedIncludeFiles>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>..\prebuild_script.bat</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
161
msvc/unicorn/ppc-softmmu/ppc-softmmu.vcxproj.filters
Normal file
161
msvc/unicorn/ppc-softmmu/ppc-softmmu.vcxproj.filters
Normal file
@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="fpu">
|
||||
<UniqueIdentifier>{70d46eb5-5a8c-4f5a-8177-ff052e72ad16}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="hw">
|
||||
<UniqueIdentifier>{3c697f87-41f1-42c8-9532-3b7569b2414a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="hw\ppc">
|
||||
<UniqueIdentifier>{1f4169dc-0b51-4e73-aae3-fd2206b4ce12}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="libdecnumber">
|
||||
<UniqueIdentifier>{80731b46-a3f5-4f61-8eb5-f028138797fc}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="target-ppc">
|
||||
<UniqueIdentifier>{b2e2301b-7983-47b6-ad06-6d8e41b3887e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="tcg">
|
||||
<UniqueIdentifier>{abb2c8a3-d95f-48a2-903a-47919c277de4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="tcg\i386">
|
||||
<UniqueIdentifier>{675cc183-f2ba-4587-aa0f-35712756ced1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\qemu\fpu\softfloat-macros.h">
|
||||
<Filter>fpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\fpu\softfloat-specialize.h">
|
||||
<Filter>fpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-be-ldst.h">
|
||||
<Filter>tcg</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-be-null.h">
|
||||
<Filter>tcg</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-op.h">
|
||||
<Filter>tcg</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-opc.h">
|
||||
<Filter>tcg</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg-runtime.h">
|
||||
<Filter>tcg</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\tcg\tcg.h">
|
||||
<Filter>tcg</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\tcg\i386\tcg-target.h">
|
||||
<Filter>tcg\i386</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\config-host.h" />
|
||||
<ClInclude Include="config-target.h" />
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\cpu-models.h">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\cpu-qom.h">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\cpu.h">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\helper.h">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\helper_regs.h">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\mmu-hash32.h">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\mmu-hash64.h">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\target-ppc\unicorn.h">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\qemu\ppc.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\qemu\fpu\softfloat.c">
|
||||
<Filter>fpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\tcg\optimize.c">
|
||||
<Filter>tcg</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\tcg\tcg.c">
|
||||
<Filter>tcg</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\cpu-exec.c" />
|
||||
<ClCompile Include="..\..\..\qemu\cpus.c" />
|
||||
<ClCompile Include="..\..\..\qemu\cputlb.c" />
|
||||
<ClCompile Include="..\..\..\qemu\exec.c" />
|
||||
<ClCompile Include="..\..\..\qemu\ioport.c" />
|
||||
<ClCompile Include="..\..\..\qemu\memory.c" />
|
||||
<ClCompile Include="..\..\..\qemu\memory_mapping.c" />
|
||||
<ClCompile Include="..\..\..\qemu\translate-all.c" />
|
||||
<ClCompile Include="..\..\..\qemu\hw\ppc\e500plat.c">
|
||||
<Filter>hw\ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\hw\ppc\ppc_booke.c">
|
||||
<Filter>hw\ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\hw\ppc\ppc.c">
|
||||
<Filter>hw\ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\decContext.c">
|
||||
<Filter>libdecnumber</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\decNumber.c">
|
||||
<Filter>libdecnumber</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\dpd\decimal128.c">
|
||||
<Filter>libdecnumber</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\dpd\decimal32.c">
|
||||
<Filter>libdecnumber</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\libdecnumber\dpd\decimal64.c">
|
||||
<Filter>libdecnumber</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\cpu-models.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\dfp_helper.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\excp_helper.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\fpu_helper.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\int_helper.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\mem_helper.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\misc_helper.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\mmu-hash32.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\mmu_helper.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\timebase_helper.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\translate.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\qemu\target-ppc\unicorn.c">
|
||||
<Filter>target-ppc</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
@ -91,7 +91,7 @@
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNICORN_DLL_EXPORTS;UNICORN_SHARED;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__i386__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNICORN_DLL_EXPORTS;UNICORN_SHARED;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__i386__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_PPC;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..;../../../include;../../../qemu;../../../qemu/include;../../../qemu/tcg</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
@ -100,7 +100,7 @@
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;ppc-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -109,7 +109,7 @@
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNICORN_DLL_EXPORTS;UNICORN_SHARED;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UNICORN_DLL_EXPORTS;UNICORN_SHARED;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_PPC;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..;../../../include;../../../qemu;../../../qemu/include;../../../qemu/tcg</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
@ -119,7 +119,7 @@
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;ppc-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -130,7 +130,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICORN_DLL_EXPORTS;UNICORN_SHARED;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__i386__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICORN_DLL_EXPORTS;UNICORN_SHARED;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__i386__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_PPC;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..;../../../include;../../../qemu;../../../qemu/include;../../../qemu/tcg</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@ -142,7 +142,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;ppc-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
@ -165,7 +165,7 @@ copy "$(SolutionDir)..\include\unicorn\*.h" "$(SolutionDir)distro\include\unicor
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICORN_DLL_EXPORTS;UNICORN_SHARED;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICORN_DLL_EXPORTS;UNICORN_SHARED;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_PPC;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..;../../../include;../../../qemu;../../../qemu/include;../../../qemu/tcg</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@ -177,7 +177,7 @@ copy "$(SolutionDir)..\include\unicorn\*.h" "$(SolutionDir)distro\include\unicor
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;ppc-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
@ -247,7 +247,7 @@
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__i386__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__i386__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_PPC;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>.;..;../../../include;../../../qemu;../../../qemu/include;../../../qemu/tcg</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
@ -259,7 +259,7 @@
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;ppc-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
</Lib>
|
||||
<PreBuildEvent>
|
||||
<Command>..\prebuild_script.bat</Command>
|
||||
@ -271,7 +271,7 @@
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_PPC;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>.;..;../../../include;../../../qemu;../../../qemu/include;../../../qemu/tcg</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
@ -284,7 +284,7 @@
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;ppc-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
</Lib>
|
||||
<PreBuildEvent>
|
||||
<Command>..\prebuild_script.bat</Command>
|
||||
@ -298,7 +298,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__i386__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__i386__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_PPC;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>.;..;../../../include;../../../qemu;../../../qemu/include;../../../qemu/tcg</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
@ -313,7 +313,7 @@
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;ppc-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
</Lib>
|
||||
<PreBuildEvent>
|
||||
<Command>..\prebuild_script.bat</Command>
|
||||
@ -338,7 +338,7 @@ copy "$(SolutionDir)..\include\unicorn\*.h" "$(SolutionDir)distro\include\unicor
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM;UNICORN_HAS_ARM64;UNICORN_HAS_M68K;UNICORN_HAS_MIPS;UNICORN_HAS_MIPS64;UNICORN_HAS_MIPSEL;UNICORN_HAS_MIPS64EL;UNICORN_HAS_PPC;UNICORN_HAS_SPARC;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>.;..;../../../include;../../../qemu;../../../qemu/include;../../../qemu/tcg</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/wd4018 /wd4244 /wd4267 %(AdditionalOptions)</AdditionalOptions>
|
||||
@ -353,7 +353,7 @@ copy "$(SolutionDir)..\include\unicorn\*.h" "$(SolutionDir)distro\include\unicor
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;m68k-softmmu.lib;mips-softmmu.lib;mips64-softmmu.lib;mipsel-softmmu.lib;mips64el-softmmu.lib;ppc-softmmu.lib;sparc-softmmu.lib;sparc64-softmmu.lib;x86_64-softmmu.lib</AdditionalDependencies>
|
||||
</Lib>
|
||||
<PreBuildEvent>
|
||||
<Command>..\prebuild_script.bat</Command>
|
||||
|
@ -7,7 +7,8 @@ PKG_MAJOR = 1
|
||||
PKG_MINOR = 0
|
||||
|
||||
# version bugfix level. Example: PKG_EXTRA = 1
|
||||
PKG_EXTRA = 2
|
||||
PKG_EXTRA = 3
|
||||
|
||||
# version tag. Examples: rc1, b2, post1
|
||||
PKG_TAG =
|
||||
# PKG_TAG = rc6
|
||||
|
@ -20,7 +20,6 @@ endif
|
||||
endif
|
||||
|
||||
CONFIG_SOFTMMU := $(if $(filter %-softmmu,$(TARGET_DIRS)),y)
|
||||
-include config-all-devices.mak
|
||||
|
||||
include $(SRC_PATH)/rules.mak
|
||||
config-host.mak: $(SRC_PATH)/configure
|
||||
@ -45,24 +44,6 @@ configure: ;
|
||||
$(call set-vpath, $(SRC_PATH))
|
||||
|
||||
SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) BUILD_DIR=$(BUILD_DIR)
|
||||
SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
|
||||
SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS))
|
||||
|
||||
ifeq ($(SUBDIR_DEVICES_MAK),)
|
||||
config-all-devices.mak:
|
||||
$(call quiet-command,echo '# no devices' > $@," GEN $@")
|
||||
else
|
||||
config-all-devices.mak: $(SUBDIR_DEVICES_MAK)
|
||||
$(call quiet-command, sed -n \
|
||||
's|^\([^=]*\)=\(.*\)$$|\1:=$$(findstring y,$$(\1)\2)|p' \
|
||||
$(SUBDIR_DEVICES_MAK) | sort -u > $@, \
|
||||
" GEN $@")
|
||||
endif
|
||||
|
||||
-include $(SUBDIR_DEVICES_MAK_DEP)
|
||||
|
||||
%/config-devices.mak: default-configs/%.mak
|
||||
$(call quiet-command, cp $< $@, " GEN $@")
|
||||
|
||||
ifneq ($(wildcard config-host.mak),)
|
||||
include $(SRC_PATH)/Makefile.objs
|
||||
@ -76,14 +57,11 @@ config-host.h: config-host.h-timestamp
|
||||
config-host.h-timestamp: config-host.mak
|
||||
|
||||
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
|
||||
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
|
||||
|
||||
$(SOFTMMU_SUBDIR_RULES): config-all-devices.mak
|
||||
|
||||
subdir-%:
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $* V="$(V)" TARGET_DIR="$*/" all,)
|
||||
|
||||
$(SUBDIR_RULES): qapi-types.c qapi-types.h qapi-visit.c qapi-visit.h $(common-obj-y) $(util-obj-y)
|
||||
$(SUBDIR_RULES): $(common-obj-y) $(util-obj-y)
|
||||
|
||||
recurse-all: $(SUBDIR_RULES)
|
||||
|
||||
@ -100,7 +78,6 @@ clean:
|
||||
|
||||
distclean: clean
|
||||
rm -f config-host.mak config-host.h*
|
||||
rm -f config-all-devices.mak
|
||||
rm -f config.log config.status
|
||||
for d in $(TARGET_DIRS); do \
|
||||
rm -rf $$d || exit 1 ; \
|
||||
|
@ -1,12 +1,11 @@
|
||||
#######################################################################
|
||||
# Common libraries for tools and emulators
|
||||
util-obj-y = util/ qobject/ qapi/ qapi-types.o qapi-visit.o
|
||||
util-obj-y = util/
|
||||
|
||||
common-obj-y += hw/
|
||||
common-obj-y += accel.o
|
||||
common-obj-y += vl.o qemu-timer.o
|
||||
common-obj-y += ../uc.o ../list.o glib_compat.o
|
||||
common-obj-y += qemu-log.o
|
||||
common-obj-y += tcg-runtime.o
|
||||
common-obj-y += hw/
|
||||
common-obj-y += qom/
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
include ../config-host.mak
|
||||
include config-target.mak
|
||||
include config-devices.mak
|
||||
include $(SRC_PATH)/rules.mak
|
||||
|
||||
$(call set-vpath, $(SRC_PATH))
|
||||
|
@ -656,6 +656,8 @@
|
||||
#define gen_helper_double_saturate gen_helper_double_saturate_aarch64
|
||||
#define gen_helper_exception_internal gen_helper_exception_internal_aarch64
|
||||
#define gen_helper_exception_with_syndrome gen_helper_exception_with_syndrome_aarch64
|
||||
#define gen_helper_float64_to_float32 gen_helper_float64_to_float32_aarch64
|
||||
#define gen_helper_float32_to_float64 gen_helper_float32_to_float64_aarch64
|
||||
#define gen_helper_get_cp_reg gen_helper_get_cp_reg_aarch64
|
||||
#define gen_helper_get_cp_reg64 gen_helper_get_cp_reg64_aarch64
|
||||
#define gen_helper_get_r13_banked gen_helper_get_r13_banked_aarch64
|
||||
@ -1376,6 +1378,8 @@
|
||||
#define helper_exception_internal helper_exception_internal_aarch64
|
||||
#define helper_exception_return helper_exception_return_aarch64
|
||||
#define helper_exception_with_syndrome helper_exception_with_syndrome_aarch64
|
||||
#define helper_float32_to_float64 helper_float32_to_float64_aarch64
|
||||
#define helper_float64_to_float32 helper_float64_to_float32_aarch64
|
||||
#define helper_get_cp_reg helper_get_cp_reg_aarch64
|
||||
#define helper_get_cp_reg64 helper_get_cp_reg64_aarch64
|
||||
#define helper_get_r13_banked helper_get_r13_banked_aarch64
|
||||
@ -2114,7 +2118,6 @@
|
||||
#define object_child_foreach object_child_foreach_aarch64
|
||||
#define object_class_foreach object_class_foreach_aarch64
|
||||
#define object_class_foreach_tramp object_class_foreach_tramp_aarch64
|
||||
#define object_class_get_list object_class_get_list_aarch64
|
||||
#define object_class_get_list_tramp object_class_get_list_tramp_aarch64
|
||||
#define object_class_get_parent object_class_get_parent_aarch64
|
||||
#define object_deinit object_deinit_aarch64
|
||||
@ -3022,6 +3025,7 @@
|
||||
#define arm64_reg_reset arm64_reg_reset_aarch64
|
||||
#define arm64_reg_read arm64_reg_read_aarch64
|
||||
#define arm64_reg_write arm64_reg_write_aarch64
|
||||
#define arm_cpu_class_init arm_cpu_class_init_aarch64
|
||||
#define gen_a64_set_pc_im gen_a64_set_pc_im_aarch64
|
||||
#define aarch64_cpu_register_types aarch64_cpu_register_types_aarch64
|
||||
#define helper_udiv64 helper_udiv64_aarch64
|
||||
|
@ -656,6 +656,8 @@
|
||||
#define gen_helper_double_saturate gen_helper_double_saturate_aarch64eb
|
||||
#define gen_helper_exception_internal gen_helper_exception_internal_aarch64eb
|
||||
#define gen_helper_exception_with_syndrome gen_helper_exception_with_syndrome_aarch64eb
|
||||
#define gen_helper_float64_to_float32 gen_helper_float64_to_float32_aarch64eb
|
||||
#define gen_helper_float32_to_float64 gen_helper_float32_to_float64_aarch64eb
|
||||
#define gen_helper_get_cp_reg gen_helper_get_cp_reg_aarch64eb
|
||||
#define gen_helper_get_cp_reg64 gen_helper_get_cp_reg64_aarch64eb
|
||||
#define gen_helper_get_r13_banked gen_helper_get_r13_banked_aarch64eb
|
||||
@ -1376,6 +1378,8 @@
|
||||
#define helper_exception_internal helper_exception_internal_aarch64eb
|
||||
#define helper_exception_return helper_exception_return_aarch64eb
|
||||
#define helper_exception_with_syndrome helper_exception_with_syndrome_aarch64eb
|
||||
#define helper_float32_to_float64 helper_float32_to_float64_aarch64eb
|
||||
#define helper_float64_to_float32 helper_float64_to_float32_aarch64eb
|
||||
#define helper_get_cp_reg helper_get_cp_reg_aarch64eb
|
||||
#define helper_get_cp_reg64 helper_get_cp_reg64_aarch64eb
|
||||
#define helper_get_r13_banked helper_get_r13_banked_aarch64eb
|
||||
@ -2114,7 +2118,6 @@
|
||||
#define object_child_foreach object_child_foreach_aarch64eb
|
||||
#define object_class_foreach object_class_foreach_aarch64eb
|
||||
#define object_class_foreach_tramp object_class_foreach_tramp_aarch64eb
|
||||
#define object_class_get_list object_class_get_list_aarch64eb
|
||||
#define object_class_get_list_tramp object_class_get_list_tramp_aarch64eb
|
||||
#define object_class_get_parent object_class_get_parent_aarch64eb
|
||||
#define object_deinit object_deinit_aarch64eb
|
||||
@ -3022,6 +3025,7 @@
|
||||
#define arm64_reg_reset arm64_reg_reset_aarch64eb
|
||||
#define arm64_reg_read arm64_reg_read_aarch64eb
|
||||
#define arm64_reg_write arm64_reg_write_aarch64eb
|
||||
#define arm_cpu_class_init arm_cpu_class_init_aarch64eb
|
||||
#define gen_a64_set_pc_im gen_a64_set_pc_im_aarch64eb
|
||||
#define aarch64_cpu_register_types aarch64_cpu_register_types_aarch64eb
|
||||
#define helper_udiv64 helper_udiv64_aarch64eb
|
||||
|
130
qemu/accel.c
130
qemu/accel.c
@ -1,130 +0,0 @@
|
||||
/*
|
||||
* QEMU System Emulator, accelerator interfaces
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2014 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Modified for Unicorn Engine by Nguyen Anh Quynh, 2015 */
|
||||
|
||||
#include "sysemu/accel.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qom/object.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
// use default size for TCG translated block
|
||||
#define TCG_TB_SIZE 0
|
||||
|
||||
static bool tcg_allowed = true;
|
||||
static int tcg_init(MachineState *ms);
|
||||
static AccelClass *accel_find(struct uc_struct *uc, const char *opt_name);
|
||||
static int accel_init_machine(AccelClass *acc, MachineState *ms);
|
||||
static void tcg_accel_class_init(struct uc_struct *uc, ObjectClass *oc, void *data);
|
||||
|
||||
static int tcg_init(MachineState *ms)
|
||||
{
|
||||
ms->uc->tcg_exec_init(ms->uc, TCG_TB_SIZE * 1024 * 1024); // arch-dependent
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const TypeInfo accel_type = {
|
||||
TYPE_ACCEL,
|
||||
TYPE_OBJECT,
|
||||
sizeof(AccelClass),
|
||||
sizeof(AccelState),
|
||||
};
|
||||
|
||||
#define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg")
|
||||
|
||||
static const TypeInfo tcg_accel_type = {
|
||||
TYPE_TCG_ACCEL,
|
||||
TYPE_ACCEL,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
tcg_accel_class_init,
|
||||
};
|
||||
|
||||
|
||||
int configure_accelerator(MachineState *ms)
|
||||
{
|
||||
int ret;
|
||||
bool accel_initialised = false;
|
||||
AccelClass *acc;
|
||||
|
||||
acc = accel_find(ms->uc, "tcg");
|
||||
ret = accel_init_machine(acc, ms);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to initialize %s: %s\n",
|
||||
acc->name,
|
||||
strerror(-ret));
|
||||
} else {
|
||||
accel_initialised = true;
|
||||
}
|
||||
|
||||
return !accel_initialised;
|
||||
}
|
||||
|
||||
void register_accel_types(struct uc_struct *uc)
|
||||
{
|
||||
type_register_static(uc, &accel_type);
|
||||
type_register_static(uc, &tcg_accel_type);
|
||||
}
|
||||
|
||||
static void tcg_accel_class_init(struct uc_struct *uc, ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(uc, oc);
|
||||
ac->name = "tcg";
|
||||
ac->init_machine = tcg_init;
|
||||
ac->allowed = &tcg_allowed;
|
||||
}
|
||||
|
||||
/* Lookup AccelClass from opt_name. Returns NULL if not found */
|
||||
static AccelClass *accel_find(struct uc_struct *uc, const char *opt_name)
|
||||
{
|
||||
char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
|
||||
AccelClass *ac = ACCEL_CLASS(uc, object_class_by_name(uc, class_name));
|
||||
g_free(class_name);
|
||||
return ac;
|
||||
}
|
||||
|
||||
static int accel_init_machine(AccelClass *acc, MachineState *ms)
|
||||
{
|
||||
ObjectClass *oc = OBJECT_CLASS(acc);
|
||||
const char *cname = object_class_get_name(oc);
|
||||
AccelState *accel = ACCEL(ms->uc, object_new(ms->uc, cname));
|
||||
int ret;
|
||||
ms->accelerator = accel;
|
||||
*(acc->allowed) = true;
|
||||
ret = acc->init_machine(ms);
|
||||
if (ret < 0) {
|
||||
ms->accelerator = NULL;
|
||||
*(acc->allowed) = false;
|
||||
object_unref(ms->uc, OBJECT(accel));
|
||||
}
|
||||
return ret;
|
||||
}
|
@ -656,6 +656,8 @@
|
||||
#define gen_helper_double_saturate gen_helper_double_saturate_arm
|
||||
#define gen_helper_exception_internal gen_helper_exception_internal_arm
|
||||
#define gen_helper_exception_with_syndrome gen_helper_exception_with_syndrome_arm
|
||||
#define gen_helper_float64_to_float32 gen_helper_float64_to_float32_arm
|
||||
#define gen_helper_float32_to_float64 gen_helper_float32_to_float64_arm
|
||||
#define gen_helper_get_cp_reg gen_helper_get_cp_reg_arm
|
||||
#define gen_helper_get_cp_reg64 gen_helper_get_cp_reg64_arm
|
||||
#define gen_helper_get_r13_banked gen_helper_get_r13_banked_arm
|
||||
@ -1376,6 +1378,8 @@
|
||||
#define helper_exception_internal helper_exception_internal_arm
|
||||
#define helper_exception_return helper_exception_return_arm
|
||||
#define helper_exception_with_syndrome helper_exception_with_syndrome_arm
|
||||
#define helper_float32_to_float64 helper_float32_to_float64_arm
|
||||
#define helper_float64_to_float32 helper_float64_to_float32_arm
|
||||
#define helper_get_cp_reg helper_get_cp_reg_arm
|
||||
#define helper_get_cp_reg64 helper_get_cp_reg64_arm
|
||||
#define helper_get_r13_banked helper_get_r13_banked_arm
|
||||
@ -2114,7 +2118,6 @@
|
||||
#define object_child_foreach object_child_foreach_arm
|
||||
#define object_class_foreach object_class_foreach_arm
|
||||
#define object_class_foreach_tramp object_class_foreach_tramp_arm
|
||||
#define object_class_get_list object_class_get_list_arm
|
||||
#define object_class_get_list_tramp object_class_get_list_tramp_arm
|
||||
#define object_class_get_parent object_class_get_parent_arm
|
||||
#define object_deinit object_deinit_arm
|
||||
@ -3018,4 +3021,5 @@
|
||||
#define xscale_cpar_write xscale_cpar_write_arm
|
||||
#define xscale_cp_reginfo xscale_cp_reginfo_arm
|
||||
#define ARM_REGS_STORAGE_SIZE ARM_REGS_STORAGE_SIZE_arm
|
||||
#define arm_cpu_class_init arm_cpu_class_init_arm
|
||||
#endif
|
||||
|
@ -656,6 +656,8 @@
|
||||
#define gen_helper_double_saturate gen_helper_double_saturate_armeb
|
||||
#define gen_helper_exception_internal gen_helper_exception_internal_armeb
|
||||
#define gen_helper_exception_with_syndrome gen_helper_exception_with_syndrome_armeb
|
||||
#define gen_helper_float64_to_float32 gen_helper_float64_to_float32_armeb
|
||||
#define gen_helper_float32_to_float64 gen_helper_float32_to_float64_armeb
|
||||
#define gen_helper_get_cp_reg gen_helper_get_cp_reg_armeb
|
||||
#define gen_helper_get_cp_reg64 gen_helper_get_cp_reg64_armeb
|
||||
#define gen_helper_get_r13_banked gen_helper_get_r13_banked_armeb
|
||||
@ -1376,6 +1378,8 @@
|
||||
#define helper_exception_internal helper_exception_internal_armeb
|
||||
#define helper_exception_return helper_exception_return_armeb
|
||||
#define helper_exception_with_syndrome helper_exception_with_syndrome_armeb
|
||||
#define helper_float32_to_float64 helper_float32_to_float64_armeb
|
||||
#define helper_float64_to_float32 helper_float64_to_float32_armeb
|
||||
#define helper_get_cp_reg helper_get_cp_reg_armeb
|
||||
#define helper_get_cp_reg64 helper_get_cp_reg64_armeb
|
||||
#define helper_get_r13_banked helper_get_r13_banked_armeb
|
||||
@ -2114,7 +2118,6 @@
|
||||
#define object_child_foreach object_child_foreach_armeb
|
||||
#define object_class_foreach object_class_foreach_armeb
|
||||
#define object_class_foreach_tramp object_class_foreach_tramp_armeb
|
||||
#define object_class_get_list object_class_get_list_armeb
|
||||
#define object_class_get_list_tramp object_class_get_list_tramp_armeb
|
||||
#define object_class_get_parent object_class_get_parent_armeb
|
||||
#define object_deinit object_deinit_armeb
|
||||
@ -3018,4 +3021,5 @@
|
||||
#define xscale_cpar_write xscale_cpar_write_armeb
|
||||
#define xscale_cp_reginfo xscale_cp_reginfo_armeb
|
||||
#define ARM_REGS_STORAGE_SIZE ARM_REGS_STORAGE_SIZE_armeb
|
||||
#define arm_cpu_class_init arm_cpu_class_init_armeb
|
||||
#endif
|
||||
|
14
qemu/configure
vendored
14
qemu/configure
vendored
@ -587,17 +587,9 @@ esac
|
||||
QEMU_CFLAGS="$CPU_CFLAGS $QEMU_CFLAGS"
|
||||
EXTRA_CFLAGS="$CPU_CFLAGS $EXTRA_CFLAGS"
|
||||
|
||||
default_target_list=""
|
||||
|
||||
mak_wilds=""
|
||||
|
||||
if [ "$softmmu" = "yes" ]; then
|
||||
mak_wilds="${mak_wilds} $source_path/default-configs/*-softmmu.mak"
|
||||
fi
|
||||
|
||||
for config in $mak_wilds; do
|
||||
default_target_list="${default_target_list} $(basename "$config" .mak)"
|
||||
done
|
||||
default_target_list="aarch64eb-softmmu aarch64-softmmu armeb-softmmu \
|
||||
arm-softmmu m68k-softmmu mips64el-softmmu mips64-softmmu mipsel-softmmu \
|
||||
mips-softmmu ppc-softmmu sparc64-softmmu sparc-softmmu x86_64-softmmu"
|
||||
|
||||
if test x"$show_help" = x"yes" ; then
|
||||
cat << EOF
|
||||
|
@ -48,7 +48,7 @@ void cpu_resume_from_signal(CPUState *cpu, void *puc)
|
||||
|
||||
/* main execution loop */
|
||||
|
||||
int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
||||
int cpu_exec(struct uc_struct *uc, CPUArchState *env)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||
@ -70,7 +70,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
||||
cpu->halted = 0;
|
||||
}
|
||||
|
||||
uc->current_cpu = cpu;
|
||||
uc->cpu = cpu;
|
||||
|
||||
/* As long as current_cpu is null, up to the assignment just above,
|
||||
* requests by other threads to exit the execution loop are expected to
|
||||
@ -97,7 +97,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
||||
|
||||
/* if an exception is pending, we execute it here */
|
||||
if (cpu->exception_index >= 0) {
|
||||
//printf(">>> GOT INTERRUPT. exception idx = %x\n", cpu->exception_index); // qq
|
||||
//printf(">>> GOT INTERRUPT. exception idx = %x\n", cpu->exception_index);
|
||||
if (cpu->exception_index >= EXCP_INTERRUPT) {
|
||||
/* exit request from the cpu execution loop */
|
||||
ret = cpu->exception_index;
|
||||
@ -221,7 +221,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
|
||||
tb = tb_find_fast(env); // qq
|
||||
tb = tb_find_fast(env);
|
||||
if (!tb) { // invalid TB due to invalid code?
|
||||
uc->invalid_error = UC_ERR_FETCH_UNMAPPED;
|
||||
ret = EXCP_HLT;
|
||||
@ -255,7 +255,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
||||
if (likely(!cpu->exit_request)) {
|
||||
tc_ptr = tb->tc_ptr;
|
||||
/* execute the generated code */
|
||||
next_tb = cpu_tb_exec(cpu, tc_ptr); // qq
|
||||
next_tb = cpu_tb_exec(cpu, tc_ptr);
|
||||
|
||||
switch (next_tb & TB_EXIT_MASK) {
|
||||
case TB_EXIT_REQUESTED:
|
||||
@ -281,7 +281,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
||||
} else {
|
||||
/* Reload env after longjmp - the compiler may have smashed all
|
||||
* local variables as longjmp is marked 'noreturn'. */
|
||||
cpu = uc->current_cpu;
|
||||
cpu = uc->cpu;
|
||||
env = cpu->env_ptr;
|
||||
cc = CPU_GET_CLASS(uc, cpu);
|
||||
#ifdef TARGET_I386
|
||||
@ -291,7 +291,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
||||
} /* for(;;) */
|
||||
|
||||
// Unicorn: Clear any TCG exit flag that might have been left set by exit requests
|
||||
uc->current_cpu->tcg_exit_req = 0;
|
||||
uc->cpu->tcg_exit_req = 0;
|
||||
|
||||
cc->cpu_exec_exit(cpu);
|
||||
|
||||
@ -300,8 +300,8 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
|
||||
// TODO: optimize this for better performance
|
||||
tb_flush(env);
|
||||
|
||||
/* fail safe : never use current_cpu outside cpu_exec() */
|
||||
// uc->current_cpu = NULL;
|
||||
/* fail safe : never use cpu outside cpu_exec() */
|
||||
// uc->cpu = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -353,7 +353,7 @@ static tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
|
||||
}
|
||||
|
||||
static TranslationBlock *tb_find_slow(CPUArchState *env, target_ulong pc,
|
||||
target_ulong cs_base, uint64_t flags) // qq
|
||||
target_ulong cs_base, uint64_t flags)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||
@ -365,7 +365,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, target_ulong pc,
|
||||
tcg_ctx->tb_ctx.tb_invalidated_flag = 0;
|
||||
|
||||
/* find translated block using physical mappings */
|
||||
phys_pc = get_page_addr_code(env, pc); // qq
|
||||
phys_pc = get_page_addr_code(env, pc);
|
||||
if (phys_pc == -1) { // invalid code?
|
||||
return NULL;
|
||||
}
|
||||
@ -397,7 +397,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, target_ulong pc,
|
||||
}
|
||||
not_found:
|
||||
/* if no translated code available, then translate it now */
|
||||
tb = tb_gen_code(cpu, pc, cs_base, (int)flags, 0); // qq
|
||||
tb = tb_gen_code(cpu, pc, cs_base, (int)flags, 0);
|
||||
if (tb == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -414,7 +414,7 @@ found:
|
||||
return tb;
|
||||
}
|
||||
|
||||
static TranslationBlock *tb_find_fast(CPUArchState *env) // qq
|
||||
static TranslationBlock *tb_find_fast(CPUArchState *env)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
TranslationBlock *tb;
|
||||
@ -428,7 +428,7 @@ static TranslationBlock *tb_find_fast(CPUArchState *env) // qq
|
||||
tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
|
||||
if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
|
||||
tb->flags != flags)) {
|
||||
tb = tb_find_slow(env, pc, cs_base, flags); // qq
|
||||
tb = tb_find_slow(env, pc, cs_base, flags);
|
||||
}
|
||||
return tb;
|
||||
}
|
||||
|
22
qemu/cpus.c
22
qemu/cpus.c
@ -189,25 +189,3 @@ static void cpu_handle_guest_debug(CPUState *cpu)
|
||||
cpu->stopped = true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifndef _WIN32
|
||||
static void qemu_tcg_init_cpu_signals(void)
|
||||
{
|
||||
sigset_t set;
|
||||
struct sigaction sigact;
|
||||
|
||||
memset(&sigact, 0, sizeof(sigact));
|
||||
sigact.sa_handler = cpu_signal;
|
||||
sigaction(SIG_IPI, &sigact, NULL);
|
||||
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIG_IPI);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
static void qemu_tcg_init_cpu_signals(void)
|
||||
{
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
#endif
|
||||
|
||||
|
@ -18,9 +18,11 @@
|
||||
*/
|
||||
|
||||
/* Modified for Unicorn Engine by Nguyen Anh Quynh, 2015 */
|
||||
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/address-spaces.h"
|
||||
@ -229,7 +231,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
|
||||
#endif
|
||||
|
||||
address = vaddr;
|
||||
if (!memory_region_is_ram(section->mr) && !memory_region_is_romd(section->mr)) {
|
||||
if (!memory_region_is_ram(section->mr)) {
|
||||
/* IO memory case */
|
||||
address |= TLB_MMIO;
|
||||
addend = 0;
|
||||
@ -264,8 +266,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
|
||||
te->addr_code = -1;
|
||||
}
|
||||
if (prot & PAGE_WRITE) {
|
||||
if ((memory_region_is_ram(section->mr) && section->readonly)
|
||||
|| memory_region_is_romd(section->mr)) {
|
||||
if (memory_region_is_ram(section->mr) && section->readonly) {
|
||||
/* Write access calls the I/O callback. */
|
||||
te->addr_write = address | TLB_MMIO;
|
||||
} else if (memory_region_is_ram(section->mr)
|
||||
|
@ -1,3 +0,0 @@
|
||||
# Default configuration for x86_64-softmmu
|
||||
|
||||
CONFIG_APIC=y
|
396
qemu/exec.c
396
qemu/exec.c
@ -17,6 +17,8 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* Modified for Unicorn Engine by Nguyen Anh Quynh, 2015 */
|
||||
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#ifndef _WIN32
|
||||
@ -27,16 +29,13 @@
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "tcg.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
#include <qemu.h>
|
||||
#endif
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
#include "exec/cputlb.h"
|
||||
@ -51,20 +50,12 @@
|
||||
|
||||
//#define DEBUG_SUBPAGE
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
|
||||
#define RAM_PREALLOC (1 << 0)
|
||||
|
||||
/* RAM is mmap-ed with MAP_SHARED */
|
||||
#define RAM_SHARED (1 << 1)
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* current CPU in the current thread. It is only valid inside
|
||||
cpu_exec() */
|
||||
//DEFINE_TLS(CPUState *, current_cpu);
|
||||
|
||||
typedef struct PhysPageEntry PhysPageEntry;
|
||||
|
||||
@ -121,10 +112,6 @@ typedef struct subpage_t {
|
||||
static void memory_map_init(struct uc_struct *uc);
|
||||
static void tcg_commit(MemoryListener *listener);
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes)
|
||||
{
|
||||
if (map->nodes_nb + nodes > map->nodes_nb_alloc) {
|
||||
@ -284,8 +271,7 @@ static MemoryRegionSection *phys_page_find(PhysPageEntry lp, hwaddr addr,
|
||||
|
||||
bool memory_region_is_unassigned(struct uc_struct* uc, MemoryRegion *mr)
|
||||
{
|
||||
return mr != &uc->io_mem_rom && mr != &uc->io_mem_notdirty &&
|
||||
!mr->rom_device && mr != &uc->io_mem_watch;
|
||||
return mr != &uc->io_mem_rom && mr != &uc->io_mem_notdirty;
|
||||
}
|
||||
|
||||
static MemoryRegionSection *address_space_lookup_region(AddressSpaceDispatch *d,
|
||||
@ -327,9 +313,6 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
|
||||
if (memory_region_is_ram(mr)) {
|
||||
return !(is_write && mr->readonly);
|
||||
}
|
||||
if (memory_region_is_romd(mr)) {
|
||||
return !is_write;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -338,7 +321,6 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
|
||||
hwaddr *xlat, hwaddr *plen,
|
||||
bool is_write)
|
||||
{
|
||||
IOMMUTLBEntry iotlb;
|
||||
MemoryRegionSection *section;
|
||||
MemoryRegion *mr;
|
||||
hwaddr len = *plen;
|
||||
@ -346,23 +328,12 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
|
||||
for (;;) {
|
||||
section = address_space_translate_internal(as->dispatch, addr, &addr, plen, true);
|
||||
mr = section->mr;
|
||||
if (mr->ops == NULL)
|
||||
if (mr->ops == NULL) {
|
||||
*xlat = 0;
|
||||
return NULL;
|
||||
|
||||
if (!mr->iommu_ops) {
|
||||
break;
|
||||
}
|
||||
|
||||
iotlb = mr->iommu_ops->translate(mr, addr, is_write);
|
||||
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
|
||||
| (addr & iotlb.addr_mask));
|
||||
len = MIN(len, (addr | iotlb.addr_mask) - addr + 1);
|
||||
if (!(iotlb.perm & (1 << is_write))) {
|
||||
mr = &as->uc->io_mem_unassigned;
|
||||
break;
|
||||
}
|
||||
|
||||
as = iotlb.target_as;
|
||||
break;
|
||||
}
|
||||
|
||||
*plen = len;
|
||||
@ -377,10 +348,8 @@ address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat,
|
||||
MemoryRegionSection *section;
|
||||
section = address_space_translate_internal(as->dispatch, addr, xlat, plen, false);
|
||||
|
||||
assert(!section->mr->iommu_ops);
|
||||
return section;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPUState *qemu_get_cpu(struct uc_struct *uc, int index)
|
||||
{
|
||||
@ -391,7 +360,6 @@ CPUState *qemu_get_cpu(struct uc_struct *uc, int index)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as)
|
||||
{
|
||||
/* We only support one address space per cpu at the moment. */
|
||||
@ -405,7 +373,6 @@ void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as)
|
||||
cpu->tcg_as_listener->commit = tcg_commit;
|
||||
memory_listener_register(as->uc, cpu->tcg_as_listener, as);
|
||||
}
|
||||
#endif
|
||||
|
||||
void cpu_exec_init(CPUArchState *env, void *opaque)
|
||||
{
|
||||
@ -427,12 +394,6 @@ void cpu_exec_init(CPUArchState *env, void *opaque)
|
||||
}
|
||||
|
||||
#if defined(TARGET_HAS_ICE)
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
||||
{
|
||||
tb_invalidate_phys_page_range(pc, pc + 1, 0);
|
||||
}
|
||||
#else
|
||||
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
||||
{
|
||||
hwaddr phys = cpu_get_phys_page_debug(cpu, pc);
|
||||
@ -441,31 +402,8 @@ static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
||||
phys | (pc & ~TARGET_PAGE_MASK));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* TARGET_HAS_ICE */
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, vaddr len,
|
||||
int flags)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint)
|
||||
{
|
||||
}
|
||||
|
||||
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
|
||||
int flags, CPUWatchpoint **watchpoint)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#else
|
||||
/* Add a watchpoint. */
|
||||
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
|
||||
int flags, CPUWatchpoint **watchpoint)
|
||||
@ -554,8 +492,6 @@ static inline bool cpu_watchpoint_address_matches(CPUWatchpoint *wp,
|
||||
return !(addr > wpend || wp->vaddr > addrend);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Add a breakpoint. */
|
||||
int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
|
||||
CPUBreakpoint **breakpoint)
|
||||
@ -630,55 +566,11 @@ void cpu_breakpoint_remove_all(CPUState *cpu, int mask)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* enable or disable single step mode. EXCP_DEBUG is returned by the
|
||||
CPU loop after each instruction */
|
||||
void cpu_single_step(CPUState *cpu, int enabled)
|
||||
{
|
||||
#if defined(TARGET_HAS_ICE)
|
||||
if (cpu->singlestep_enabled != enabled) {
|
||||
CPUArchState *env;
|
||||
cpu->singlestep_enabled = enabled;
|
||||
/* must flush all the translated code to avoid inconsistencies */
|
||||
/* XXX: only flush what is necessary */
|
||||
env = cpu->env_ptr;
|
||||
tb_flush(env);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void cpu_abort(CPUState *cpu, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap2;
|
||||
|
||||
va_start(ap, fmt);
|
||||
va_copy(ap2, ap);
|
||||
fprintf(stderr, "qemu: fatal: ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU | CPU_DUMP_CCOP);
|
||||
if (qemu_log_enabled()) {
|
||||
qemu_log("qemu: fatal: ");
|
||||
qemu_log_vprintf(fmt, ap2);
|
||||
qemu_log("\n");
|
||||
log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
|
||||
qemu_log_flush();
|
||||
qemu_log_close();
|
||||
}
|
||||
va_end(ap2);
|
||||
va_end(ap);
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
{
|
||||
struct sigaction act;
|
||||
sigfillset(&act.sa_mask);
|
||||
act.sa_handler = SIG_DFL;
|
||||
sigaction(SIGABRT, &act, NULL);
|
||||
}
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
static RAMBlock *qemu_get_ram_block(struct uc_struct *uc, ram_addr_t addr)
|
||||
{
|
||||
RAMBlock *block;
|
||||
@ -770,9 +662,7 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
|
||||
|
||||
return iotlb;
|
||||
}
|
||||
#endif /* defined(CONFIG_USER_ONLY) */
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
|
||||
uint16_t section);
|
||||
@ -781,16 +671,6 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
|
||||
static void *(*phys_mem_alloc)(size_t size, uint64_t *align) =
|
||||
qemu_anon_ram_alloc;
|
||||
|
||||
/*
|
||||
* Set a custom physical guest memory alloator.
|
||||
* Accelerators with unusual needs may need this. Hopefully, we can
|
||||
* get rid of it eventually.
|
||||
*/
|
||||
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align))
|
||||
{
|
||||
phys_mem_alloc = alloc;
|
||||
}
|
||||
|
||||
static uint16_t phys_section_add(PhysPageMap *map,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
@ -806,17 +686,13 @@ static uint16_t phys_section_add(PhysPageMap *map,
|
||||
map->sections_nb_alloc);
|
||||
}
|
||||
map->sections[map->sections_nb] = *section;
|
||||
memory_region_ref(section->mr);
|
||||
return map->sections_nb++;
|
||||
}
|
||||
|
||||
static void phys_section_destroy(MemoryRegion *mr)
|
||||
{
|
||||
memory_region_unref(mr);
|
||||
|
||||
if (mr->subpage) {
|
||||
subpage_t *subpage = container_of(mr, subpage_t, iomem);
|
||||
object_unref(mr->uc, OBJECT(&subpage->iomem));
|
||||
g_free(subpage);
|
||||
}
|
||||
}
|
||||
@ -906,14 +782,6 @@ static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <sys/vfs.h>
|
||||
|
||||
#define HUGETLBFS_MAGIC 0x958458f6
|
||||
|
||||
#endif
|
||||
|
||||
static ram_addr_t find_ram_offset(struct uc_struct *uc, ram_addr_t size)
|
||||
{
|
||||
RAMBlock *block, *next_block;
|
||||
@ -960,56 +828,18 @@ ram_addr_t last_ram_offset(struct uc_struct *uc)
|
||||
return last;
|
||||
}
|
||||
|
||||
static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
|
||||
{
|
||||
}
|
||||
|
||||
static RAMBlock *find_ram_block(struct uc_struct *uc, ram_addr_t addr)
|
||||
static ram_addr_t ram_block_add(struct uc_struct *uc, RAMBlock *new_block)
|
||||
{
|
||||
RAMBlock *block;
|
||||
|
||||
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
|
||||
if (block->offset == addr) {
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void qemu_ram_unset_idstr(struct uc_struct *uc, ram_addr_t addr)
|
||||
{
|
||||
RAMBlock *block = find_ram_block(uc, addr);
|
||||
|
||||
if (block) {
|
||||
memset(block->idstr, 0, sizeof(block->idstr));
|
||||
}
|
||||
}
|
||||
|
||||
static int memory_try_enable_merging(void *addr, size_t len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ram_addr_t ram_block_add(struct uc_struct *uc, RAMBlock *new_block, Error **errp)
|
||||
{
|
||||
RAMBlock *block;
|
||||
ram_addr_t old_ram_size, new_ram_size;
|
||||
|
||||
old_ram_size = last_ram_offset(uc) >> TARGET_PAGE_BITS;
|
||||
|
||||
new_block->offset = find_ram_offset(uc, new_block->length);
|
||||
|
||||
if (!new_block->host) {
|
||||
new_block->host = phys_mem_alloc(new_block->length,
|
||||
&new_block->mr->align);
|
||||
if (!new_block->host) {
|
||||
error_setg_errno(errp, errno,
|
||||
"cannot set up guest memory '%s'",
|
||||
memory_region_name(new_block->mr));
|
||||
return -1;
|
||||
}
|
||||
memory_try_enable_merging(new_block->host, new_block->length);
|
||||
}
|
||||
|
||||
/* Keep the list sorted from biggest to smallest block. */
|
||||
@ -1025,34 +855,17 @@ static ram_addr_t ram_block_add(struct uc_struct *uc, RAMBlock *new_block, Error
|
||||
}
|
||||
uc->ram_list.mru_block = NULL;
|
||||
|
||||
uc->ram_list.version++;
|
||||
|
||||
new_ram_size = last_ram_offset(uc) >> TARGET_PAGE_BITS;
|
||||
|
||||
if (new_ram_size > old_ram_size) {
|
||||
int i;
|
||||
for (i = 0; i < DIRTY_MEMORY_NUM; i++) {
|
||||
uc->ram_list.dirty_memory[i] =
|
||||
bitmap_zero_extend(uc->ram_list.dirty_memory[i],
|
||||
old_ram_size, new_ram_size);
|
||||
}
|
||||
}
|
||||
cpu_physical_memory_set_dirty_range(uc, new_block->offset, new_block->length);
|
||||
|
||||
qemu_ram_setup_dump(new_block->host, new_block->length);
|
||||
//qemu_madvise(new_block->host, new_block->length, QEMU_MADV_HUGEPAGE);
|
||||
//qemu_madvise(new_block->host, new_block->length, QEMU_MADV_DONTFORK);
|
||||
|
||||
return new_block->offset;
|
||||
}
|
||||
|
||||
// return -1 on error
|
||||
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
|
||||
MemoryRegion *mr, Error **errp)
|
||||
MemoryRegion *mr)
|
||||
{
|
||||
RAMBlock *new_block;
|
||||
ram_addr_t addr;
|
||||
Error *local_err = NULL;
|
||||
|
||||
size = TARGET_PAGE_ALIGN(size);
|
||||
new_block = g_malloc0(sizeof(*new_block));
|
||||
@ -1061,23 +874,18 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
|
||||
|
||||
new_block->mr = mr;
|
||||
new_block->length = size;
|
||||
new_block->fd = -1;
|
||||
new_block->host = host;
|
||||
if (host) {
|
||||
new_block->flags |= RAM_PREALLOC;
|
||||
}
|
||||
addr = ram_block_add(mr->uc, new_block, &local_err);
|
||||
if (local_err) {
|
||||
g_free(new_block);
|
||||
error_propagate(errp, local_err);
|
||||
return -1;
|
||||
}
|
||||
addr = ram_block_add(mr->uc, new_block);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp)
|
||||
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr)
|
||||
{
|
||||
return qemu_ram_alloc_from_ptr(size, NULL, mr, errp);
|
||||
return qemu_ram_alloc_from_ptr(size, NULL, mr);
|
||||
}
|
||||
|
||||
void qemu_ram_free_from_ptr(struct uc_struct *uc, ram_addr_t addr)
|
||||
@ -1088,7 +896,6 @@ void qemu_ram_free_from_ptr(struct uc_struct *uc, ram_addr_t addr)
|
||||
if (addr == block->offset) {
|
||||
QTAILQ_REMOVE(&uc->ram_list.blocks, block, next);
|
||||
uc->ram_list.mru_block = NULL;
|
||||
uc->ram_list.version++;
|
||||
g_free(block);
|
||||
break;
|
||||
}
|
||||
@ -1103,15 +910,7 @@ void qemu_ram_free(struct uc_struct *uc, ram_addr_t addr)
|
||||
if (addr == block->offset) {
|
||||
QTAILQ_REMOVE(&uc->ram_list.blocks, block, next);
|
||||
uc->ram_list.mru_block = NULL;
|
||||
uc->ram_list.version++;
|
||||
if (block->flags & RAM_PREALLOC) {
|
||||
;
|
||||
#ifndef _WIN32
|
||||
} else if (block->fd >= 0) {
|
||||
munmap(block->host, block->length);
|
||||
close(block->fd);
|
||||
#endif
|
||||
} else {
|
||||
if (!block->flags) {
|
||||
qemu_anon_ram_free(block->host, block->length);
|
||||
}
|
||||
g_free(block);
|
||||
@ -1120,62 +919,6 @@ void qemu_ram_free(struct uc_struct *uc, ram_addr_t addr)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void qemu_ram_remap(struct uc_struct *uc, ram_addr_t addr, ram_addr_t length)
|
||||
{
|
||||
RAMBlock *block;
|
||||
ram_addr_t offset;
|
||||
int flags;
|
||||
void *area, *vaddr;
|
||||
|
||||
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
|
||||
offset = addr - block->offset;
|
||||
if (offset < block->length) {
|
||||
vaddr = block->host + offset;
|
||||
if (block->flags & RAM_PREALLOC) {
|
||||
;
|
||||
} else {
|
||||
flags = MAP_FIXED;
|
||||
munmap(vaddr, length);
|
||||
if (block->fd >= 0) {
|
||||
flags |= (block->flags & RAM_SHARED ?
|
||||
MAP_SHARED : MAP_PRIVATE);
|
||||
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|
||||
flags, block->fd, offset);
|
||||
} else {
|
||||
/*
|
||||
* Remap needs to match alloc. Accelerators that
|
||||
* set phys_mem_alloc never remap. If they did,
|
||||
* we'd need a remap hook here.
|
||||
*/
|
||||
assert(phys_mem_alloc == qemu_anon_ram_alloc);
|
||||
|
||||
flags |= MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|
||||
flags, -1, 0);
|
||||
}
|
||||
if (area == MAP_FAILED || area != vaddr) {
|
||||
fprintf(stderr, "Could not remap addr: "
|
||||
RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
|
||||
length, addr);
|
||||
exit(1);
|
||||
}
|
||||
memory_try_enable_merging(vaddr, length);
|
||||
qemu_ram_setup_dump(vaddr, length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
int qemu_get_ram_fd(struct uc_struct *uc, ram_addr_t addr)
|
||||
{
|
||||
RAMBlock *block = qemu_get_ram_block(uc, addr);
|
||||
|
||||
return block->fd;
|
||||
}
|
||||
|
||||
void *qemu_get_ram_block_host_ptr(struct uc_struct *uc, ram_addr_t addr)
|
||||
{
|
||||
RAMBlock *block = qemu_get_ram_block(uc, addr);
|
||||
@ -1362,8 +1105,8 @@ static void notdirty_mem_write(struct uc_struct* uc, void *opaque, hwaddr ram_ad
|
||||
/* we remove the notdirty callback only if the code has been
|
||||
flushed */
|
||||
if (!cpu_physical_memory_is_clean(uc, ram_addr)) {
|
||||
CPUArchState *env = uc->current_cpu->env_ptr;
|
||||
tlb_set_dirty(env, uc->current_cpu->mem_io_vaddr);
|
||||
CPUArchState *env = uc->cpu->env_ptr;
|
||||
tlb_set_dirty(env, uc->cpu->mem_io_vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1384,13 +1127,12 @@ static const MemoryRegionOps notdirty_mem_ops = {
|
||||
|
||||
static void io_mem_init(struct uc_struct* uc)
|
||||
{
|
||||
memory_region_init_io(uc, &uc->io_mem_rom, NULL, &unassigned_mem_ops, NULL, NULL, UINT64_MAX);
|
||||
memory_region_init_io(uc, &uc->io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
|
||||
memory_region_init_io(uc, &uc->io_mem_rom, &unassigned_mem_ops,
|
||||
NULL, UINT64_MAX);
|
||||
memory_region_init_io(uc, &uc->io_mem_notdirty, NULL, ¬dirty_mem_ops, NULL,
|
||||
memory_region_init_io(uc, &uc->io_mem_unassigned, &unassigned_mem_ops,
|
||||
NULL, UINT64_MAX);
|
||||
memory_region_init_io(uc, &uc->io_mem_notdirty, ¬dirty_mem_ops,
|
||||
NULL, UINT64_MAX);
|
||||
//memory_region_init_io(uc, &uc->io_mem_watch, NULL, &watch_mem_ops, NULL,
|
||||
// NULL, UINT64_MAX);
|
||||
}
|
||||
|
||||
static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
|
||||
@ -1401,8 +1143,7 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
|
||||
|
||||
mmio->as = as;
|
||||
mmio->base = base;
|
||||
memory_region_init_io(as->uc, &mmio->iomem, NULL, &subpage_ops, mmio,
|
||||
NULL, TARGET_PAGE_SIZE);
|
||||
memory_region_init_io(as->uc, &mmio->iomem, &subpage_ops, mmio, TARGET_PAGE_SIZE);
|
||||
mmio->iomem.subpage = true;
|
||||
#if defined(DEBUG_SUBPAGE)
|
||||
printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
|
||||
@ -1453,8 +1194,6 @@ static void mem_begin(MemoryListener *listener)
|
||||
assert(n == PHYS_SECTION_NOTDIRTY);
|
||||
n = dummy_section(&d->map, as, &uc->io_mem_rom);
|
||||
assert(n == PHYS_SECTION_ROM);
|
||||
// n = dummy_section(&d->map, as, &uc->io_mem_watch);
|
||||
// assert(n == PHYS_SECTION_WATCH);
|
||||
|
||||
d->phys_map = ppe;
|
||||
d->as = as;
|
||||
@ -1528,16 +1267,13 @@ void address_space_destroy_dispatch(AddressSpace *as)
|
||||
static void memory_map_init(struct uc_struct *uc)
|
||||
{
|
||||
uc->system_memory = g_malloc(sizeof(*(uc->system_memory)));
|
||||
|
||||
memory_region_init(uc, uc->system_memory, NULL, "system", UINT64_MAX);
|
||||
address_space_init(uc, &uc->as, uc->system_memory, "memory");
|
||||
memory_region_init(uc, uc->system_memory, UINT64_MAX);
|
||||
address_space_init(uc, &uc->as, uc->system_memory);
|
||||
}
|
||||
|
||||
void cpu_exec_init_all(struct uc_struct *uc)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
memory_map_init(uc);
|
||||
#endif
|
||||
io_mem_init(uc);
|
||||
}
|
||||
|
||||
@ -1546,51 +1282,7 @@ MemoryRegion *get_system_memory(struct uc_struct *uc)
|
||||
return uc->system_memory;
|
||||
}
|
||||
|
||||
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||
|
||||
/* physical memory access (slow version, mainly for debug) */
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
||||
uint8_t *buf, int len, int is_write)
|
||||
{
|
||||
int l, flags;
|
||||
target_ulong page;
|
||||
void * p;
|
||||
|
||||
while (len > 0) {
|
||||
page = addr & TARGET_PAGE_MASK;
|
||||
l = (page + TARGET_PAGE_SIZE) - addr;
|
||||
if (l > len)
|
||||
l = len;
|
||||
flags = page_get_flags(page);
|
||||
if (!(flags & PAGE_VALID))
|
||||
return -1;
|
||||
if (is_write) {
|
||||
if (!(flags & PAGE_WRITE))
|
||||
return -1;
|
||||
/* XXX: this code should not depend on lock_user */
|
||||
if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
|
||||
return -1;
|
||||
memcpy(p, buf, l);
|
||||
unlock_user(p, addr, l);
|
||||
} else {
|
||||
if (!(flags & PAGE_READ))
|
||||
return -1;
|
||||
/* XXX: this code should not depend on lock_user */
|
||||
if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
|
||||
return -1;
|
||||
memcpy(buf, p, l);
|
||||
unlock_user(p, addr, 0);
|
||||
}
|
||||
len -= l;
|
||||
buf += l;
|
||||
addr += l;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void invalidate_and_set_dirty(struct uc_struct *uc, hwaddr addr,
|
||||
hwaddr length)
|
||||
{
|
||||
@ -1759,23 +1451,19 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
|
||||
l = len;
|
||||
mr = address_space_translate(as, addr, &addr1, &l, true);
|
||||
|
||||
if (!(memory_region_is_ram(mr) ||
|
||||
memory_region_is_romd(mr))) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
addr1 += memory_region_get_ram_addr(mr);
|
||||
/* ROM/RAM case */
|
||||
ptr = qemu_get_ram_ptr(as->uc, addr1);
|
||||
switch (type) {
|
||||
case WRITE_DATA:
|
||||
memcpy(ptr, buf, l);
|
||||
invalidate_and_set_dirty(as->uc, addr1, l);
|
||||
break;
|
||||
case FLUSH_CACHE:
|
||||
flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
|
||||
break;
|
||||
}
|
||||
addr1 += memory_region_get_ram_addr(mr);
|
||||
/* ROM/RAM case */
|
||||
ptr = qemu_get_ram_ptr(as->uc, addr1);
|
||||
switch (type) {
|
||||
case WRITE_DATA:
|
||||
memcpy(ptr, buf, l);
|
||||
invalidate_and_set_dirty(as->uc, addr1, l);
|
||||
break;
|
||||
case FLUSH_CACHE:
|
||||
flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
|
||||
break;
|
||||
}
|
||||
|
||||
len -= l;
|
||||
buf += l;
|
||||
addr += l;
|
||||
@ -1832,8 +1520,6 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_
|
||||
* May map a subset of the requested range, given by and returned in *plen.
|
||||
* May return NULL if resources needed to perform the mapping are exhausted.
|
||||
* Use only for reads OR writes - not for read-modify-write operations.
|
||||
* Use cpu_register_map_client() to know when retrying the map operation is
|
||||
* likely to succeed.
|
||||
*/
|
||||
void *address_space_map(AddressSpace *as,
|
||||
hwaddr addr,
|
||||
@ -1862,7 +1548,6 @@ void *address_space_map(AddressSpace *as,
|
||||
as->uc->bounce.addr = addr;
|
||||
as->uc->bounce.len = l;
|
||||
|
||||
memory_region_ref(mr);
|
||||
as->uc->bounce.mr = mr;
|
||||
if (!is_write) {
|
||||
address_space_read(as, addr, as->uc->bounce.buffer, l);
|
||||
@ -1890,7 +1575,6 @@ void *address_space_map(AddressSpace *as,
|
||||
}
|
||||
}
|
||||
|
||||
memory_region_ref(mr);
|
||||
*plen = done;
|
||||
return qemu_ram_ptr_length(as->uc, raddr + base, plen);
|
||||
}
|
||||
@ -1911,7 +1595,6 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
|
||||
if (is_write) {
|
||||
invalidate_and_set_dirty(as->uc, addr1, access_len);
|
||||
}
|
||||
memory_region_unref(mr);
|
||||
return;
|
||||
}
|
||||
if (is_write) {
|
||||
@ -1919,7 +1602,6 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
|
||||
}
|
||||
qemu_vfree(as->uc->bounce.buffer);
|
||||
as->uc->bounce.buffer = NULL;
|
||||
memory_region_unref(as->uc->bounce.mr);
|
||||
}
|
||||
|
||||
void *cpu_physical_memory_map(AddressSpace *as, hwaddr addr,
|
||||
@ -2308,7 +1990,6 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A helper function for the _utterly broken_ virtio device model to find out if
|
||||
@ -2324,7 +2005,6 @@ bool target_words_bigendian(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
bool cpu_physical_memory_is_io(AddressSpace *as, hwaddr phys_addr)
|
||||
{
|
||||
MemoryRegion*mr;
|
||||
@ -2332,8 +2012,7 @@ bool cpu_physical_memory_is_io(AddressSpace *as, hwaddr phys_addr)
|
||||
|
||||
mr = address_space_translate(as, phys_addr, &phys_addr, &l, false);
|
||||
|
||||
return !(memory_region_is_ram(mr) ||
|
||||
memory_region_is_romd(mr));
|
||||
return !(memory_region_is_ram(mr));
|
||||
}
|
||||
|
||||
void qemu_ram_foreach_block(struct uc_struct *uc, RAMBlockIterFunc func, void *opaque)
|
||||
@ -2344,4 +2023,3 @@ void qemu_ram_foreach_block(struct uc_struct *uc, RAMBlockIterFunc func, void *o
|
||||
func(block->host, block->offset, block->length, opaque);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
for d in x86_64 arm armeb m68k aarch64 aarch64eb mips mipsel mips64 mips64el sparc sparc64; do
|
||||
for d in x86_64 arm armeb m68k aarch64 aarch64eb mips mipsel mips64 mips64el sparc sparc64 ppc ppc64; do
|
||||
python header_gen.py $d > $d.h
|
||||
done
|
||||
|
@ -1455,3 +1455,18 @@ gchar** g_strsplit (const gchar *string,
|
||||
|
||||
return str_array;
|
||||
}
|
||||
|
||||
GSList *g_slist_find_custom (GSList *list, gconstpointer data, GCompareFunc func)
|
||||
{
|
||||
if (!func)
|
||||
return NULL;
|
||||
|
||||
while (list) {
|
||||
if (func (list->data, data) == 0)
|
||||
return list;
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -662,6 +662,8 @@ symbols = (
|
||||
'gen_helper_double_saturate',
|
||||
'gen_helper_exception_internal',
|
||||
'gen_helper_exception_with_syndrome',
|
||||
'gen_helper_float64_to_float32',
|
||||
'gen_helper_float32_to_float64',
|
||||
'gen_helper_get_cp_reg',
|
||||
'gen_helper_get_cp_reg64',
|
||||
'gen_helper_get_r13_banked',
|
||||
@ -1382,6 +1384,8 @@ symbols = (
|
||||
'helper_exception_internal',
|
||||
'helper_exception_return',
|
||||
'helper_exception_with_syndrome',
|
||||
'helper_float32_to_float64',
|
||||
'helper_float64_to_float32',
|
||||
'helper_get_cp_reg',
|
||||
'helper_get_cp_reg64',
|
||||
'helper_get_r13_banked',
|
||||
@ -2120,7 +2124,7 @@ symbols = (
|
||||
'object_child_foreach',
|
||||
'object_class_foreach',
|
||||
'object_class_foreach_tramp',
|
||||
'object_class_get_list',
|
||||
# 'object_class_get_list',
|
||||
'object_class_get_list_tramp',
|
||||
'object_class_get_parent',
|
||||
'object_deinit',
|
||||
@ -2378,7 +2382,6 @@ symbols = (
|
||||
'qemu_get_guest_simple_memory_mapping',
|
||||
'qemu_get_ram_block',
|
||||
'qemu_get_ram_block_host_ptr',
|
||||
'qemu_get_ram_fd',
|
||||
'qemu_get_ram_ptr',
|
||||
'qemu_host_page_mask',
|
||||
'qemu_host_page_size',
|
||||
@ -3027,6 +3030,7 @@ symbols = (
|
||||
|
||||
arm_symbols = (
|
||||
'ARM_REGS_STORAGE_SIZE',
|
||||
'arm_cpu_class_init',
|
||||
)
|
||||
|
||||
aarch64_symbols = (
|
||||
@ -3035,6 +3039,7 @@ aarch64_symbols = (
|
||||
'arm64_reg_reset',
|
||||
'arm64_reg_read',
|
||||
'arm64_reg_write',
|
||||
'arm_cpu_class_init',
|
||||
'gen_a64_set_pc_im',
|
||||
'aarch64_cpu_register_types',
|
||||
'helper_udiv64',
|
||||
@ -4052,7 +4057,14 @@ sparc_symbols = (
|
||||
'cpu_cwp_inc',
|
||||
'cpu_cwp_dec',
|
||||
'helper_save',
|
||||
'helper_restore')
|
||||
'helper_restore',
|
||||
'helper_divs',
|
||||
'helper_fsqrt')
|
||||
|
||||
ppc_symbols = (
|
||||
'helper_fsqrt',
|
||||
'helper_divs',
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@ -4081,5 +4093,9 @@ if __name__ == '__main__':
|
||||
for s in sparc_symbols:
|
||||
print("#define %s %s_%s" %(s, s, arch))
|
||||
|
||||
if 'ppc' in arch:
|
||||
for s in ppc_symbols:
|
||||
print("#define %s %s_%s" %(s, s, arch))
|
||||
|
||||
print("#endif")
|
||||
|
||||
|
@ -1,4 +1,2 @@
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += intc/
|
||||
devices-dirs-y += core/
|
||||
common-obj-y += $(devices-dirs-y)
|
||||
obj-y += $(devices-dirs-y)
|
||||
|
@ -1,2 +0,0 @@
|
||||
obj-y += tosa.o
|
||||
obj-y += virt.o
|
@ -1,45 +0,0 @@
|
||||
/* vim:set shiftwidth=4 ts=4 et: */
|
||||
/*
|
||||
* PXA255 Sharp Zaurus SL-6000 PDA platform
|
||||
*
|
||||
* Copyright (c) 2008 Dmitry Baryshkov
|
||||
*
|
||||
* Code based on spitz platform by Andrzej Zaborowski <balrog@zabor.org>
|
||||
* This code is licensed under the GNU GPL v2.
|
||||
*
|
||||
* Contributions after 2012-01-13 are licensed under the terms of the
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
|
||||
static int tosa_init(struct uc_struct *uc, MachineState *machine)
|
||||
{
|
||||
if (uc->mode & UC_MODE_MCLASS)
|
||||
uc->cpu = (CPUState *)cpu_arm_init(uc, "cortex-m3");
|
||||
else if (uc->mode & UC_MODE_ARM926)
|
||||
uc->cpu = (CPUState *)cpu_arm_init(uc, "arm926");
|
||||
else if (uc->mode & UC_MODE_ARM946)
|
||||
uc->cpu = (CPUState *)cpu_arm_init(uc, "arm946");
|
||||
else if (uc->mode & UC_MODE_ARM1176)
|
||||
uc->cpu = (CPUState *)cpu_arm_init(uc, "arm1176");
|
||||
else
|
||||
uc->cpu = (CPUState *)cpu_arm_init(uc, "cortex-a15");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tosa_machine_init(struct uc_struct *uc)
|
||||
{
|
||||
static QEMUMachine tosapda_machine = { 0 };
|
||||
tosapda_machine.name = "tosa",
|
||||
tosapda_machine.init = tosa_init,
|
||||
tosapda_machine.is_default = 1,
|
||||
tosapda_machine.arch = UC_ARCH_ARM,
|
||||
|
||||
qemu_register_machine(uc, &tosapda_machine, TYPE_MACHINE, NULL);
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* ARM mach-virt emulation
|
||||
*
|
||||
* Copyright (c) 2013 Linaro Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Emulate a virtual board which works by passing Linux all the information
|
||||
* it needs about what devices are present via the device tree.
|
||||
* There are some restrictions about what we can do here:
|
||||
* + we can only present devices whose Linux drivers will work based
|
||||
* purely on the device tree with no platform data at all
|
||||
* + we want to present a very stripped-down minimalist platform,
|
||||
* both because this reduces the security attack surface from the guest
|
||||
* and also because it reduces our exposure to being broken when
|
||||
* the kernel updates its device tree bindings and requires further
|
||||
* information in a device binding that we aren't providing.
|
||||
* This is essentially the same approach kvmtool uses.
|
||||
*/
|
||||
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh, 2015 */
|
||||
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
|
||||
static int machvirt_init(struct uc_struct *uc, MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
int n;
|
||||
|
||||
if (!cpu_model) {
|
||||
cpu_model = "cortex-a57"; // ARM64
|
||||
}
|
||||
|
||||
for (n = 0; n < smp_cpus; n++) {
|
||||
Object *cpuobj;
|
||||
ObjectClass *oc = cpu_class_by_name(uc, TYPE_ARM_CPU, cpu_model);
|
||||
|
||||
if (!oc) {
|
||||
fprintf(stderr, "Unable to find CPU definition\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cpuobj = object_new(uc, object_class_get_name(oc));
|
||||
uc->cpu = (CPUState *)cpuobj;
|
||||
object_property_set_bool(uc, cpuobj, true, "realized", NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void machvirt_machine_init(struct uc_struct *uc)
|
||||
{
|
||||
static QEMUMachine machvirt_a15_machine = { 0 };
|
||||
machvirt_a15_machine.name = "virt",
|
||||
machvirt_a15_machine.init = machvirt_init,
|
||||
machvirt_a15_machine.is_default = 1,
|
||||
machvirt_a15_machine.arch = UC_ARCH_ARM64,
|
||||
|
||||
qemu_register_machine(uc, &machvirt_a15_machine, TYPE_MACHINE, NULL);
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
# core qdev-related obj files, also used by *-user:
|
||||
common-obj-y += qdev.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += machine.o
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* QEMU Machine
|
||||
*
|
||||
* Copyright (C) 2014 Red Hat Inc
|
||||
*
|
||||
* Authors:
|
||||
* Marcel Apfelbaum <marcel.a@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "hw/boards.h"
|
||||
|
||||
static void machine_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
static void machine_finalize(struct uc_struct *uc, Object *obj, void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
static const TypeInfo machine_info = {
|
||||
TYPE_MACHINE,
|
||||
TYPE_OBJECT,
|
||||
|
||||
sizeof(MachineClass),
|
||||
sizeof(MachineState),
|
||||
NULL,
|
||||
|
||||
machine_initfn,
|
||||
NULL,
|
||||
machine_finalize,
|
||||
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
true,
|
||||
};
|
||||
|
||||
void machine_register_types(struct uc_struct *uc)
|
||||
{
|
||||
type_register_static(uc, &machine_info);
|
||||
}
|
@ -1,344 +0,0 @@
|
||||
/*
|
||||
* Dynamic device configuration and creation.
|
||||
*
|
||||
* Copyright (c) 2009 CodeSourcery
|
||||
*
|
||||
* 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 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/>.
|
||||
*/
|
||||
|
||||
/* The theory here is that it should be possible to create a machine without
|
||||
knowledge of specific devices. Historically board init routines have
|
||||
passed a bunch of arguments to each device, requiring the board know
|
||||
exactly which device it is dealing with. This file provides an abstract
|
||||
API for device configuration and initialization. Devices will generally
|
||||
inherit from a particular bus (e.g. PCI or I2C) rather than
|
||||
this API directly. */
|
||||
|
||||
#include "hw/qdev.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
|
||||
|
||||
static void bus_add_child(BusState *bus, DeviceState *child)
|
||||
{
|
||||
char name[32];
|
||||
BusChild *kid = g_malloc0(sizeof(*kid));
|
||||
|
||||
kid->index = bus->max_index++;
|
||||
kid->child = child;
|
||||
object_ref(OBJECT(kid->child));
|
||||
|
||||
QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
|
||||
|
||||
/* This transfers ownership of kid->child to the property. */
|
||||
snprintf(name, sizeof(name), "child[%d]", kid->index);
|
||||
object_property_add_link(OBJECT(bus), name,
|
||||
object_get_typename(OBJECT(child)),
|
||||
(Object **)&kid->child,
|
||||
NULL, /* read-only property */
|
||||
0, /* return ownership on prop deletion */
|
||||
NULL);
|
||||
}
|
||||
|
||||
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
|
||||
{
|
||||
dev->parent_bus = bus;
|
||||
object_ref(OBJECT(bus));
|
||||
bus_add_child(bus, dev);
|
||||
}
|
||||
|
||||
/* Create a new device. This only initializes the device state structure
|
||||
and allows properties to be set. qdev_init should be called to
|
||||
initialize the actual device emulation. */
|
||||
DeviceState *qdev_create(BusState *bus, const char *name)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_try_create(bus, name);
|
||||
if (!dev) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
DeviceState *qdev_try_create(BusState *bus, const char *type)
|
||||
{
|
||||
#if 0
|
||||
DeviceState *dev;
|
||||
|
||||
if (object_class_by_name(NULL, type) == NULL) { // no need to fix. aq
|
||||
return NULL;
|
||||
}
|
||||
dev = DEVICE(object_new(NULL, type)); // no need to fix. aq
|
||||
if (!dev) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!bus) {
|
||||
bus = sysbus_get_default();
|
||||
}
|
||||
|
||||
qdev_set_parent_bus(dev, bus);
|
||||
object_unref(OBJECT(dev));
|
||||
return dev;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize a device. Device properties should be set before calling
|
||||
this function. IRQs and MMIO regions should be connected/mapped after
|
||||
calling this function.
|
||||
On failure, destroy the device and return negative value.
|
||||
Return 0 on success. */
|
||||
int qdev_init(DeviceState *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BusState *qdev_get_parent_bus(DeviceState *dev)
|
||||
{
|
||||
return dev->parent_bus;
|
||||
}
|
||||
|
||||
static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
|
||||
{
|
||||
}
|
||||
|
||||
static void bus_unparent(struct uc_struct *uc, Object *obj)
|
||||
{
|
||||
BusState *bus = BUS(uc, obj);
|
||||
BusChild *kid;
|
||||
|
||||
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
|
||||
DeviceState *dev = kid->child;
|
||||
object_unparent(uc, OBJECT(dev));
|
||||
}
|
||||
if (bus->parent) {
|
||||
QLIST_REMOVE(bus, sibling);
|
||||
bus->parent->num_child_bus--;
|
||||
bus->parent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void qbus_create_inplace(void *bus, size_t size, const char *typename,
|
||||
DeviceState *parent, const char *name)
|
||||
{
|
||||
object_initialize(NULL, bus, size, typename); // unused, so no need to fix. aq
|
||||
qbus_realize(bus, parent, name);
|
||||
}
|
||||
|
||||
BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
|
||||
{
|
||||
BusState *bus;
|
||||
|
||||
bus = BUS(NULL, object_new(NULL, typename)); // no need to fix. aq
|
||||
qbus_realize(bus, parent, name);
|
||||
|
||||
return bus;
|
||||
}
|
||||
|
||||
static bool device_get_realized(struct uc_struct *uc, Object *obj, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(uc, obj);
|
||||
return dev->realized;
|
||||
}
|
||||
|
||||
static int device_set_realized(struct uc_struct *uc, Object *obj, bool value, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(uc, obj);
|
||||
DeviceClass *dc = DEVICE_GET_CLASS(uc, dev);
|
||||
BusState *bus;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (dev->hotplugged && !dc->hotpluggable) {
|
||||
error_set(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (value && !dev->realized) {
|
||||
#if 0
|
||||
if (!obj->parent) {
|
||||
static int unattached_count;
|
||||
gchar *name = g_strdup_printf("device[%d]", unattached_count++);
|
||||
|
||||
object_property_add_child(container_get(qdev_get_machine(),
|
||||
"/unattached"),
|
||||
name, obj, &error_abort);
|
||||
g_free(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dc->realize) {
|
||||
if (dc->realize(uc, dev, &local_err))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (local_err != NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (local_err != NULL) {
|
||||
goto post_realize_fail;
|
||||
}
|
||||
|
||||
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||
object_property_set_bool(uc, OBJECT(bus), true, "realized",
|
||||
&local_err);
|
||||
if (local_err != NULL) {
|
||||
goto child_realize_fail;
|
||||
}
|
||||
}
|
||||
if (dev->hotplugged) {
|
||||
device_reset(dev);
|
||||
}
|
||||
dev->pending_deleted_event = false;
|
||||
} else if (!value && dev->realized) {
|
||||
Error **local_errp = NULL;
|
||||
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||
local_errp = local_err ? NULL : &local_err;
|
||||
object_property_set_bool(uc, OBJECT(bus), false, "realized",
|
||||
local_errp);
|
||||
}
|
||||
if (dc->unrealize) {
|
||||
local_errp = local_err ? NULL : &local_err;
|
||||
dc->unrealize(dev, local_errp);
|
||||
}
|
||||
dev->pending_deleted_event = true;
|
||||
}
|
||||
|
||||
if (local_err != NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev->realized = value;
|
||||
return 0;
|
||||
|
||||
child_realize_fail:
|
||||
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||
object_property_set_bool(uc, OBJECT(bus), false, "realized",
|
||||
NULL);
|
||||
}
|
||||
|
||||
post_realize_fail:
|
||||
if (dc->unrealize) {
|
||||
dc->unrealize(dev, NULL);
|
||||
}
|
||||
|
||||
fail:
|
||||
error_propagate(errp, local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void device_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(uc, obj);
|
||||
|
||||
dev->instance_id_alias = -1;
|
||||
dev->realized = false;
|
||||
|
||||
object_property_add_bool(uc, obj, "realized",
|
||||
device_get_realized, device_set_realized, NULL);
|
||||
}
|
||||
|
||||
static void device_post_init(struct uc_struct *uc, Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
/* Unlink device from bus and free the structure. */
|
||||
static void device_finalize(struct uc_struct *uc, Object *obj, void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
static void device_class_base_init(ObjectClass *class, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void device_class_init(struct uc_struct *uc, ObjectClass *class, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
void device_reset(DeviceState *dev)
|
||||
{
|
||||
}
|
||||
|
||||
Object *qdev_get_machine(struct uc_struct *uc)
|
||||
{
|
||||
return container_get(uc, object_get_root(uc), "/machine");
|
||||
}
|
||||
|
||||
static const TypeInfo device_type_info = {
|
||||
TYPE_DEVICE,
|
||||
TYPE_OBJECT,
|
||||
|
||||
sizeof(DeviceClass),
|
||||
sizeof(DeviceState),
|
||||
NULL,
|
||||
|
||||
device_initfn,
|
||||
device_post_init,
|
||||
device_finalize,
|
||||
|
||||
NULL,
|
||||
|
||||
device_class_init,
|
||||
device_class_base_init,
|
||||
NULL,
|
||||
|
||||
true,
|
||||
};
|
||||
|
||||
static void qbus_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
static void bus_class_init(struct uc_struct *uc, ObjectClass *class, void *data)
|
||||
{
|
||||
class->unparent = bus_unparent;
|
||||
}
|
||||
|
||||
static void qbus_finalize(struct uc_struct *uc, Object *obj, void *opaque)
|
||||
{
|
||||
BusState *bus = BUS(uc, obj);
|
||||
|
||||
g_free((char *)bus->name);
|
||||
}
|
||||
|
||||
static const TypeInfo bus_info = {
|
||||
TYPE_BUS,
|
||||
TYPE_OBJECT,
|
||||
|
||||
sizeof(BusClass),
|
||||
sizeof(BusState),
|
||||
NULL,
|
||||
|
||||
qbus_initfn,
|
||||
NULL,
|
||||
qbus_finalize,
|
||||
|
||||
NULL,
|
||||
|
||||
bus_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
true,
|
||||
};
|
||||
|
||||
void qdev_register_types(struct uc_struct *uc)
|
||||
{
|
||||
type_register_static(uc, &bus_info);
|
||||
type_register_static(uc, &device_type_info);
|
||||
}
|
@ -1 +1 @@
|
||||
obj-y += pc.o pc_piix.o
|
||||
obj-y += pc.o
|
||||
|
@ -22,160 +22,12 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
/* Modified for Unicorn Engine by Nguyen Anh Quynh, 2015 */
|
||||
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi-visit.h"
|
||||
|
||||
|
||||
/* XXX: add IGNNE support */
|
||||
void cpu_set_ferr(CPUX86State *s)
|
||||
{
|
||||
// qemu_irq_raise(ferr_irq);
|
||||
}
|
||||
|
||||
/* TSC handling */
|
||||
uint64_t cpu_get_tsc(CPUX86State *env)
|
||||
{
|
||||
return cpu_get_ticks();
|
||||
}
|
||||
|
||||
/* SMM support */
|
||||
|
||||
static cpu_set_smm_t smm_set;
|
||||
static void *smm_arg;
|
||||
|
||||
void cpu_smm_register(cpu_set_smm_t callback, void *arg)
|
||||
{
|
||||
assert(smm_set == NULL);
|
||||
assert(smm_arg == NULL);
|
||||
smm_set = callback;
|
||||
smm_arg = arg;
|
||||
}
|
||||
|
||||
void cpu_smm_update(CPUX86State *env)
|
||||
{
|
||||
struct uc_struct *uc = x86_env_get_cpu(env)->parent_obj.uc;
|
||||
|
||||
if (smm_set && smm_arg && CPU(x86_env_get_cpu(env)) == uc->cpu) {
|
||||
smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* IRQ handling */
|
||||
int cpu_get_pic_interrupt(CPUX86State *env)
|
||||
{
|
||||
X86CPU *cpu = x86_env_get_cpu(env);
|
||||
int intno;
|
||||
|
||||
intno = apic_get_interrupt(cpu->apic_state);
|
||||
if (intno >= 0) {
|
||||
return intno;
|
||||
}
|
||||
/* read the irq from the PIC */
|
||||
if (!apic_accept_pic_intr(cpu->apic_state)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DeviceState *cpu_get_current_apic(struct uc_struct *uc)
|
||||
{
|
||||
if (uc->current_cpu) {
|
||||
X86CPU *cpu = X86_CPU(uc, uc->current_cpu);
|
||||
return cpu->apic_state;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static X86CPU *pc_new_cpu(struct uc_struct *uc, const char *cpu_model, int64_t apic_id,
|
||||
Error **errp)
|
||||
{
|
||||
X86CPU *cpu;
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu = cpu_x86_create(uc, cpu_model, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
object_property_set_int(uc, OBJECT(cpu), apic_id, "apic-id", &local_err);
|
||||
object_property_set_bool(uc, OBJECT(cpu), true, "realized", &local_err);
|
||||
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
object_unref(uc, OBJECT(cpu));
|
||||
cpu = NULL;
|
||||
}
|
||||
return cpu;
|
||||
}
|
||||
|
||||
int pc_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
{
|
||||
int i;
|
||||
Error *error = NULL;
|
||||
|
||||
/* init CPUs */
|
||||
if (cpu_model == NULL) {
|
||||
#ifdef TARGET_X86_64
|
||||
cpu_model = "qemu64";
|
||||
#else
|
||||
cpu_model = "qemu32";
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
uc->cpu = (CPUState *)pc_new_cpu(uc, cpu_model, x86_cpu_apic_id_from_index(i), &error);
|
||||
if (error) {
|
||||
//error_report("%s", error_get_pretty(error));
|
||||
error_free(error);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pc_machine_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
static void pc_machine_class_init(struct uc_struct *uc, ObjectClass *oc, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static const TypeInfo pc_machine_info = {
|
||||
TYPE_PC_MACHINE,
|
||||
TYPE_MACHINE,
|
||||
|
||||
sizeof(PCMachineClass),
|
||||
sizeof(PCMachineState),
|
||||
NULL,
|
||||
|
||||
pc_machine_initfn,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
|
||||
pc_machine_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
true,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
// should this be added somehow?
|
||||
//.interfaces = (InterfaceInfo[]) { { } },
|
||||
};
|
||||
|
||||
void pc_machine_register_types(struct uc_struct *uc)
|
||||
{
|
||||
type_register_static(uc, &pc_machine_info);
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* QEMU PC System Emulator
|
||||
*
|
||||
* Copyright (c) 2003-2004 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
/* Modified for Unicorn Engine by Nguyen Anh Quynh, 2015 */
|
||||
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "uc_priv.h"
|
||||
|
||||
|
||||
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
|
||||
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
|
||||
* pages in the host.
|
||||
*/
|
||||
#define GIGABYTE_ALIGN true
|
||||
|
||||
/* PC hardware initialisation */
|
||||
static int pc_init1(struct uc_struct *uc, MachineState *machine)
|
||||
{
|
||||
return pc_cpus_init(uc, machine->cpu_model);
|
||||
}
|
||||
|
||||
static int pc_init_pci(struct uc_struct *uc, MachineState *machine)
|
||||
{
|
||||
return pc_init1(uc, machine);
|
||||
}
|
||||
|
||||
static QEMUMachine pc_i440fx_machine_v2_2 = {
|
||||
"pc_piix",
|
||||
"pc-i440fx-2.2",
|
||||
pc_init_pci,
|
||||
NULL,
|
||||
255,
|
||||
1,
|
||||
UC_ARCH_X86, // X86
|
||||
};
|
||||
|
||||
static void pc_generic_machine_class_init(struct uc_struct *uc, ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(uc, oc);
|
||||
QEMUMachine *qm = data;
|
||||
|
||||
mc->family = qm->family;
|
||||
mc->name = qm->name;
|
||||
mc->init = qm->init;
|
||||
mc->reset = qm->reset;
|
||||
mc->max_cpus = qm->max_cpus;
|
||||
mc->is_default = qm->is_default;
|
||||
mc->arch = qm->arch;
|
||||
}
|
||||
|
||||
void pc_machine_init(struct uc_struct *uc);
|
||||
void pc_machine_init(struct uc_struct *uc)
|
||||
{
|
||||
qemu_register_machine(uc, &pc_i440fx_machine_v2_2,
|
||||
TYPE_PC_MACHINE, pc_generic_machine_class_init);
|
||||
}
|
@ -1 +0,0 @@
|
||||
obj-$(CONFIG_APIC) += apic.o apic_common.o
|
@ -1,230 +0,0 @@
|
||||
/*
|
||||
* APIC support
|
||||
*
|
||||
* Copyright (c) 2004-2005 Fabrice Bellard
|
||||
*
|
||||
* 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 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 "qemu/thread.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "hw/i386/apic.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "hw/i386/pc.h"
|
||||
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
#define MAX_APIC_WORDS 8
|
||||
|
||||
#define SYNC_FROM_VAPIC 0x1
|
||||
#define SYNC_TO_VAPIC 0x2
|
||||
#define SYNC_ISR_IRR_TO_VAPIC 0x4
|
||||
|
||||
static void apic_update_irq(APICCommonState *s);
|
||||
|
||||
/* Find first bit starting from msb */
|
||||
static int apic_fls_bit(uint32_t value)
|
||||
{
|
||||
return 31 - clz32(value);
|
||||
}
|
||||
|
||||
/* return -1 if no bit is set */
|
||||
static int get_highest_priority_int(uint32_t *tab)
|
||||
{
|
||||
int i;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
if (tab[i] != 0) {
|
||||
return i * 32 + apic_fls_bit(tab[i]);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void apic_sync_vapic(APICCommonState *s, int sync_type)
|
||||
{
|
||||
VAPICState vapic_state;
|
||||
//size_t length;
|
||||
//off_t start;
|
||||
int vector;
|
||||
|
||||
if (!s->vapic_paddr) {
|
||||
return;
|
||||
}
|
||||
if (sync_type & SYNC_FROM_VAPIC) {
|
||||
cpu_physical_memory_read(NULL, s->vapic_paddr, &vapic_state,
|
||||
sizeof(vapic_state));
|
||||
s->tpr = vapic_state.tpr;
|
||||
}
|
||||
if (sync_type & (SYNC_TO_VAPIC | SYNC_ISR_IRR_TO_VAPIC)) {
|
||||
//start = offsetof(VAPICState, isr);
|
||||
//length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr);
|
||||
|
||||
if (sync_type & SYNC_TO_VAPIC) {
|
||||
|
||||
vapic_state.tpr = s->tpr;
|
||||
vapic_state.enabled = 1;
|
||||
//start = 0;
|
||||
//length = sizeof(VAPICState);
|
||||
}
|
||||
|
||||
vector = get_highest_priority_int(s->isr);
|
||||
if (vector < 0) {
|
||||
vector = 0;
|
||||
}
|
||||
vapic_state.isr = vector & 0xf0;
|
||||
|
||||
vapic_state.zero = 0;
|
||||
|
||||
vector = get_highest_priority_int(s->irr);
|
||||
if (vector < 0) {
|
||||
vector = 0;
|
||||
}
|
||||
vapic_state.irr = vector & 0xff;
|
||||
|
||||
//cpu_physical_memory_write_rom(&address_space_memory,
|
||||
// s->vapic_paddr + start,
|
||||
// ((void *)&vapic_state) + start, length);
|
||||
// FIXME qq
|
||||
}
|
||||
}
|
||||
|
||||
static void apic_vapic_base_update(APICCommonState *s)
|
||||
{
|
||||
apic_sync_vapic(s, SYNC_TO_VAPIC);
|
||||
}
|
||||
|
||||
#define foreach_apic(apic, deliver_bitmask, code) \
|
||||
{\
|
||||
int __i, __j;\
|
||||
for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
|
||||
uint32_t __mask = deliver_bitmask[__i];\
|
||||
if (__mask) {\
|
||||
for(__j = 0; __j < 32; __j++) {\
|
||||
if (__mask & (1U << __j)) {\
|
||||
apic = local_apics[__i * 32 + __j];\
|
||||
if (apic) {\
|
||||
code;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
static void apic_set_base(APICCommonState *s, uint64_t val)
|
||||
{
|
||||
s->apicbase = (val & 0xfffff000) |
|
||||
(s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
|
||||
/* if disabled, cannot be enabled again */
|
||||
if (!(val & MSR_IA32_APICBASE_ENABLE)) {
|
||||
s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
|
||||
cpu_clear_apic_feature(&s->cpu->env);
|
||||
s->spurious_vec &= ~APIC_SV_ENABLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void apic_set_tpr(APICCommonState *s, uint8_t val)
|
||||
{
|
||||
/* Updates from cr8 are ignored while the VAPIC is active */
|
||||
if (!s->vapic_paddr) {
|
||||
s->tpr = val << 4;
|
||||
apic_update_irq(s);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t apic_get_tpr(APICCommonState *s)
|
||||
{
|
||||
apic_sync_vapic(s, SYNC_FROM_VAPIC);
|
||||
return s->tpr >> 4;
|
||||
}
|
||||
|
||||
/* signal the CPU if an irq is pending */
|
||||
static void apic_update_irq(APICCommonState *s)
|
||||
{
|
||||
}
|
||||
|
||||
void apic_poll_irq(DeviceState *dev)
|
||||
{
|
||||
}
|
||||
|
||||
void apic_sipi(DeviceState *dev)
|
||||
{
|
||||
}
|
||||
|
||||
int apic_get_interrupt(DeviceState *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apic_accept_pic_intr(DeviceState *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void apic_pre_save(APICCommonState *s)
|
||||
{
|
||||
apic_sync_vapic(s, SYNC_FROM_VAPIC);
|
||||
}
|
||||
|
||||
static void apic_post_load(APICCommonState *s)
|
||||
{
|
||||
#if 0
|
||||
if (s->timer_expiry != -1) {
|
||||
timer_mod(s->timer, s->timer_expiry);
|
||||
} else {
|
||||
timer_del(s->timer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int apic_realize(struct uc_struct *uc, DeviceState *dev, Error **errp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void apic_class_init(struct uc_struct *uc, ObjectClass *klass, void *data)
|
||||
{
|
||||
APICCommonClass *k = APIC_COMMON_CLASS(uc, klass);
|
||||
|
||||
k->realize = apic_realize;
|
||||
k->set_base = apic_set_base;
|
||||
k->set_tpr = apic_set_tpr;
|
||||
k->get_tpr = apic_get_tpr;
|
||||
k->vapic_base_update = apic_vapic_base_update;
|
||||
k->pre_save = apic_pre_save;
|
||||
k->post_load = apic_post_load;
|
||||
//printf("... init apic class\n");
|
||||
}
|
||||
|
||||
static const TypeInfo apic_info = {
|
||||
"apic",
|
||||
TYPE_APIC_COMMON,
|
||||
|
||||
0,
|
||||
sizeof(APICCommonState),
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
|
||||
apic_class_init,
|
||||
};
|
||||
|
||||
void apic_register_types(struct uc_struct *uc)
|
||||
{
|
||||
//printf("... register apic types\n");
|
||||
type_register_static(uc, &apic_info);
|
||||
}
|
@ -1,274 +0,0 @@
|
||||
/*
|
||||
* APIC support - common bits of emulated and KVM kernel model
|
||||
*
|
||||
* Copyright (c) 2004-2005 Fabrice Bellard
|
||||
* Copyright (c) 2011 Jan Kiszka, Siemens AG
|
||||
*
|
||||
* 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 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 "hw/i386/apic.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "hw/qdev.h"
|
||||
|
||||
#include "uc_priv.h"
|
||||
|
||||
|
||||
void cpu_set_apic_base(struct uc_struct *uc, DeviceState *dev, uint64_t val)
|
||||
{
|
||||
if (dev) {
|
||||
APICCommonState *s = APIC_COMMON(uc, dev);
|
||||
APICCommonClass *info = APIC_COMMON_GET_CLASS(uc, s);
|
||||
info->set_base(s, val);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t cpu_get_apic_base(struct uc_struct *uc, DeviceState *dev)
|
||||
{
|
||||
if (dev) {
|
||||
APICCommonState *s = APIC_COMMON(uc, dev);
|
||||
return s->apicbase;
|
||||
} else {
|
||||
return MSR_IA32_APICBASE_BSP;
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_set_apic_tpr(struct uc_struct *uc, DeviceState *dev, uint8_t val)
|
||||
{
|
||||
APICCommonState *s;
|
||||
APICCommonClass *info;
|
||||
|
||||
if (!dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
s = APIC_COMMON(uc, dev);
|
||||
info = APIC_COMMON_GET_CLASS(uc, s);
|
||||
|
||||
info->set_tpr(s, val);
|
||||
}
|
||||
|
||||
uint8_t cpu_get_apic_tpr(struct uc_struct *uc, DeviceState *dev)
|
||||
{
|
||||
APICCommonState *s;
|
||||
APICCommonClass *info;
|
||||
|
||||
if (!dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = APIC_COMMON(uc, dev);
|
||||
info = APIC_COMMON_GET_CLASS(uc, s);
|
||||
|
||||
return info->get_tpr(s);
|
||||
}
|
||||
|
||||
void apic_enable_vapic(struct uc_struct *uc, DeviceState *dev, hwaddr paddr)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(uc, dev);
|
||||
APICCommonClass *info = APIC_COMMON_GET_CLASS(uc, s);
|
||||
|
||||
s->vapic_paddr = paddr;
|
||||
info->vapic_base_update(s);
|
||||
}
|
||||
|
||||
void apic_handle_tpr_access_report(DeviceState *dev, target_ulong ip,
|
||||
TPRAccess access)
|
||||
{
|
||||
//APICCommonState *s = APIC_COMMON(NULL, dev);
|
||||
|
||||
//vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access);
|
||||
}
|
||||
|
||||
bool apic_next_timer(APICCommonState *s, int64_t current_time)
|
||||
{
|
||||
int64_t d;
|
||||
|
||||
/* We need to store the timer state separately to support APIC
|
||||
* implementations that maintain a non-QEMU timer, e.g. inside the
|
||||
* host kernel. This open-coded state allows us to migrate between
|
||||
* both models. */
|
||||
s->timer_expiry = -1;
|
||||
|
||||
if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
d = (current_time - s->initial_count_load_time) >> s->count_shift;
|
||||
|
||||
if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
|
||||
if (!s->initial_count) {
|
||||
return false;
|
||||
}
|
||||
d = ((d / ((uint64_t)s->initial_count + 1)) + 1) *
|
||||
((uint64_t)s->initial_count + 1);
|
||||
} else {
|
||||
if (d >= s->initial_count) {
|
||||
return false;
|
||||
}
|
||||
d = (uint64_t)s->initial_count + 1;
|
||||
}
|
||||
s->next_time = s->initial_count_load_time + (d << s->count_shift);
|
||||
s->timer_expiry = s->next_time;
|
||||
return true;
|
||||
}
|
||||
|
||||
void apic_init_reset(struct uc_struct *uc, DeviceState *dev)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(uc, dev);
|
||||
APICCommonClass *info = APIC_COMMON_GET_CLASS(uc, s);
|
||||
int i;
|
||||
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
s->tpr = 0;
|
||||
s->spurious_vec = 0xff;
|
||||
s->log_dest = 0;
|
||||
s->dest_mode = 0xf;
|
||||
memset(s->isr, 0, sizeof(s->isr));
|
||||
memset(s->tmr, 0, sizeof(s->tmr));
|
||||
memset(s->irr, 0, sizeof(s->irr));
|
||||
for (i = 0; i < APIC_LVT_NB; i++) {
|
||||
s->lvt[i] = APIC_LVT_MASKED;
|
||||
}
|
||||
s->esr = 0;
|
||||
memset(s->icr, 0, sizeof(s->icr));
|
||||
s->divide_conf = 0;
|
||||
s->count_shift = 0;
|
||||
s->initial_count = 0;
|
||||
s->initial_count_load_time = 0;
|
||||
s->next_time = 0;
|
||||
s->wait_for_sipi = !cpu_is_bsp(s->cpu);
|
||||
|
||||
if (s->timer) {
|
||||
// timer_del(s->timer);
|
||||
}
|
||||
s->timer_expiry = -1;
|
||||
|
||||
if (info->reset) {
|
||||
info->reset(s);
|
||||
}
|
||||
}
|
||||
|
||||
void apic_designate_bsp(struct uc_struct *uc, DeviceState *dev)
|
||||
{
|
||||
APICCommonState *s;
|
||||
|
||||
if (dev == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
s = APIC_COMMON(uc, dev);
|
||||
s->apicbase |= MSR_IA32_APICBASE_BSP;
|
||||
}
|
||||
|
||||
static void apic_reset_common(struct uc_struct *uc, DeviceState *dev)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(uc, dev);
|
||||
APICCommonClass *info = APIC_COMMON_GET_CLASS(uc, s);
|
||||
bool bsp;
|
||||
|
||||
bsp = cpu_is_bsp(s->cpu);
|
||||
s->apicbase = APIC_DEFAULT_ADDRESS |
|
||||
(bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
|
||||
|
||||
s->vapic_paddr = 0;
|
||||
info->vapic_base_update(s);
|
||||
|
||||
apic_init_reset(uc, dev);
|
||||
|
||||
if (bsp) {
|
||||
/*
|
||||
* LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
|
||||
* time typically by BIOS, so PIC interrupt can be delivered to the
|
||||
* processor when local APIC is enabled.
|
||||
*/
|
||||
s->lvt[APIC_LVT_LINT0] = 0x700;
|
||||
}
|
||||
}
|
||||
|
||||
static int apic_common_realize(struct uc_struct *uc, DeviceState *dev, Error **errp)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(uc, dev);
|
||||
APICCommonClass *info;
|
||||
|
||||
if (uc->apic_no >= MAX_APICS) {
|
||||
error_setg(errp, "%s initialization failed.",
|
||||
object_get_typename(OBJECT(dev)));
|
||||
return -1;
|
||||
}
|
||||
s->idx = uc->apic_no++;
|
||||
|
||||
info = APIC_COMMON_GET_CLASS(uc, s);
|
||||
info->realize(uc, dev, errp);
|
||||
if (!uc->mmio_registered) {
|
||||
ICCBus *b = ICC_BUS(uc, qdev_get_parent_bus(dev));
|
||||
memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory);
|
||||
uc->mmio_registered = true;
|
||||
}
|
||||
|
||||
/* Note: We need at least 1M to map the VAPIC option ROM */
|
||||
if (!uc->vapic && s->vapic_control & VAPIC_ENABLE_MASK) {
|
||||
// ram_size >= 1024 * 1024) { // FIXME
|
||||
uc->vapic = NULL;
|
||||
}
|
||||
s->vapic = uc->vapic;
|
||||
if (uc->apic_report_tpr_access && info->enable_tpr_reporting) {
|
||||
info->enable_tpr_reporting(s, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void apic_common_class_init(struct uc_struct *uc, ObjectClass *klass, void *data)
|
||||
{
|
||||
ICCDeviceClass *idc = ICC_DEVICE_CLASS(uc, klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(uc, klass);
|
||||
|
||||
dc->reset = apic_reset_common;
|
||||
idc->realize = apic_common_realize;
|
||||
/*
|
||||
* Reason: APIC and CPU need to be wired up by
|
||||
* x86_cpu_apic_create()
|
||||
*/
|
||||
dc->cannot_instantiate_with_device_add_yet = true;
|
||||
//printf("... init apic common class\n");
|
||||
}
|
||||
|
||||
static const TypeInfo apic_common_type = {
|
||||
TYPE_APIC_COMMON,
|
||||
TYPE_DEVICE,
|
||||
|
||||
sizeof(APICCommonClass),
|
||||
sizeof(APICCommonState),
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
|
||||
apic_common_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
true,
|
||||
};
|
||||
|
||||
void apic_common_register_types(struct uc_struct *uc)
|
||||
{
|
||||
//printf("... register apic common\n");
|
||||
type_register_static(uc, &apic_common_type);
|
||||
}
|
@ -1 +0,0 @@
|
||||
obj-y += dummy_m68k.o
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Dummy board with just RAM and CPU for use as an ISS.
|
||||
*
|
||||
* Copyright (c) 2007 CodeSourcery.
|
||||
*
|
||||
* This code is licensed under the GPL
|
||||
*/
|
||||
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh, 2015 */
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/m68k/m68k.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
|
||||
/* Board init. */
|
||||
static int dummy_m68k_init(struct uc_struct *uc, MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
CPUM68KState *env;
|
||||
|
||||
if (!cpu_model)
|
||||
cpu_model = "cfv4e";
|
||||
|
||||
env = cpu_init(uc, cpu_model);
|
||||
if (!env) {
|
||||
fprintf(stderr, "Unable to find m68k CPU definition\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize CPU registers. */
|
||||
env->vbr = 0;
|
||||
env->pc = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dummy_m68k_machine_init(struct uc_struct *uc)
|
||||
{
|
||||
static QEMUMachine dummy_m68k_machine = { 0 };
|
||||
dummy_m68k_machine.name = "dummy",
|
||||
dummy_m68k_machine.init = dummy_m68k_init,
|
||||
dummy_m68k_machine.is_default = 1,
|
||||
dummy_m68k_machine.arch = UC_ARCH_M68K,
|
||||
|
||||
//printf(">>> dummy_m68k_machine_init\n");
|
||||
qemu_register_machine(uc, &dummy_m68k_machine, TYPE_MACHINE, NULL);
|
||||
}
|
@ -1,2 +1 @@
|
||||
obj-y += mips_r4k.o
|
||||
obj-y += addr.o cputimer.o
|
||||
obj-y += cputimer.o
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* QEMU MIPS address translation support
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
|
||||
uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr & 0x1fffffffll;
|
||||
}
|
||||
|
||||
uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr | ~0x7fffffffll;
|
||||
}
|
||||
|
||||
uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr | 0x40000000ll;
|
||||
}
|
@ -19,11 +19,11 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
/* Modified for Unicorn Engine by Chen Huitao<chenhuitao@hfmrit.com>, 2020 */
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
/* from qemu/hw/mips/cpitimer.c */
|
||||
#define TIMER_FREQ 100 * 1000 * 1000
|
||||
|
||||
/* XXX: do not use a global */
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* QEMU/MIPS pseudo-board
|
||||
*
|
||||
* emulates a simple machine with ISA-like bus.
|
||||
* ISA IO space mapped to the 0x14000000 (PHYS) and
|
||||
* ISA memory at the 0x10000000 (PHYS, 16Mb in size).
|
||||
* All peripherial devices are attached to this "bus" with
|
||||
* the standard PC ISA addresses.
|
||||
*/
|
||||
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh, 2015 */
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/mips/mips.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
|
||||
static int mips_r4k_init(struct uc_struct *uc, MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
|
||||
/* init CPUs */
|
||||
if (cpu_model == NULL) {
|
||||
#ifdef TARGET_MIPS64
|
||||
cpu_model = "R4000";
|
||||
#else
|
||||
cpu_model = "24Kf";
|
||||
#endif
|
||||
}
|
||||
|
||||
uc->cpu = (void*) cpu_mips_init(uc, cpu_model);
|
||||
if (uc->cpu == NULL) {
|
||||
fprintf(stderr, "Unable to find CPU definition\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mips_machine_init(struct uc_struct *uc)
|
||||
{
|
||||
static QEMUMachine mips_machine = {
|
||||
NULL,
|
||||
"mips",
|
||||
mips_r4k_init,
|
||||
NULL,
|
||||
0,
|
||||
1,
|
||||
UC_ARCH_MIPS,
|
||||
};
|
||||
|
||||
qemu_register_machine(uc, &mips_machine, TYPE_MACHINE, NULL);
|
||||
}
|
13
qemu/hw/ppc/Makefile.objs
Normal file
13
qemu/hw/ppc/Makefile.objs
Normal file
@ -0,0 +1,13 @@
|
||||
# shared objects
|
||||
obj-y += ppc.o ppc_booke.o
|
||||
# IBM pSeries (sPAPR)
|
||||
#obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
|
||||
#obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
|
||||
#obj-$(CONFIG_PSERIES) += spapr_pci.o
|
||||
# PReP
|
||||
#obj-$(CONFIG_PREP) += prep.o
|
||||
# e500
|
||||
#obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
|
||||
#obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
|
||||
#obj-y += e500plat.o
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user