Compare commits

...

110 Commits
master ... next

Author SHA1 Message Date
Simon Wörner
66df39ebc9
Improve Rust bindings (#1367)
* fixed tests

* constant readability

* HookType as bitflags

* Mode as bitflags

* improve bitflags

* cargo fmt

* removed unnecessary "as usize"
2021-05-08 18:48:50 +08:00
Nguyen Anh Quynh
1e457ecc66 cmake: enable UNICORN_HAS_ARMEB when ARM is on 2020-11-17 15:13:57 +08:00
Nguyen Anh Quynh
b2f253d732 copy .travis.yml from master branch 2020-11-17 13:09:22 +08:00
Nguyen Anh Quynh
fb667f5cdc merge master & fix conflicts 2020-11-17 13:07:34 +08:00
Jhe
19f8991cbb
fix HI/LO register read/write issue in MIPS (#1319)
* fix HI/LO register read/write issue in MIPS

* fix typo
2020-09-21 10:40:01 +08:00
Nikolas Eller
473405797d
Improved Rust bindings: (#1309)
* Added basic block hooking
* Changed confusing struct naming. Before: Protection::All -> R,W,X, Now: Permission::All -> R,W,X
* Fixed issue with remove_hook(..). Implementation tried to remove hook from incorrect hashmap.
* Made unused private vmmap(..) public.
2020-09-21 10:36:58 +08:00
Chen Huitao
848d52033e
fix aarch64 cpu init error. (#1307) 2020-09-17 18:03:36 +08:00
mogoreanu
3f56323fef
Removed unused bitmap_set rename bitmap_clear to qemu_bitmap_clear. (#1327)
When unicorn and systemd are included into a single binary they conflict
on the bitmap_clear function which breaks unicorn. It seems that
long-term we can remove the qemu_bitmap_clear altogether and leave only
bitmap_zero_extend.

Co-authored-by: Nicolae Mogoreanu <mogo@google.com>
2020-09-16 21:47:08 +08:00
Nguyen Anh Quynh
b22d4cfbb2 uc_struct: remove current_cpu 2020-06-27 21:59:58 +08:00
Nguyen Anh Quynh
0f0bf3ed83 uc_struct: delete block_addr field 2020-06-25 14:44:25 +08:00
Nguyen Anh Quynh
acc0d6cc9b restore MemoryRegion.enabled & delete io_mem_watch 2020-06-22 17:09:12 +08:00
Nguyen Anh Quynh
3db98ac1be cleanup memory api 2020-06-22 12:49:12 +08:00
Nguyen Anh Quynh
cae6f80e5e x86 cleanup 2020-06-21 11:48:14 +08:00
Nguyen Anh Quynh
ac30245e18 cleanup 2020-06-21 01:12:02 +08:00
Nguyen Anh Quynh
961fed7b11 clean cpus.h 2020-06-15 00:51:28 +08:00
Nguyen Anh Quynh
e0c89b7f2c cleanup qemu/include/exec/ 2020-06-15 00:45:58 +08:00
Nguyen Anh Quynh
38ddaf585f cleanup RAMList & exec.c 2020-06-15 00:16:18 +08:00
Nguyen Anh Quynh
036306579a simplify RAMBlock struct 2020-06-14 23:42:38 +08:00
Lukas Seidel
5a6344b8d8
Rust bindings (#1295)
* rust bindings init

* updated bindings/README
2020-06-14 21:39:59 +08:00
Nguyen Anh Quynh
297a78990d i386: remove hyperv stuff in X86CPU 2020-06-13 11:27:22 +08:00
Nguyen Anh Quynh
5b3a27721e cleanup 2020-06-12 19:37:02 +08:00
Nguyen Anh Quynh
6b091b755a i386: clean cpu.h 2020-06-12 13:48:56 +08:00
Nguyen Anh Quynh
8ce974b519 x86: remove eflags0 from CPUState 2020-06-12 13:05:27 +08:00
Nguyen Anh Quynh
d685bedac4 cleanup cpu.h of x86 2020-06-12 12:21:47 +08:00
Nguyen Anh Quynh
6b457f23ba clean CPUState 2020-06-12 11:11:53 +08:00
Nguyen Anh Quynh
07958cd846 remove MemoryRegin.iommu_ops 2020-06-11 21:21:06 +08:00
Nguyen Anh Quynh
e120cd03b4 simplify MemoryRegion 2020-06-11 20:55:13 +08:00
Nguyen Anh Quynh
db01ecd4be qemu_system_shutdown_request() to stop emulation 2020-06-11 18:14:17 +08:00
Nguyen Anh Quynh
f275ac6a9b cleanup memory_mapping.c 2020-06-11 18:00:13 +08:00
Nguyen Anh Quynh
b5917989b3 cleanup memory code 2020-06-11 17:41:37 +08:00
Nguyen Anh Quynh
cfaa329d36 remove dead code 2020-06-11 15:56:39 +08:00
Nguyen Anh Quynh
33bd9eadae simplify transaction & pending memory update 2020-06-11 15:50:16 +08:00
Nguyen Anh Quynh
ac05215a9c unicorn memory is not dirty 2020-06-11 13:11:30 +08:00
Nguyen Anh Quynh
f3b1d9fd20 Revert "cleanup parent_class"
This reverts commit b0c74bbee2.
2020-06-11 12:54:48 +08:00
Nguyen Anh Quynh
d531096586 cleanup 2020-06-11 01:56:32 +08:00
Nguyen Anh Quynh
b6b92391d6 cleanup 2020-06-10 11:43:42 +08:00
Nguyen Anh Quynh
c25c9d6be0 cleanup 2020-06-10 00:30:42 +08:00
Nguyen Anh Quynh
b0c74bbee2 cleanup parent_class 2020-06-09 22:21:10 +08:00
Chen Huitao
1ee37cc026
remove i386 and mips in hw (#1289)
* remove apic files. update make and cmake.

* remove default-configs dir.

* fix a mem-leak bug. remove owner arg in memory.

* fix a mem-leak bug.

* remove hw/i386, hw/mips.

* clean code.

* update cmake.

* restore code.
2020-06-09 19:32:24 +08:00
Nguyen Anh Quynh
84c6f0d82f cleanup 2020-06-08 18:32:31 +08:00
Nguyen Anh Quynh
df8237175f some more cleanup 2020-06-08 11:18:52 +08:00
Nguyen Anh Quynh
68f2bdc641 more cleanup for Makefile 2020-06-08 10:06:34 +08:00
Nguyen Anh Quynh
09d42b408a remove more dead files 2020-06-08 10:00:06 +08:00
Nguyen Anh Quynh
5605522d15 cleanup Makefile 2020-06-08 09:13:51 +08:00
Nguyen Anh Quynh
411648eb0c cleanup x86 code 2020-06-08 08:30:36 +08:00
Chen Huitao
c09adf5b7b
remove apci, default-congfigs (#1288)
* remove apic files. update make and cmake.

* remove default-configs dir.

* fix a mem-leak bug. remove owner arg in memory.
2020-06-08 08:21:44 +08:00
Nguyen Anh Quynh
a8f724010b cleanup disable code (from the commit removing qom qobject) 2020-06-07 23:51:44 +08:00
chenhuitao
6fc4fc41ec update cmake. remove warnings. 2020-06-07 04:57:03 +08:00
chenhuitao
a51715734a update PPC objs. only build libdecnumber while PPC is enabled. 2020-06-07 04:25:07 +08:00
chenhuitao
4ba2b30d18 Merge remote-tracking branch 'upstream/next' into next 2020-06-07 03:54:22 +08:00
chenhuitao
37e325643b remove qobject, qapi, qom... 2020-06-07 03:53:10 +08:00
John Zimmermann
cc586bdba6 cmake: fix build if workdir is outside of CMAKE_BINARY_DIR (#1284)
this e.g. happens if you would try to compile this like this:

cmake -B build
cmake --build build --config Release
2020-06-06 12:55:14 +08:00
Dominik Maier
7bd93c0d74 fix error handling of mmap() calls (#1283) 2020-06-06 12:52:36 +08:00
Nguyen Anh Quynh
b33c0afa63 save cpu->jmp_env in saving context, so uc_emu_start() can be reentrant. also improved Python binding on handling context 2020-06-06 12:52:00 +08:00
John Zimmermann
991d2432b3
cmake: fix static linking due to cyclic deps (#1281)
linking of samples like sample_arm do fail due to cyclic references in
the archives
2020-06-04 17:37:23 +08:00
Nguyen Anh Quynh
42bc8b1768 cmake: more typo fix of UNICRON (ppc) 2020-06-03 10:15:55 +08:00
scribam
a23ce3c27f cmake: fix typo "UNICRON" => "UNICORN" (#1277) 2020-06-03 10:14:33 +08:00
Nguyen Anh Quynh
0cfe8b9bad cmake: fix Visual Studio build with FI, following other archs 2020-06-02 16:08:24 +08:00
scribam
d3e55b1c2d cmake: fix Visual Studio build (#1276) 2020-06-02 16:06:15 +08:00
Nguyen Anh Quynh
fdb6494934 Merge branch 'next' of github.com:unicorn-engine/unicorn into next 2020-06-01 00:02:16 +08:00
scribam
1a68ae656f cmake: add option to build unicorn as a static library (#1275) 2020-06-01 00:02:05 +08:00
Stuart Dootson
b27af3398d
Update CREDITS.TXT (#1274) 2020-05-29 17:49:06 +08:00
Nguyen Anh Quynh
7292e5d6e4 python: add PPC to long description of setup.py 2020-05-29 11:59:24 +08:00
Nguyen Anh Quynh
eeb6208fb3 python: add long description to setup.py 2020-05-29 11:58:33 +08:00
Nguyen Anh Quynh
857b155bb8 CREDITS 2020-05-29 00:09:17 +08:00
Stuart Dootson
c5bae30b1d
Add Visual Studio project files for PowerPC support (#1272)
* Fix 64-bit enums for MSVC

As Windows has 32 bit ints (x86 or x64), enums in the Microsoft C compiler are only 32 bits. The PPC machine description uses 64 bit enum values, which won't work for MSVC. Replace them with #defines

* Add `ffs` implementation for Microsoft C/C++

* Remove GCC function attributes for non-GCC compilers

* Add macro to provide MSVC definition of strncasecmp

* Workaround MSVC pre-processor deficiencies

The MSVC preprocessor doesn't appear to like having a #if/#endif within a macro invocation. To placate it, surround two instances of the macro invocation (with appropriately different arguments!) with #if/#else/#endif

* Add Visual Studio project files for PowerPC

* Forgot to add PPC import library to x64 configurations
2020-05-29 00:07:56 +08:00
Nguyen Anh Quynh
b69126612d delete qemu/target-ppc/pointer_fix.py 2020-05-28 09:45:29 +08:00
chenhuitao
e33fcc2f30 Merge remote-tracking branch 'upstream/next' into next 2020-05-28 01:41:07 +08:00
Stuart Dootson
9bfa40184c
Make MSVC happy with the new PowerPC code (#1271)
* Fix 64-bit enums for MSVC

As Windows has 32 bit ints (x86 or x64), enums in the Microsoft C compiler are only 32 bits. The PPC machine description uses 64 bit enum values, which won't work for MSVC. Replace them with #defines

* Add `ffs` implementation for Microsoft C/C++

* Remove GCC function attributes for non-GCC compilers

* Add macro to provide MSVC definition of strncasecmp

* Workaround MSVC pre-processor deficiencies

The MSVC preprocessor doesn't appear to like having a #if/#endif within a macro invocation. To placate it, surround two instances of the macro invocation (with appropriately different arguments!) with #if/#else/#endif
2020-05-28 01:26:03 +08:00
Nguyen Anh Quynh
10cac9d34e add msvc/unicorn/ppc-softmmu/config-target.h 2020-05-27 19:37:54 +08:00
Nguyen Anh Quynh
b4894ce43e cleanup sample_ppc.c 2020-05-27 16:54:00 +08:00
chfl4gs
1b4fb66138 make header for make related builds (#1268)
* Travis-CI Migration (#1230)

* Travis-CI Migration

* Travis-CI addition cmake Linux

* Travis-CI cmake fix

* Travis-CI Arm64 build

* make header for make related build
2020-05-27 16:42:51 +08:00
Nguyen Anh Quynh
132d97dfea cmake supports PPC. TODO: msvc/unicorn/ppc-softmmu is still missing 2020-05-27 16:33:08 +08:00
Nguyen Anh Quynh
f77bdb3c7e ppc: remove unused files 2020-05-27 15:53:51 +08:00
Nguyen Anh Quynh
90ed828e90 unicorn.h: PPC32 mode is supported 2020-05-27 15:33:35 +08:00
Nguyen Anh Quynh
8cbbf3df42 powerpc: chmod -x source files 2020-05-27 15:32:14 +08:00
Nguyen Anh Quynh
ad1d9156f3 chmod -x for PPC files 2020-05-27 15:17:39 +08:00
Nguyen Anh Quynh
02047d7645 update bindings 2020-05-27 15:04:42 +08:00
Nguyen Anh Quynh
d5d513d9f1 bump version to 1.0.3 2020-05-27 14:50:07 +08:00
Nguyen Anh Quynh
17e7c80eba cleanup & fix qemu/header_gen.py 2020-05-27 14:43:12 +08:00
Nguyen Anh Quynh
5b25f3f53e Merge branch 'master' of https://github.com/simigo79/unicorn-ppc into next 2020-05-27 14:02:32 +08:00
Simon Gorchakov
7e66419c03 Fixed more warnings. 2020-05-26 22:00:29 +03:00
Simon Gorchakov
0e8b6a8bba Fixed warnings. 2020-05-25 23:28:25 +03:00
chenhuitao
63cb1cdd58 Merge remote-tracking branch 'upstream/master' 2020-05-24 00:11:22 +08:00
Simon Gorchakov
e55b25c744 Removed warning about missing interrupt controller. 2020-05-21 22:10:25 +03:00
Simon Gorchakov
a5ab143189 Fixed some comments in the samples 2020-05-21 22:08:53 +03:00
Simon Gorchakov
fd44c670cb Indented with spaces, not tabs 2020-05-15 09:52:31 +03:00
Simon Gorchakov
5c55aa2d56 Fix UC_HOOK_CODE 2020-05-14 23:46:16 +03:00
Simon Gorchakov
b3da5d0761 Fix readme 2020-05-13 18:30:22 +03:00
Simon Gorchakov
425efda77e Remove debug message causing python check failure 2020-05-11 23:55:26 +03:00
Simon Gorchakov
65188be06f Fix some warnings 2020-05-11 23:13:47 +03:00
Simon Gorchakov
c12934a770 Fix C sample output to match python sample 2020-05-11 23:11:52 +03:00
Simon Gorchakov
ea26926b60 Fix ffs() in MinGW 2020-05-11 23:10:19 +03:00
Simon Gorchakov
7e413d2fcf Fix conflict with aarch64 2020-05-11 23:09:08 +03:00
Simon Gorchakov
92ecc28491 Add python binding aattempt #2 2020-05-10 22:38:42 +03:00
Simon Gorchakov
a5bc710d08 Add python bindings and test 2020-05-10 22:35:47 +03:00
Simon Gorchakov
279483ec29 Fix ffs() argument type problem. 2020-05-10 22:32:51 +03:00
Simon Gorchakov
76a3ebdc03 Fix no return value error. 2020-05-10 22:31:20 +03:00
chenhuitao
bdbba45dcf Merge remote-tracking branch 'upstream/master' 2020-05-10 23:50:05 +08:00
Simon Gorchakov
1ec0c0a769 Added PPC sample 2020-05-08 22:04:58 +03:00
Simon Gorchakov
a6c9b41c68 Initial update for PPC 2020-05-08 21:54:29 +03:00
chenhuitao
c316b866ec Merge remote-tracking branch 'upstream/master' 2020-05-05 01:12:49 +08:00
chenhuitao
8a30e1ac0d Merge remote-tracking branch 'upstream/master' 2020-04-30 14:02:01 +08:00
chenhuitao
93fc10de8d Merge remote-tracking branch 'upstream/master' 2020-04-29 00:40:56 +08:00
chenhuitao
d2c8d152ba Merge remote-tracking branch 'upstream/master' 2020-04-28 13:18:28 +08:00
chenhuitao
ef1fffccfe Merge remote-tracking branch 'upstream/master' 2020-04-28 02:43:11 +08:00
chenhuitao
fe559ea3b1 Merge remote-tracking branch 'upstream/master' 2020-04-27 23:35:16 +08:00
chenhuitao
f37568c186 Merge remote-tracking branch 'upstream/master' 2020-04-27 13:16:48 +08:00
chenhuitao
b3891003fe Merge remote-tracking branch 'upstream/master' 2020-04-19 03:56:03 +08:00
chenhuitao
7ef4460c3a fix finding python path which only has python3. 2020-03-04 02:17:37 +08:00
296 changed files with 58126 additions and 17081 deletions

4
.gitignore vendored
View File

@ -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

View File

@ -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}

View File

@ -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.

View File

@ -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)."

View File

@ -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)

View File

@ -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)

View File

@ -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': '',

View File

@ -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

View 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

View 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
)

View File

@ -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

View File

@ -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;

View 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;
}

View File

@ -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;

View 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
View 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()

View File

@ -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'],

View 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

View File

@ -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

View 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

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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,
}

View 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,
}

View 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
View 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 &regions {
println!("{:#010x?}", region);
}
}

281
bindings/rust/src/x86.rs Normal file
View 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,
}

View 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(()));
}

View File

@ -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
################################################################################

View File

@ -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;

View File

@ -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

View File

@ -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
View 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

View File

@ -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)

View 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>

View 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>

View File

@ -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

View 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

View 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>

View 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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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 ; \

View File

@ -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/

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -1,3 +0,0 @@
# Default configuration for x86_64-softmmu
CONFIG_APIC=y

View File

@ -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, &notdirty_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, &notdirty_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

View File

@ -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

View File

@ -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;
}

View File

@ -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")

View File

@ -1,4 +1,2 @@
devices-dirs-$(CONFIG_SOFTMMU) += intc/
devices-dirs-y += core/
common-obj-y += $(devices-dirs-y)
obj-y += $(devices-dirs-y)

View File

@ -1,2 +0,0 @@
obj-y += tosa.o
obj-y += virt.o

View File

@ -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);
}

View File

@ -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);
}

View File

@ -1,3 +0,0 @@
# core qdev-related obj files, also used by *-user:
common-obj-y += qdev.o
common-obj-$(CONFIG_SOFTMMU) += machine.o

View File

@ -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);
}

View File

@ -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);
}

View File

@ -1 +1 @@
obj-y += pc.o pc_piix.o
obj-y += pc.o

View File

@ -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);
}

View File

@ -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);
}

View File

@ -1 +0,0 @@
obj-$(CONFIG_APIC) += apic.o apic_common.o

View File

@ -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);
}

View File

@ -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);
}

View File

@ -1 +0,0 @@
obj-y += dummy_m68k.o

View File

@ -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);
}

View File

@ -1,2 +1 @@
obj-y += mips_r4k.o
obj-y += addr.o cputimer.o
obj-y += cputimer.o

View File

@ -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;
}

View File

@ -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 */

View File

@ -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
View 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