├── .clang-format ├── .github └── workflows │ ├── Crate-publishing.yml │ ├── Nuget-publishing.yml │ ├── build-uc2.yml │ ├── build-wheels-publish.yml │ ├── prerelease.yml │ ├── release.yml │ └── zigbuild.yml ├── .gitignore ├── .gitmodules ├── AUTHORS.TXT ├── CMakeLists.txt ├── COPYING ├── COPYING.LGPL2 ├── COPYING_GLIB ├── CREDITS.TXT ├── Cargo.toml ├── ChangeLog ├── README.md ├── SECURITY.md ├── TODO ├── bindings ├── Makefile ├── README ├── const_generator.py ├── dotnet │ ├── README.md │ ├── UnicornDotNet.sln │ ├── UnicornEngine │ │ ├── Binding │ │ │ ├── BindingFactory.fs │ │ │ ├── IBinding.fs │ │ │ ├── MockBinding.fs │ │ │ └── NativeBinding.fs │ │ ├── Const │ │ │ ├── Arm.fs │ │ │ ├── Arm64.fs │ │ │ ├── Common.fs │ │ │ ├── M68k.fs │ │ │ ├── Mips.fs │ │ │ ├── Ppc.fs │ │ │ ├── Riscv.fs │ │ │ ├── S390x.fs │ │ │ ├── Sparc.fs │ │ │ ├── TriCore.fs │ │ │ └── X86.fs │ │ ├── ConvertUtility.fs │ │ ├── InternalHooks.fs │ │ ├── Unicorn.fs │ │ ├── UnicornEngine.fsproj │ │ └── UnicornEngineException.fs │ └── UnicornSamples │ │ ├── Program.cs │ │ ├── ShellcodeSample.cs │ │ ├── UnicornSamples.csproj │ │ ├── Utils.cs │ │ └── X86Sample32.cs ├── go │ ├── Makefile │ ├── README.md │ ├── sample.go │ └── unicorn │ │ ├── arm64_const.go │ │ ├── arm_const.go │ │ ├── cgo.go │ │ ├── cgo_dynamic.go │ │ ├── cgo_static.go │ │ ├── context.go │ │ ├── context_test.go │ │ ├── hook.c │ │ ├── hook.go │ │ ├── hook.h │ │ ├── m68k_const.go │ │ ├── mips_const.go │ │ ├── ppc_const.go │ │ ├── reg_batch.go │ │ ├── riscv_const.go │ │ ├── s390x_const.go │ │ ├── sparc_const.go │ │ ├── tricore_const.go │ │ ├── uc.c │ │ ├── uc.h │ │ ├── unicorn.go │ │ ├── unicorn_const.go │ │ ├── unicorn_test.go │ │ ├── x86.go │ │ ├── x86_const.go │ │ └── x86_test.go ├── haskell │ ├── .gitignore │ ├── README.TXT │ ├── Setup.hs │ ├── samples │ │ ├── SampleArm.hs │ │ ├── SampleArm64.hs │ │ ├── SampleBatchReg.hs │ │ ├── SampleM68k.hs │ │ ├── SampleMips.hs │ │ ├── SampleSparc.hs │ │ ├── SampleX86.hs │ │ └── Shellcode.hs │ ├── src │ │ ├── Unicorn.hs │ │ ├── Unicorn │ │ │ ├── CPU │ │ │ │ ├── Arm.chs │ │ │ │ ├── Arm64.chs │ │ │ │ ├── M68k.chs │ │ │ │ ├── Mips.chs │ │ │ │ ├── Sparc.chs │ │ │ │ └── X86.chs │ │ │ ├── Hook.hs │ │ │ └── Internal │ │ │ │ ├── Core.chs │ │ │ │ ├── Hook.chs │ │ │ │ ├── Unicorn.chs │ │ │ │ └── Util.hs │ │ ├── cbits │ │ │ └── unicorn_wrapper.c │ │ └── include │ │ │ └── unicorn_wrapper.h │ └── unicorn.cabal ├── java │ ├── .gitignore │ ├── CMakeLists.txt │ ├── Makefile │ ├── README.md │ ├── eclipse-formatter.xml │ ├── pom.xml │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── unicorn │ │ │ │ ├── Arm64Const.java │ │ │ │ ├── Arm64SysHook.java │ │ │ │ ├── Arm64_CP.java │ │ │ │ ├── ArmConst.java │ │ │ │ ├── Arm_CP.java │ │ │ │ ├── BlockHook.java │ │ │ │ ├── CodeHook.java │ │ │ │ ├── CpuidHook.java │ │ │ │ ├── EdgeGeneratedHook.java │ │ │ │ ├── EventMemHook.java │ │ │ │ ├── Hook.java │ │ │ │ ├── InHook.java │ │ │ │ ├── InstructionHook.java │ │ │ │ ├── InterruptHook.java │ │ │ │ ├── InvalidInstructionHook.java │ │ │ │ ├── M68kConst.java │ │ │ │ ├── MemHook.java │ │ │ │ ├── MemRegion.java │ │ │ │ ├── MipsConst.java │ │ │ │ ├── MmioReadHandler.java │ │ │ │ ├── MmioWriteHandler.java │ │ │ │ ├── OutHook.java │ │ │ │ ├── PpcConst.java │ │ │ │ ├── RiscvConst.java │ │ │ │ ├── S390xConst.java │ │ │ │ ├── SparcConst.java │ │ │ │ ├── SyscallHook.java │ │ │ │ ├── TcgOpcodeHook.java │ │ │ │ ├── TlbFillHook.java │ │ │ │ ├── TranslationBlock.java │ │ │ │ ├── TriCoreConst.java │ │ │ │ ├── Unicorn.java │ │ │ │ ├── UnicornConst.java │ │ │ │ ├── UnicornException.java │ │ │ │ ├── X86Const.java │ │ │ │ ├── X86_Float80.java │ │ │ │ ├── X86_MMR.java │ │ │ │ └── X86_MSR.java │ │ └── test │ │ │ └── java │ │ │ ├── samples │ │ │ ├── SampleNetworkAuditing.java │ │ │ ├── Sample_arm.java │ │ │ ├── Sample_arm64.java │ │ │ ├── Sample_ctl.java │ │ │ ├── Sample_m68k.java │ │ │ ├── Sample_mips.java │ │ │ ├── Sample_mmu.java │ │ │ ├── Sample_ppc.java │ │ │ ├── Sample_riscv.java │ │ │ ├── Sample_s390x.java │ │ │ ├── Sample_sparc.java │ │ │ ├── Sample_tricore.java │ │ │ ├── Sample_x86.java │ │ │ ├── Sample_x86_mmr.java │ │ │ ├── Shellcode.java │ │ │ └── Utils.java │ │ │ └── tests │ │ │ ├── FunctionalityTests.java │ │ │ ├── HookTests.java │ │ │ ├── MemTests.java │ │ │ ├── RegTests.java │ │ │ ├── RegressionTests.java │ │ │ └── TestSamples.java │ └── unicorn_Unicorn.c ├── pascal │ ├── LICENSE │ ├── README.md │ ├── examples │ │ ├── x86.lpi │ │ ├── x86.lpr │ │ └── x86.lps │ └── unicorn │ │ ├── Arm64Const.pas │ │ ├── ArmConst.pas │ │ ├── M68kConst.pas │ │ ├── MipsConst.pas │ │ ├── PpcConst.pas │ │ ├── RiscvConst.pas │ │ ├── S390xConst.pas │ │ ├── SparcConst.pas │ │ ├── TriCoreConst.pas │ │ ├── UnicornConst.pas │ │ ├── Unicorn_dyn.pas │ │ └── X86Const.pas ├── python │ ├── MANIFEST.in │ ├── Makefile │ ├── README.md │ ├── prebuilt │ │ └── .gitkeep │ ├── pyproject.toml │ ├── setup.py │ ├── tests │ │ ├── test_arm.py │ │ ├── test_arm64.py │ │ ├── test_arm64eb.py │ │ ├── test_armeb.py │ │ ├── test_ctl.py │ │ ├── test_m68k.py │ │ ├── test_mips.py │ │ ├── test_network_auditing.py │ │ ├── test_ppc.py │ │ ├── test_riscv.py │ │ ├── test_s390x.py │ │ ├── test_shellcode.py │ │ ├── test_sparc.py │ │ ├── test_tricore.py │ │ └── test_x86.py │ └── unicorn │ │ ├── __init__.py │ │ ├── arm64_const.py │ │ ├── arm_const.py │ │ ├── m68k_const.py │ │ ├── mips_const.py │ │ ├── ppc_const.py │ │ ├── py.typed │ │ ├── riscv_const.py │ │ ├── s390x_const.py │ │ ├── sparc_const.py │ │ ├── tricore_const.py │ │ ├── unicorn.py │ │ ├── unicorn_const.py │ │ ├── unicorn_py2.py │ │ ├── unicorn_py3 │ │ ├── __init__.py │ │ ├── arch │ │ │ ├── __init__.py │ │ │ ├── arm.py │ │ │ ├── arm64.py │ │ │ ├── intel.py │ │ │ └── types.py │ │ └── unicorn.py │ │ └── x86_const.py ├── ruby │ ├── Makefile │ ├── README.md │ ├── sample_arm.rb │ ├── sample_arm64.rb │ ├── sample_m68k.rb │ ├── sample_mips.rb │ ├── sample_sparc.rb │ ├── sample_x86.rb │ ├── sample_x86_gdt.rb │ ├── test_hook_gc.rb │ └── unicorn_gem │ │ ├── Gemfile │ │ ├── Rakefile │ │ ├── ext │ │ ├── extconf.rb │ │ ├── types.h │ │ ├── unicorn.c │ │ └── unicorn.h │ │ ├── lib │ │ └── unicorn_engine │ │ │ ├── arm64_const.rb │ │ │ ├── arm_const.rb │ │ │ ├── m68k_const.rb │ │ │ ├── mips_const.rb │ │ │ ├── ppc_const.rb │ │ │ ├── riscv_const.rb │ │ │ ├── s390x_const.rb │ │ │ ├── sparc_const.rb │ │ │ ├── tricore_const.rb │ │ │ ├── unicorn_const.rb │ │ │ ├── version.rb │ │ │ └── x86_const.rb │ │ ├── pkg │ │ └── .gitignore │ │ └── unicorn-engine.gemspec ├── rust │ ├── COPYING │ ├── README.md │ ├── build.rs │ └── src │ │ ├── arm.rs │ │ ├── arm64.rs │ │ ├── ffi.rs │ │ ├── lib.rs │ │ ├── m68k.rs │ │ ├── mips.rs │ │ ├── ppc.rs │ │ ├── riscv.rs │ │ ├── s390x.rs │ │ ├── sparc.rs │ │ ├── tricore.rs │ │ ├── unicorn_const.rs │ │ └── x86.rs ├── vb6 │ ├── .gitattributes │ ├── Apache_2.0_License.txt │ ├── CMemRegion.cls │ ├── Form1.frm │ ├── Project1.vbp │ ├── Project1.vbw │ ├── README.txt │ ├── example_output.txt │ ├── main.cpp │ ├── misc.bas │ ├── msvbvm60.tlh │ ├── msvbvm60.tli │ ├── screenshot.png │ ├── ucIntel32.cls │ ├── uc_def.bas │ ├── ucvbshim.sln │ └── ucvbshim.vcproj └── zig │ ├── README.md │ ├── sample │ └── sample_riscv_zig.zig │ ├── tools │ ├── zigcc.cmd │ └── zigcc.sh │ └── unicorn │ ├── arm64_const.zig │ ├── arm_const.zig │ ├── m68k_const.zig │ ├── mips_const.zig │ ├── ppc_const.zig │ ├── riscv_const.zig │ ├── s390x_const.zig │ ├── sparc_const.zig │ ├── tricore_const.zig │ ├── unicorn.zig │ ├── unicorn_const.zig │ └── x86_const.zig ├── build.zig ├── build.zig.zon ├── cmake ├── bundle_static.cmake ├── mingw-w64.cmake └── zig.cmake ├── docs ├── BHUSA2015-unicorn.pdf ├── COMPILE.md ├── FAQ.md ├── Hooks.md ├── OPENBSD-NOTES.md ├── README.md ├── Testing.md ├── unicorn-logo-text.png ├── unicorn-logo.png ├── unicorn-logo.svg ├── unicorn1-logo.png └── unicorn1-logo.txt ├── format.sh ├── glib_compat ├── README ├── garray.c ├── garray.h ├── ghash.h ├── glib_compat.c ├── glib_compat.h ├── glist.c ├── glist.h ├── gmacros.h ├── gmem.c ├── gmem.h ├── gmessages.h ├── gnode.h ├── gpattern.c ├── gpattern.h ├── grand.c ├── grand.h ├── gslice.c ├── gslice.h ├── gtestutils.c ├── gtestutils.h ├── gtree.c ├── gtree.h └── gtypes.h ├── go.mod ├── include ├── list.h ├── qemu.h ├── uc_priv.h └── unicorn │ ├── arm.h │ ├── arm64.h │ ├── m68k.h │ ├── mips.h │ ├── platform.h │ ├── ppc.h │ ├── riscv.h │ ├── s390x.h │ ├── sparc.h │ ├── tricore.h │ ├── unicorn.h │ └── x86.h ├── list.c ├── msvc ├── aarch64-softmmu │ └── config-target.h ├── aarch64eb-softmmu │ └── config-target.h ├── arm-softmmu │ └── config-target.h ├── armeb-softmmu │ └── config-target.h ├── config-host.h ├── m68k-softmmu │ └── config-target.h ├── mips-softmmu │ └── config-target.h ├── mips64-softmmu │ └── config-target.h ├── mips64el-softmmu │ └── config-target.h ├── mipsel-softmmu │ └── config-target.h ├── ppc-softmmu │ └── config-target.h ├── ppc64-softmmu │ └── config-target.h ├── riscv32-softmmu │ └── config-target.h ├── riscv64-softmmu │ └── config-target.h ├── s390x-softmmu │ └── config-target.h ├── sparc-softmmu │ └── config-target.h ├── sparc64-softmmu │ └── config-target.h ├── tricore-softmmu │ └── config-target.h ├── unicorn │ └── dllmain.cpp └── x86_64-softmmu │ └── config-target.h ├── qemu ├── .editorconfig ├── CODING_STYLE.rst ├── COPYING ├── COPYING.LIB ├── LICENSE ├── MAINTAINERS ├── VERSION ├── aarch64.h ├── accel │ └── tcg │ │ ├── atomic_template.h │ │ ├── cpu-exec-common.c │ │ ├── cpu-exec.c │ │ ├── cputlb.c │ │ ├── tcg-all.c │ │ ├── tcg-runtime-gvec.c │ │ ├── tcg-runtime.c │ │ ├── tcg-runtime.h │ │ ├── translate-all.c │ │ ├── translate-all.h │ │ └── translator.c ├── arm.h ├── configure ├── crypto │ ├── aes.c │ └── init.c ├── exec-vary.c ├── exec.c ├── fpu │ ├── softfloat-specialize.inc.c │ └── softfloat.c ├── hw │ ├── core │ │ └── cpu.c │ ├── i386 │ │ └── x86.c │ ├── ppc │ │ ├── ppc.c │ │ └── ppc_booke.c │ └── s390x │ │ └── s390-skeys.c ├── include │ ├── crypto │ │ ├── aes.h │ │ ├── init.h │ │ └── random.h │ ├── elf.h │ ├── exec │ │ ├── cpu-all.h │ │ ├── cpu-common.h │ │ ├── cpu-defs.h │ │ ├── cpu_ldst.h │ │ ├── cputlb.h │ │ ├── exec-all.h │ │ ├── gen-icount.h │ │ ├── helper-gen.h │ │ ├── helper-head.h │ │ ├── helper-proto.h │ │ ├── helper-tcg.h │ │ ├── hwaddr.h │ │ ├── ioport.h │ │ ├── memattrs.h │ │ ├── memop.h │ │ ├── memory-internal.h │ │ ├── memory.h │ │ ├── memory_ldst.inc.h │ │ ├── memory_ldst_cached.inc.h │ │ ├── memory_ldst_phys.inc.h │ │ ├── poison.h │ │ ├── ram_addr.h │ │ ├── ramblock.h │ │ ├── ramlist.h │ │ ├── softmmu-semi.h │ │ ├── target_page.h │ │ ├── tb-context.h │ │ ├── tb-hash.h │ │ ├── tb-lookup.h │ │ └── translator.h │ ├── fpu │ │ ├── softfloat-helpers.h │ │ ├── softfloat-macros.h │ │ ├── softfloat-types.h │ │ └── softfloat.h │ ├── hw │ │ ├── core │ │ │ └── cpu.h │ │ ├── i386 │ │ │ └── topology.h │ │ ├── mips │ │ │ └── cpudevs.h │ │ ├── ppc │ │ │ └── ppc.h │ │ ├── registerfields.h │ │ └── s390x │ │ │ ├── ebcdic.h │ │ │ ├── ioinst.h │ │ │ ├── sclp.h │ │ │ └── storage-keys.h │ ├── libdecnumber │ │ ├── dconfig.h │ │ ├── decContext.h │ │ ├── decDPD.h │ │ ├── decNumber.h │ │ ├── decNumberLocal.h │ │ └── dpd │ │ │ ├── decimal128.h │ │ │ ├── decimal128Local.h │ │ │ ├── decimal32.h │ │ │ └── decimal64.h │ ├── qemu-common.h │ ├── qemu │ │ ├── atomic.h │ │ ├── atomic128.h │ │ ├── bitmap.h │ │ ├── bitops.h │ │ ├── bswap.h │ │ ├── compiler.h │ │ ├── cpuid.h │ │ ├── crc32c.h │ │ ├── ctype.h │ │ ├── cutils.h │ │ ├── guest-random.h │ │ ├── host-utils.h │ │ ├── int128.h │ │ ├── log.h │ │ ├── osdep.h │ │ ├── processor.h │ │ ├── qdist.h │ │ ├── qht.h │ │ ├── queue.h │ │ ├── range.h │ │ ├── rcu_queue.h │ │ ├── thread-posix.h │ │ ├── thread-win32.h │ │ ├── thread.h │ │ ├── timer.h │ │ ├── typedefs.h │ │ ├── units.h │ │ └── xxhash.h │ ├── sysemu │ │ ├── cpus.h │ │ ├── memory_mapping.h │ │ ├── os-win32.h │ │ ├── sysemu.h │ │ └── tcg.h │ └── tcg │ │ ├── tcg-apple-jit.h │ │ ├── tcg-gvec-desc.h │ │ ├── tcg-mo.h │ │ ├── tcg-op-gvec.h │ │ ├── tcg-op.h │ │ ├── tcg-opc.h │ │ └── tcg.h ├── libdecnumber │ ├── decContext.c │ ├── decNumber.c │ └── dpd │ │ ├── decimal128.c │ │ ├── decimal32.c │ │ └── decimal64.c ├── m68k.h ├── memory_ldst.inc.c ├── mips.h ├── mips64.h ├── mips64el.h ├── mipsel.h ├── ppc.h ├── ppc64.h ├── riscv32.h ├── riscv64.h ├── rules.mak ├── s390x.h ├── scripts │ └── create_config ├── softmmu │ ├── cpus.c │ ├── ioport.c │ ├── memory.c │ ├── memory_mapping.c │ ├── unicorn_vtlb.c │ └── vl.c ├── sparc.h ├── sparc64.h ├── target │ ├── arm │ │ ├── README │ │ ├── arm-powerctl.c │ │ ├── arm-powerctl.h │ │ ├── arm-semi.c │ │ ├── arm_ldst.h │ │ ├── cpu-param.h │ │ ├── cpu-qom.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── cpu64.c │ │ ├── crypto_helper.c │ │ ├── debug_helper.c │ │ ├── decode-a32-uncond.inc.c │ │ ├── decode-a32.inc.c │ │ ├── decode-sve.inc.c │ │ ├── decode-t16.inc.c │ │ ├── decode-t32.inc.c │ │ ├── decode-vfp-uncond.inc.c │ │ ├── decode-vfp.inc.c │ │ ├── helper-a64.c │ │ ├── helper-a64.h │ │ ├── helper-sve.h │ │ ├── helper.c │ │ ├── helper.h │ │ ├── internals.h │ │ ├── iwmmxt_helper.c │ │ ├── kvm-consts.h │ │ ├── m_helper.c │ │ ├── neon_helper.c │ │ ├── op_addsub.h │ │ ├── op_helper.c │ │ ├── pauth_helper.c │ │ ├── psci.c │ │ ├── sve_helper.c │ │ ├── tlb_helper.c │ │ ├── translate-a64.c │ │ ├── translate-a64.h │ │ ├── translate-sve.c │ │ ├── translate-vfp.inc.c │ │ ├── translate.c │ │ ├── translate.h │ │ ├── unicorn.h │ │ ├── unicorn_aarch64.c │ │ ├── unicorn_arm.c │ │ ├── vec_helper.c │ │ └── vfp_helper.c │ ├── i386 │ │ ├── TODO │ │ ├── arch_memory_mapping.c │ │ ├── bpt_helper.c │ │ ├── cc_helper.c │ │ ├── cc_helper_template.h │ │ ├── cpu-param.h │ │ ├── cpu-qom.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── excp_helper.c │ │ ├── fpu_helper.c │ │ ├── helper.c │ │ ├── helper.h │ │ ├── int_helper.c │ │ ├── machine.c │ │ ├── mem_helper.c │ │ ├── misc_helper.c │ │ ├── mpx_helper.c │ │ ├── ops_sse.h │ │ ├── ops_sse_header.h │ │ ├── seg_helper.c │ │ ├── shift_helper_template.h │ │ ├── smm_helper.c │ │ ├── svm.h │ │ ├── svm_helper.c │ │ ├── translate.c │ │ ├── unicorn.c │ │ ├── unicorn.h │ │ └── xsave_helper.c │ ├── m68k │ │ ├── cpu-param.h │ │ ├── cpu-qom.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── fpu_helper.c │ │ ├── helper.c │ │ ├── helper.h │ │ ├── op_helper.c │ │ ├── qregs.def │ │ ├── softfloat.c │ │ ├── softfloat.h │ │ ├── softfloat_fpsp_tables.h │ │ ├── translate.c │ │ ├── unicorn.c │ │ └── unicorn.h │ ├── mips │ │ ├── TODO │ │ ├── cp0_helper.c │ │ ├── cp0_timer.c │ │ ├── cpu-param.h │ │ ├── cpu-qom.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── dsp_helper.c │ │ ├── fpu_helper.c │ │ ├── helper.c │ │ ├── helper.h │ │ ├── internal.h │ │ ├── lmi_helper.c │ │ ├── mips-defs.h │ │ ├── msa_helper.c │ │ ├── op_helper.c │ │ ├── translate.c │ │ ├── translate_init.inc.c │ │ ├── unicorn.c │ │ └── unicorn.h │ ├── ppc │ │ ├── compat.c │ │ ├── cpu-models.c │ │ ├── cpu-models.h │ │ ├── cpu-param.h │ │ ├── cpu-qom.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── dfp_helper.c │ │ ├── excp_helper.c │ │ ├── fpu_helper.c │ │ ├── helper.h │ │ ├── helper_regs.h │ │ ├── int_helper.c │ │ ├── internal.h │ │ ├── kvm_ppc.h │ │ ├── machine.c │ │ ├── mem_helper.c │ │ ├── mfrom_table.inc.c │ │ ├── mfrom_table_gen.c │ │ ├── misc_helper.c │ │ ├── mmu-book3s-v3.c │ │ ├── mmu-book3s-v3.h │ │ ├── mmu-hash32.c │ │ ├── mmu-hash32.h │ │ ├── mmu-hash64.c │ │ ├── mmu-hash64.h │ │ ├── mmu-radix64.c │ │ ├── mmu-radix64.h │ │ ├── mmu_helper.c │ │ ├── timebase_helper.c │ │ ├── translate.c │ │ ├── translate │ │ │ ├── dfp-impl.inc.c │ │ │ ├── dfp-ops.inc.c │ │ │ ├── fp-impl.inc.c │ │ │ ├── fp-ops.inc.c │ │ │ ├── spe-impl.inc.c │ │ │ ├── spe-ops.inc.c │ │ │ ├── vmx-impl.inc.c │ │ │ ├── vmx-ops.inc.c │ │ │ ├── vsx-impl.inc.c │ │ │ └── vsx-ops.inc.c │ │ ├── translate_init.inc.c │ │ ├── unicorn.c │ │ └── unicorn.h │ ├── riscv │ │ ├── README │ │ ├── cpu-param.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── cpu_bits.h │ │ ├── cpu_helper.c │ │ ├── cpu_user.h │ │ ├── csr.c │ │ ├── fpu_helper.c │ │ ├── helper.h │ │ ├── insn_trans │ │ │ ├── trans_privileged.inc.c │ │ │ ├── trans_rva.inc.c │ │ │ ├── trans_rvd.inc.c │ │ │ ├── trans_rvf.inc.c │ │ │ ├── trans_rvi.inc.c │ │ │ └── trans_rvm.inc.c │ │ ├── instmap.h │ │ ├── op_helper.c │ │ ├── pmp.c │ │ ├── pmp.h │ │ ├── riscv32 │ │ │ ├── decode_insn16.inc.c │ │ │ └── decode_insn32.inc.c │ │ ├── riscv64 │ │ │ ├── decode_insn16.inc.c │ │ │ └── decode_insn32.inc.c │ │ ├── translate.c │ │ ├── unicorn.c │ │ └── unicorn.h │ ├── s390x │ │ ├── cc_helper.c │ │ ├── cpu-param.h │ │ ├── cpu-qom.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── cpu_features.c │ │ ├── cpu_features.h │ │ ├── cpu_features_def.h │ │ ├── cpu_features_def.inc.h │ │ ├── cpu_models.c │ │ ├── cpu_models.h │ │ ├── crypto_helper.c │ │ ├── excp_helper.c │ │ ├── fpu_helper.c │ │ ├── gen-features.c │ │ ├── gen-features.h │ │ ├── helper.c │ │ ├── helper.h │ │ ├── insn-data.def │ │ ├── insn-format.def │ │ ├── int_helper.c │ │ ├── internal.h │ │ ├── interrupt.c │ │ ├── ioinst.c │ │ ├── mem_helper.c │ │ ├── misc_helper.c │ │ ├── mmu_helper.c │ │ ├── s390-tod.h │ │ ├── sigp.c │ │ ├── tcg-stub.c │ │ ├── tcg_s390x.h │ │ ├── translate.c │ │ ├── translate_vx.inc.c │ │ ├── unicorn.c │ │ ├── unicorn.h │ │ ├── vec.h │ │ ├── vec_fpu_helper.c │ │ ├── vec_helper.c │ │ ├── vec_int_helper.c │ │ └── vec_string_helper.c │ ├── sparc │ │ ├── asi.h │ │ ├── cc_helper.c │ │ ├── cpu-param.h │ │ ├── cpu-qom.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── fop_helper.c │ │ ├── helper.c │ │ ├── helper.h │ │ ├── int32_helper.c │ │ ├── int64_helper.c │ │ ├── ldst_helper.c │ │ ├── mmu_helper.c │ │ ├── translate.c │ │ ├── unicorn.c │ │ ├── unicorn.h │ │ ├── unicorn64.c │ │ ├── vis_helper.c │ │ └── win_helper.c │ └── tricore │ │ ├── cpu-param.h │ │ ├── cpu-qom.h │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── csfr.def │ │ ├── fpu_helper.c │ │ ├── helper.c │ │ ├── helper.h │ │ ├── op_helper.c │ │ ├── translate.c │ │ ├── tricore-defs.h │ │ ├── tricore-opcodes.h │ │ ├── unicorn.c │ │ └── unicorn.h ├── tcg │ ├── README │ ├── aarch64 │ │ ├── tcg-target.h │ │ ├── tcg-target.inc.c │ │ └── tcg-target.opc.h │ ├── arm │ │ ├── tcg-target.h │ │ └── tcg-target.inc.c │ ├── i386 │ │ ├── tcg-target.h │ │ ├── tcg-target.inc.c │ │ └── tcg-target.opc.h │ ├── mips │ │ ├── tcg-target.h │ │ └── tcg-target.inc.c │ ├── optimize.c │ ├── ppc │ │ ├── tcg-target.h │ │ ├── tcg-target.inc.c │ │ └── tcg-target.opc.h │ ├── riscv │ │ ├── tcg-target.h │ │ └── tcg-target.inc.c │ ├── s390 │ │ ├── tcg-target.h │ │ └── tcg-target.inc.c │ ├── sparc │ │ ├── tcg-target.h │ │ └── tcg-target.inc.c │ ├── tcg-ldst.inc.c │ ├── tcg-op-gvec.c │ ├── tcg-op-vec.c │ ├── tcg-op.c │ ├── tcg-pool.inc.c │ └── tcg.c ├── trace │ ├── mem-internal.h │ └── mem.h ├── tricore.h ├── unicorn_common.h ├── util │ ├── bitmap.c │ ├── bitops.c │ ├── cacheinfo.c │ ├── crc32c.c │ ├── cutils.c │ ├── getauxval.c │ ├── guest-random.c │ ├── host-utils.c │ ├── osdep.c │ ├── oslib-posix.c │ ├── oslib-win32.c │ ├── pagesize.c │ ├── qdist.c │ ├── qemu-thread-posix.c │ ├── qemu-thread-win32.c │ ├── qemu-timer-common.c │ ├── qemu-timer.c │ ├── qht.c │ ├── range.c │ └── setjmp-wrapper-win32.asm ├── vl.h └── x86_64.h ├── samples ├── Makefile ├── mem_apis.c ├── sample_all.sh ├── sample_arm.c ├── sample_arm64.c ├── sample_batch_reg.c ├── sample_ctl.c ├── sample_m68k.c ├── sample_mips.c ├── sample_mmu.c ├── sample_ppc.c ├── sample_riscv.c ├── sample_s390x.c ├── sample_sparc.c ├── sample_tricore.c ├── sample_x86.c ├── sample_x86_32_gdt_and_seg_regs.c └── shellcode.c ├── symbols.sh ├── tests ├── README.md ├── benchmarks │ └── cow │ │ ├── Makefile │ │ ├── benchmark.c │ │ └── binary.S ├── fuzz │ ├── Makefile │ ├── dlcorpus.sh │ ├── fuzz_emu.options │ ├── fuzz_emu_arm64_arm.c │ ├── fuzz_emu_arm64_armbe.c │ ├── fuzz_emu_arm_arm.c │ ├── fuzz_emu_arm_armbe.c │ ├── fuzz_emu_arm_thumb.c │ ├── fuzz_emu_m68k_be.c │ ├── fuzz_emu_mips_32be.c │ ├── fuzz_emu_mips_32le.c │ ├── fuzz_emu_s390x_be.c │ ├── fuzz_emu_sparc_32be.c │ ├── fuzz_emu_x86_16.c │ ├── fuzz_emu_x86_32.c │ ├── fuzz_emu_x86_64.c │ ├── gentargets.sh │ ├── onedir.c │ └── onefile.c ├── regress │ ├── .gitignore │ ├── 001-bad_condition_code_0xe.c │ ├── 002-qemu__fatal__unimplemented_control_register_write_0xffb___0x0.c │ ├── 003-qemu__fatal__wdebug_not_implemented.c │ ├── 004-segmentation_fault_1.c │ ├── 005-qemu__fatal__illegal_instruction__0000___00000404.c │ ├── 006-qemu__fatal__illegal_instruction__0421___00040026.c │ ├── 00opcode_uc_crash.c │ ├── LICENSE │ ├── Makefile │ ├── arm64_reg_rw_w0_w30.py │ ├── arm_bx_unmapped.py │ ├── arm_bxeq_hang.py │ ├── arm_enable_vfp.c │ ├── arm_fp_vfp_disabled.py │ ├── arm_init_input_crash.py │ ├── arm_memcpy_neon.py │ ├── arm_movr12_hang.py │ ├── arm_vldr_invalid.py │ ├── arm_wfi_first_insn_of_tb.py │ ├── bad_ram.py │ ├── block_test.c │ ├── callback-pc.py │ ├── core_ctl.py │ ├── crash_tb.py │ ├── deadlock_1.py │ ├── eflags_noset.c │ ├── eflags_nosync.c │ ├── emu_clear_errors.c │ ├── emu_clear_errors.py │ ├── emu_stop_in_hook_overrun.c │ ├── emu_stop_segfault.py │ ├── ensure_typedef_consts_generated.py │ ├── fpu_ip.py │ ├── fpu_mem_write.py │ ├── hang.py │ ├── high_mem.py │ ├── hook_add_crash.py │ ├── hook_code_add_del.py │ ├── hook_code_stop_emu.py │ ├── hook_extrainvoke.c │ ├── hook_raises_exception.py │ ├── hook_readonly_write_local.py │ ├── init.py │ ├── invalid_insn.py │ ├── invalid_read_in_cpu_tb_exec.c │ ├── invalid_read_in_tb_flush_x86_64.c │ ├── invalid_write.py │ ├── invalid_write_in_cpu_tb_exec_x86_64.c │ ├── jmp_ebx_hang.py │ ├── jumping.py │ ├── leaked_refs.py │ ├── map_crash.c │ ├── map_write.c │ ├── memmap.py │ ├── memmap_segfault.py │ ├── mips64.py │ ├── mips_branch_delay.py │ ├── mips_branch_likely_issue.c │ ├── mips_cp1.py │ ├── mips_delay_slot_code_hook.c │ ├── mips_except.py │ ├── mips_invalid_read_of_size_4_when_tracing.c │ ├── mips_kernel_mmu.py │ ├── mips_kseg0_1.c │ ├── mips_single_step_sp.py │ ├── mips_syscall_pc.py │ ├── mov_gs_eax.py │ ├── movsd.py │ ├── nr_mem_test.c │ ├── osx_qemu_thread_create_crash.py │ ├── potential_memory_leak.py │ ├── pshufb.py │ ├── reg_write_sign_extension.py │ ├── regress.py │ ├── regress.sh │ ├── rep_hook.py │ ├── rep_movsb.c │ ├── ro_mem_test.c │ ├── run_across_bb.py │ ├── rw_hookstack.c │ ├── segfault_on_stop.py │ ├── sigill.c │ ├── sigill2.c │ ├── sparc64.py │ ├── sparc_jump_to_zero.c │ ├── sparc_reg.py │ ├── sysenter_hook_x86.c │ ├── tcg_liveness_analysis_bug_issue-287.py │ ├── test_old_ctl.py │ ├── threaded_emu_start.c │ ├── timeout_segfault.c │ ├── translator_buffer.py │ ├── vld.py │ ├── write_before_map.py │ ├── wrong_rip.py │ ├── wrong_rip_arm.py │ ├── wrong_sp_arm.py │ ├── x86_16_segfault.c │ ├── x86_64_conditional_jump.py │ ├── x86_64_eflags.py │ ├── x86_64_msr.py │ ├── x86_eflags.py │ ├── x86_fldt_fsqrt.py │ ├── x86_gdt.py │ ├── x86_ld_crash.py │ ├── x86_self_modifying.elf │ ├── x86_self_modifying.py │ ├── x86_self_modifying.s │ ├── x86_set_ip.py │ ├── x86_vex │ └── x86_vex.c ├── rust-tests │ └── main.rs └── unit │ ├── acutest.h │ ├── test_arm.c │ ├── test_arm64.c │ ├── test_ctl.c │ ├── test_m68k.c │ ├── test_mem.c │ ├── test_mips.c │ ├── test_ppc.c │ ├── test_riscv.c │ ├── test_s390x.c │ ├── test_sparc.c │ ├── test_tricore.c │ ├── test_x86.c │ └── unicorn_test.h └── uc.c /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | IndentWidth: 4 3 | UseTab: Never 4 | BreakBeforeBraces: Linux 5 | AllowShortIfStatementsOnASingleLine: Never 6 | AllowShortCaseLabelsOnASingleLine: false 7 | AllowShortBlocksOnASingleLine: Empty 8 | AllowShortFunctionsOnASingleLine: Empty 9 | AllowShortLoopsOnASingleLine: false 10 | IndentCaseLabels: false 11 | ColumnLimit: 80 12 | SortIncludes: false 13 | AllowShortLambdasOnASingleLine: Inline 14 | AlwaysBreakBeforeMultilineStrings: false 15 | BreakStringLiterals: true 16 | PointerAlignment: Right 17 | -------------------------------------------------------------------------------- /.github/workflows/prerelease.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | 4 | name: Upload Prerelease Assets 5 | 6 | jobs: 7 | build: 8 | name: Upload Release Assets 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@v4 13 | 14 | - name: Create Release 15 | id: create_release 16 | uses: actions/create-release@v1 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | with: 20 | tag_name: ${{ github.ref }} 21 | release_name: Release ${{ github.ref }} 22 | draft: true 23 | prerelease: true 24 | 25 | - name: create artifacts directory 26 | run: mkdir artifact 27 | working-directory: ./ 28 | 29 | - uses: dawidd6/action-download-artifact@v2 30 | id: download-artifact 31 | with: 32 | workflow: build-uc2.yml 33 | workflow_conclusion: success 34 | branch: master 35 | path: artifact 36 | 37 | - name: Display structure of downloaded files 38 | run: ls -R 39 | working-directory: artifact 40 | 41 | 42 | - name: Upload Release Assets 43 | id: upload-release-assets 44 | uses: dwenegar/upload-release-assets@v1 45 | env: 46 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | with: 48 | release_id: ${{ steps.create_release.outputs.id }} 49 | assets_path: artifact -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | 4 | name: Upload Release Assets 5 | 6 | jobs: 7 | build: 8 | name: Upload Release Assets 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@v4 13 | 14 | - name: Create Release 15 | id: create_release 16 | uses: actions/create-release@v1 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | with: 20 | tag_name: ${{ github.ref }} 21 | release_name: Release ${{ github.ref }} 22 | draft: true 23 | prerelease: false 24 | 25 | - name: create artifacts directory 26 | run: mkdir artifact 27 | working-directory: ./ 28 | 29 | - uses: dawidd6/action-download-artifact@v6 30 | id: download-artifact 31 | with: 32 | workflow: build-uc2.yml 33 | workflow_conclusion: success 34 | branch: master 35 | path: artifact 36 | 37 | - name: Display structure of downloaded files 38 | run: ls -R 39 | working-directory: artifact 40 | 41 | 42 | - name: Upload Release Assets 43 | id: upload-release-assets 44 | uses: dwenegar/upload-release-assets@v1 45 | env: 46 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | with: 48 | release_id: ${{ steps.create_release.outputs.id }} 49 | assets_path: artifact -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "docs/Unicorn_Engine_Documentation"] 2 | path = docs/Unicorn_Engine_Documentation 3 | url = https://github.com/kabeor/Unicorn-Engine-Documentation 4 | -------------------------------------------------------------------------------- /AUTHORS.TXT: -------------------------------------------------------------------------------- 1 | Nguyen Anh Quynh 2 | Dang Hoang Vu 3 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | aquynh -at- gmail.com 2 | 3 | mio -at- lazym.io 4 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Moved to https://github.com/unicorn-engine/unicorn/milestones -------------------------------------------------------------------------------- /bindings/Makefile: -------------------------------------------------------------------------------- 1 | # Unicorn Engine 2 | # By Nguyen Anh Quynh & Dang Hoang Vu, 2015 3 | DIFF = diff 4 | 5 | SAMPLE_SOURCE = $(wildcard ../samples/*.c) 6 | SAMPLE = $(SAMPLE_SOURCE:../samples/%.c=%) 7 | SAMPLE := $(SAMPLE:mem_apis=) 8 | SAMPLE := $(SAMPLE:sample_batch_reg=) 9 | SAMPLE := $(SAMPLE:sample_x86_32_gdt_and_seg_regs=) 10 | SAMPLE := $(SAMPLE:shellcode=) 11 | 12 | UNAME_S := $(shell uname -s) 13 | ifeq ($(UNAME_S), Linux) 14 | ENV_VARS = LD_PRELOAD=librt.so LD_LIBRARY_PATH=../ DYLD_LIBRARY_PATH=../ 15 | else 16 | ENV_VARS = LD_LIBRARY_PATH=../ DYLD_LIBRARY_PATH=../ LIBUNICORN_PATH=$(TRAVIS_BUILD_DIR) 17 | endif 18 | 19 | 20 | .PHONY: build install python c clean check test 21 | 22 | build: 23 | $(MAKE) -C python gen_const 24 | $(MAKE) -C go gen_const 25 | $(MAKE) -C java gen_const 26 | $(MAKE) -C ruby gen_const 27 | python3 const_generator.py dotnet 28 | python3 const_generator.py pascal 29 | python3 const_generator.py zig 30 | 31 | install: build 32 | $(MAKE) -C python install 33 | $(MAKE) -C java install 34 | 35 | test: $(SAMPLE:%=%.py.test) 36 | 37 | c: 38 | $(MAKE) -C ../samples 39 | python: 40 | $(MAKE) -C python 41 | %.c.txt: c 42 | $(ENV_VARS) ../samples/$(@:%.c.txt=%) > $@ 43 | %.py.txt: python 44 | $(ENV_VARS) python3 python/$(@:%.txt=%) > $@ 45 | 46 | %.py.test: %.c.txt %.py.txt 47 | $(DIFF) -u $(@:%.py.test=%.c.txt) $(@:%.py.test=%.py.txt) 48 | 49 | clean: 50 | # rm -rf *.txt 51 | $(MAKE) -C python clean 52 | $(MAKE) -C java clean 53 | 54 | check: 55 | make -C python check 56 | -------------------------------------------------------------------------------- /bindings/README: -------------------------------------------------------------------------------- 1 | This directory contains bindings & test code for Python, Java, Go and .NET. 2 | See /README or /README.TXT or /README.md for how to install each binding. 3 | 4 | The following bindings are contributed by community. 5 | 6 | - Java binding: by Chris Eagle. 7 | - Go binding: by Ryan Hileman. 8 | - .NET binding: by Antonio Parata. 9 | - Ruby binding: by Sascha Schirra 10 | - Haskell binding: by Adrian Herrera. 11 | - VB6 binding: David Zimmer. 12 | - FreePascal/Delphi binding: Mohamed Osama. 13 | 14 | More bindings created & maintained externally by community are available as follows. 15 | 16 | - UnicornPascal: Delphi/Free Pascal binding (by Stievie). 17 | https://github.com/stievie/UnicornPascal 18 | 19 | - Unicorn-Rs: Rust binding (by Sébastien Duquette) 20 | https://github.com/ekse/unicorn-rs 21 | 22 | - UnicornEngine: Perl binding (by Vikas Naresh Kumar) 23 | https://metacpan.org/pod/UnicornEngine 24 | 25 | - Unicorn.CR: Crystal binding (by Benoit Côté-Jodoin) 26 | https://github.com/Becojo/unicorn.cr 27 | 28 | - Deimos/unicorn: D binding (by Vladimir Panteleev) 29 | https://github.com/D-Programming-Deimos/unicorn 30 | 31 | - Unicorn-Lua: Lua binding (by Diego Argueta) 32 | https://github.com/dargueta/unicorn-lua 33 | 34 | - pharo-unicorn: Pharo binding (by Guille Polito) 35 | https://github.com/guillep/pharo-unicorn 36 | 37 | - Unicorn.js: JavaScript binding (by Alexandro Sanchez) 38 | https://github.com/AlexAltea/unicorn.js 39 | -------------------------------------------------------------------------------- /bindings/dotnet/README.md: -------------------------------------------------------------------------------- 1 | This documentation explains how to use the .NET binding for Unicorn 2 | from source. 3 | 4 | 0. Install the core engine as a dependency 5 | 6 | Follow README in the root directory to compile & install the core. 7 | 8 | 1. Compile the code 9 | 10 | You need to have at least version 5.0 of .NET installed. 11 | 12 | 1. Windows 13 | 14 | To compile the code open the UnicornSln.sln with Microsoft Visual 15 | Studio 12 or with a newer version and just press Ctrl+Shift+B to build 16 | the solution. 17 | 18 | 2. Linux 19 | 20 | To compile the code open a terminal in this directory 21 | and enter the following command to build the solution: 22 | `dotnet build` 23 | 24 | 2. Usage 25 | 26 | The solution includes the testing project UnicornTests with examples 27 | of usage. 28 | 29 | In order to use the library in your project just add a reference to 30 | the .NET library and be sure to copy the unmanaged unicorn.dll 31 | library in the output directory. 32 | 33 | The naming convention used is the Upper Camel Case, this mean that to 34 | invoke the uc_mem_read method you have to search for the MemRead method. 35 | -------------------------------------------------------------------------------- /bindings/dotnet/UnicornEngine/Binding/BindingFactory.fs: -------------------------------------------------------------------------------- 1 | namespace UnicornEngine.Binding 2 | 3 | 4 | module BindingFactory = 5 | let mutable _instance = NativeBinding.instance 6 | 7 | let setDefaultBinding(binding: IBinding) = 8 | _instance <- binding 9 | 10 | let getDefault() = 11 | _instance 12 | -------------------------------------------------------------------------------- /bindings/dotnet/UnicornEngine/Const/M68k.fs: -------------------------------------------------------------------------------- 1 | // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT 2 | 3 | namespace UnicornEngine.Const 4 | 5 | open System 6 | 7 | [] 8 | module M68k = 9 | 10 | // M68K CPU 11 | 12 | let UC_CPU_M68K_M5206 = 0 13 | let UC_CPU_M68K_M68000 = 1 14 | let UC_CPU_M68K_M68020 = 2 15 | let UC_CPU_M68K_M68030 = 3 16 | let UC_CPU_M68K_M68040 = 4 17 | let UC_CPU_M68K_M68060 = 5 18 | let UC_CPU_M68K_M5208 = 6 19 | let UC_CPU_M68K_CFV4E = 7 20 | let UC_CPU_M68K_ANY = 8 21 | let UC_CPU_M68K_ENDING = 9 22 | 23 | // M68K registers 24 | 25 | let UC_M68K_REG_INVALID = 0 26 | let UC_M68K_REG_A0 = 1 27 | let UC_M68K_REG_A1 = 2 28 | let UC_M68K_REG_A2 = 3 29 | let UC_M68K_REG_A3 = 4 30 | let UC_M68K_REG_A4 = 5 31 | let UC_M68K_REG_A5 = 6 32 | let UC_M68K_REG_A6 = 7 33 | let UC_M68K_REG_A7 = 8 34 | let UC_M68K_REG_D0 = 9 35 | let UC_M68K_REG_D1 = 10 36 | let UC_M68K_REG_D2 = 11 37 | let UC_M68K_REG_D3 = 12 38 | let UC_M68K_REG_D4 = 13 39 | let UC_M68K_REG_D5 = 14 40 | let UC_M68K_REG_D6 = 15 41 | let UC_M68K_REG_D7 = 16 42 | let UC_M68K_REG_SR = 17 43 | let UC_M68K_REG_PC = 18 44 | let UC_M68K_REG_ENDING = 19 45 | 46 | -------------------------------------------------------------------------------- /bindings/dotnet/UnicornEngine/ConvertUtility.fs: -------------------------------------------------------------------------------- 1 | namespace UnicornEngine 2 | 3 | open System 4 | 5 | [] 6 | module internal ConvertUtility = 7 | 8 | let int64ToBytes(v: Int64) = 9 | let res = Array.zeroCreate 8 10 | let mutable uv = uint64 v 11 | for i = 0 to res.Length-1 do 12 | res.[i] <- byte (uv &&& uint64 0xFF) 13 | uv <- uv >>> 8 14 | res 15 | 16 | let bytesToInt64(v: Byte array) = 17 | let mutable res = uint64 0 18 | for i = 0 to v.Length-1 do 19 | let tmpV = v.[i] &&& byte 0xFF 20 | res <- res + (uint64 tmpV <<< (i * 8)) 21 | int64 res -------------------------------------------------------------------------------- /bindings/dotnet/UnicornEngine/UnicornEngineException.fs: -------------------------------------------------------------------------------- 1 | namespace UnicornEngine 2 | 3 | open System 4 | 5 | type UnicornEngineException(errNo: Int32, msg: String) = 6 | inherit ApplicationException(msg) 7 | 8 | member this.ErrorNo = errNo 9 | 10 | -------------------------------------------------------------------------------- /bindings/dotnet/UnicornSamples/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UnicornSamples 4 | { 5 | internal static class Program 6 | { 7 | private static void Main(string[] args) 8 | { 9 | // X86 tests 32bit 10 | X86Sample32.X86Code32(); 11 | X86Sample32.X86Code32InvalidMemRead(); 12 | X86Sample32.X86Code32InvalidMemWriteWithRuntimeFix(); 13 | X86Sample32.X86Code32InOut(); 14 | 15 | // Run all shellcode tests 16 | ShellcodeSample.X86Code32Self(); 17 | ShellcodeSample.X86Code32(); 18 | 19 | Console.Write("Tests completed"); 20 | Console.ReadLine(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bindings/dotnet/UnicornSamples/UnicornSamples.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net6.0 4 | Exe 5 | UnicornSamples 6 | UnicornSamples 7 | Copyright © Antonio Parata 2016 8 | https://github.com/unicorn-engine/unicorn 9 | 2.1.3 10 | {B80B5987-1E24-4309-8BF9-C4F91270F21C} 11 | true 12 | 13 | 14 | 15 | prompt 16 | 4 17 | 18 | 19 | 20 | 21 | {0c21f1c1-2725-4a46-9022-1905f85822a5} 22 | UnicornEngine 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /bindings/dotnet/UnicornSamples/Utils.cs: -------------------------------------------------------------------------------- 1 | using Gee.External.Capstone.X86; 2 | using System; 3 | using System.Text; 4 | 5 | namespace UnicornSamples 6 | { 7 | internal static class Utils 8 | { 9 | public static long ToInt(byte[] val) 10 | { 11 | ulong res = 0; 12 | for (var i = 0; i < val.Length; i++) 13 | { 14 | var v = val[i] & 0xFF; 15 | res += (ulong)(v << (i * 8)); 16 | } 17 | return (long)res; 18 | } 19 | 20 | public static byte[] Int64ToBytes(long intVal) 21 | { 22 | var res = new byte[8]; 23 | var uval = (ulong)intVal; 24 | for (var i = 0; i < res.Length; i++) 25 | { 26 | res[i] = (byte)(uval & 0xff); 27 | uval = uval >> 8; 28 | } 29 | return res; 30 | } 31 | 32 | public static string Disassemble(CapstoneX86Disassembler disassembler, byte[] code) 33 | { 34 | var sb = new StringBuilder(); 35 | var instructions = disassembler.Disassemble(code); 36 | foreach (var instruction in instructions) 37 | { 38 | sb.AppendFormat($"{instruction.Mnemonic} {instruction.Operand}{Environment.NewLine}"); 39 | } 40 | return sb.ToString().Trim(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bindings/go/Makefile: -------------------------------------------------------------------------------- 1 | # Go binding for Unicorn engine. Ryan Hileman 2 | 3 | .PHONY: all gen_const test 4 | 5 | all: gen_const 6 | cd unicorn && go build 7 | 8 | gen_const: 9 | cd .. && python3 const_generator.py go 10 | 11 | test: all 12 | cd unicorn && LD_LIBRARY_PATH=../../../ DYLD_LIBRARY_PATH=../../../ go test 13 | -------------------------------------------------------------------------------- /bindings/go/README.md: -------------------------------------------------------------------------------- 1 | To download/update the Unicorn Go bindings, run: 2 | 3 | go get -u github.com/unicorn-engine/unicorn/bindings/go 4 | 5 | A very basic usage example follows 6 | 7 | _(Does not handle most errors for brevity. Please see sample.go for a more hygenic example):_ 8 | 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn" 14 | ) 15 | 16 | func main() { 17 | mu, _ := uc.NewUnicorn(uc.ARCH_X86, uc.MODE_32) 18 | // mov eax, 1234 19 | code := []byte{184, 210, 4, 0, 0} 20 | mu.MemMap(0x1000, 0x1000) 21 | mu.MemWrite(0x1000, code) 22 | if err := mu.Start(0x1000, 0x1000+uint64(len(code))); err != nil { 23 | panic(err) 24 | } 25 | eax, _ := mu.RegRead(uc.X86_REG_EAX) 26 | fmt.Printf("EAX is now: %d\n", eax) 27 | } 28 | 29 | An example program exercising far more Unicorn functionality and error handling can be found in sample.go. 30 | -------------------------------------------------------------------------------- /bindings/go/unicorn/cgo.go: -------------------------------------------------------------------------------- 1 | package unicorn 2 | 3 | // #cgo CFLAGS: -I../../../include -O3 -Wall -Werror 4 | import "C" 5 | -------------------------------------------------------------------------------- /bindings/go/unicorn/cgo_dynamic.go: -------------------------------------------------------------------------------- 1 | //go:build !static 2 | 3 | package unicorn 4 | 5 | // #cgo LDFLAGS: -lunicorn 6 | import "C" 7 | -------------------------------------------------------------------------------- /bindings/go/unicorn/cgo_static.go: -------------------------------------------------------------------------------- 1 | //go:build static 2 | 3 | package unicorn 4 | 5 | // #cgo !darwin LDFLAGS: -lunicorn -lpthread -lm -latomic 6 | // #cgo darwin LDFLAGS: -lunicorn.o 7 | import "C" 8 | -------------------------------------------------------------------------------- /bindings/go/unicorn/context.go: -------------------------------------------------------------------------------- 1 | package unicorn 2 | 3 | import ( 4 | "runtime" 5 | "unsafe" 6 | ) 7 | 8 | // #include 9 | import "C" 10 | 11 | type Context **C.uc_context 12 | 13 | func (u *uc) ContextSave(reuse Context) (Context, error) { 14 | ctx := reuse 15 | if ctx == nil { 16 | ctx = new(*C.uc_context) 17 | } 18 | if err := errReturn(C.uc_context_alloc(u.handle, ctx)); err != nil { 19 | return nil, err 20 | } 21 | runtime.SetFinalizer(ctx, func(p Context) { C.uc_free(unsafe.Pointer(*p)) }) 22 | if err := errReturn(C.uc_context_save(u.handle, *ctx)); err != nil { 23 | } 24 | return ctx, nil 25 | } 26 | 27 | func (u *uc) ContextRestore(ctx Context) error { 28 | return errReturn(C.uc_context_restore(u.handle, *ctx)) 29 | } 30 | -------------------------------------------------------------------------------- /bindings/go/unicorn/context_test.go: -------------------------------------------------------------------------------- 1 | package unicorn 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestContext(t *testing.T) { 8 | u, err := NewUnicorn(ARCH_X86, MODE_32) 9 | if err != nil { 10 | t.Fatal(err) 11 | } 12 | u.RegWrite(X86_REG_EBP, 100) 13 | ctx, err := u.ContextSave(nil) 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | u.RegWrite(X86_REG_EBP, 200) 18 | err = u.ContextRestore(ctx) 19 | if err != nil { 20 | t.Fatal(err) 21 | } 22 | val, _ := u.RegRead(X86_REG_EBP) 23 | if val != 100 { 24 | t.Fatal("context restore failed") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /bindings/go/unicorn/hook.h: -------------------------------------------------------------------------------- 1 | uc_err uc_hook_add_wrap(uc_engine *handle, uc_hook *h2, uc_hook_type type, void *callback, uintptr_t user, uint64_t begin, uint64_t end); 2 | uc_err uc_hook_add_insn(uc_engine *handle, uc_hook *h2, uc_hook_type type, void *callback, uintptr_t user, uint64_t begin, uint64_t end, int insn); 3 | void hookCode_cgo(uc_engine *handle, uint64_t addr, uint32_t size, uintptr_t user); 4 | bool hookMemInvalid_cgo(uc_engine *handle, uc_mem_type type, uint64_t addr, int size, int64_t value, uintptr_t user); 5 | void hookMemAccess_cgo(uc_engine *handle, uc_mem_type type, uint64_t addr, int size, int64_t value, uintptr_t user); 6 | void hookInterrupt_cgo(uc_engine *handle, uint32_t intno, uintptr_t user); 7 | uint32_t hookX86In_cgo(uc_engine *handle, uint32_t port, uint32_t size, uintptr_t user); 8 | void hookX86Out_cgo(uc_engine *handle, uint32_t port, uint32_t size, uint32_t value, uintptr_t user); 9 | void hookX86Syscall_cgo(uc_engine *handle, uintptr_t user); 10 | int hookX86Cpuid_cgo(uc_engine *handle, uintptr_t user); 11 | -------------------------------------------------------------------------------- /bindings/go/unicorn/m68k_const.go: -------------------------------------------------------------------------------- 1 | package unicorn 2 | // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.go] 3 | const ( 4 | 5 | // M68K CPU 6 | 7 | CPU_M68K_M5206 = 0 8 | CPU_M68K_M68000 = 1 9 | CPU_M68K_M68020 = 2 10 | CPU_M68K_M68030 = 3 11 | CPU_M68K_M68040 = 4 12 | CPU_M68K_M68060 = 5 13 | CPU_M68K_M5208 = 6 14 | CPU_M68K_CFV4E = 7 15 | CPU_M68K_ANY = 8 16 | CPU_M68K_ENDING = 9 17 | 18 | // M68K registers 19 | 20 | M68K_REG_INVALID = 0 21 | M68K_REG_A0 = 1 22 | M68K_REG_A1 = 2 23 | M68K_REG_A2 = 3 24 | M68K_REG_A3 = 4 25 | M68K_REG_A4 = 5 26 | M68K_REG_A5 = 6 27 | M68K_REG_A6 = 7 28 | M68K_REG_A7 = 8 29 | M68K_REG_D0 = 9 30 | M68K_REG_D1 = 10 31 | M68K_REG_D2 = 11 32 | M68K_REG_D3 = 12 33 | M68K_REG_D4 = 13 34 | M68K_REG_D5 = 14 35 | M68K_REG_D6 = 15 36 | M68K_REG_D7 = 16 37 | M68K_REG_SR = 17 38 | M68K_REG_PC = 18 39 | M68K_REG_ENDING = 19 40 | ) -------------------------------------------------------------------------------- /bindings/go/unicorn/uc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "_cgo_export.h" 4 | 5 | uc_err uc_reg_read_batch_helper(uc_engine *handle, int *regs, uint64_t *val_out, int count) { 6 | void **val_ref = malloc(sizeof(void *) * count); 7 | int i; 8 | for (i = 0; i < count; i++) { 9 | val_ref[i] = (void *)&val_out[i]; 10 | } 11 | uc_err ret = uc_reg_read_batch(handle, regs, val_ref, count); 12 | free(val_ref); 13 | return ret; 14 | } 15 | 16 | uc_err uc_reg_write_batch_helper(uc_engine *handle, int *regs, uint64_t *val_in, int count) { 17 | void **val_ref = malloc(sizeof(void *) * count); 18 | int i; 19 | for (i = 0; i < count; i++) { 20 | val_ref[i] = (void *)&val_in[i]; 21 | } 22 | uc_err ret = uc_reg_write_batch(handle, regs, (void *const *)val_ref, count); 23 | free(val_ref); 24 | return ret; 25 | } 26 | 27 | uc_err uc_ctl_set_cpu_model_helper(uc_engine *handle, int model) { 28 | return uc_ctl_set_cpu_model(handle, model); 29 | } 30 | -------------------------------------------------------------------------------- /bindings/go/unicorn/uc.h: -------------------------------------------------------------------------------- 1 | uc_err uc_reg_read_batch_helper(uc_engine *handle, int *regs, uint64_t *val_out, int count); 2 | uc_err uc_reg_write_batch_helper(uc_engine *handle, int *regs, uint64_t *val_in, int count); 3 | uc_err uc_ctl_set_cpu_model_helper(uc_engine *handle, int model); 4 | -------------------------------------------------------------------------------- /bindings/haskell/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | cabal-dev 3 | *.o 4 | *.hi 5 | *.chi 6 | *.chs.h 7 | *.dyn_o 8 | *.dyn_hi 9 | .virtualenv 10 | .hpc 11 | .hsenv 12 | .cabal-sandbox/ 13 | cabal.sandbox.config 14 | *.prof 15 | *.aux 16 | *.hp 17 | SampleArm 18 | SampleArm64 19 | SampleM68k 20 | SampleMips 21 | SampleSparc 22 | SampleX86 23 | Shellcode 24 | SampleBatchReg 25 | -------------------------------------------------------------------------------- /bindings/haskell/README.TXT: -------------------------------------------------------------------------------- 1 | This documentation explains how to install Haskell binding for Unicorn 2 | from source. 3 | 4 | 5 | 0. Install the core engine as dependency 6 | 7 | Follow README in the root directory to compile & install the core. 8 | 9 | On *nix, this can simply be done by (project root directory): 10 | 11 | $ sudo ./make.sh install 12 | 13 | 14 | 1. Change directories into the Haskell bindings, build and install 15 | 16 | $ cd bindings/haskell 17 | $ cabal install 18 | 19 | 20 | If you are installing into a sandbox, run `cabal sandbox init` before 21 | installing Unicorn's dependencies. 22 | 23 | If the build fails, install c2hs manually `cabal install c2hs` (note that this 24 | will probably also require you to run `cabal install alex` and `cabal install 25 | happy` as well). If you are NOT using a sandbox, ensure that `$HOME/.cabal/bin` 26 | is on your PATH. 27 | 28 | To build a sample (after having built and installed the Haskell bindings) 29 | 30 | $ cd bindings/haskell 31 | $ ghc --make samples/SampleArm.hs 32 | -------------------------------------------------------------------------------- /bindings/haskell/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /bindings/haskell/src/Unicorn/CPU/Arm.chs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | {-| 4 | Module : Unicorn.CPU.Arm 5 | Description : Definitions for the ARM architecture. 6 | Copyright : (c) Adrian Herrera, 2016 7 | License : GPL-2 8 | 9 | Definitions for the ARM architecture. 10 | -} 11 | module Unicorn.CPU.Arm 12 | ( 13 | Register(..) 14 | ) where 15 | 16 | import Unicorn.Internal.Core (Reg) 17 | 18 | {# context lib = "unicorn" #} 19 | 20 | #include 21 | 22 | -- | ARM registers. 23 | {# enum uc_arm_reg as Register 24 | { underscoreToCase } 25 | omit ( UC_ARM_REG_INVALID 26 | , UC_ARM_REG_ENDING 27 | ) 28 | with prefix = "UC_ARM_REG_" 29 | deriving (Show, Eq, Bounded) 30 | #} 31 | 32 | instance Reg Register 33 | -------------------------------------------------------------------------------- /bindings/haskell/src/Unicorn/CPU/Arm64.chs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | {-| 4 | Module : Unicorn.CPU.Arm64 5 | Description : Definitions for the ARM64 (ARMv8) architecture. 6 | Copyright : (c) Adrian Herrera, 2016 7 | License : GPL-2 8 | 9 | Definitions for the ARM64 (ARMv8) architecture. 10 | -} 11 | module Unicorn.CPU.Arm64 12 | ( 13 | Register(..) 14 | ) where 15 | 16 | import Unicorn.Internal.Core (Reg) 17 | 18 | {# context lib = "unicorn" #} 19 | 20 | #include 21 | 22 | -- | ARM64 registers. 23 | {# enum uc_arm64_reg as Register 24 | { underscoreToCase } 25 | omit ( UC_ARM64_REG_INVALID 26 | , UC_ARM64_REG_ENDING 27 | ) 28 | with prefix = "UC_ARM64_REG_" 29 | deriving (Show, Eq, Bounded) 30 | #} 31 | 32 | instance Reg Register 33 | -------------------------------------------------------------------------------- /bindings/haskell/src/Unicorn/CPU/M68k.chs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | {-| 4 | Module : Unicorn.CPU.Mk68k 5 | Description : Definitions for the MK68K architecture. 6 | Copyright : (c) Adrian Herrera, 2016 7 | License : GPL-2 8 | 9 | Definitions for the MK68K architecture. 10 | -} 11 | module Unicorn.CPU.M68k 12 | ( 13 | Register(..) 14 | ) where 15 | 16 | import Unicorn.Internal.Core (Reg) 17 | 18 | {# context lib = "unicorn" #} 19 | 20 | #include 21 | 22 | -- | M68K registers. 23 | {# enum uc_m68k_reg as Register 24 | { underscoreToCase } 25 | omit ( UC_M68K_REG_INVALID 26 | , UC_M68K_REG_ENDING 27 | ) 28 | with prefix = "UC_M68K_REG_" 29 | deriving (Show, Eq, Bounded) 30 | #} 31 | 32 | instance Reg Register 33 | -------------------------------------------------------------------------------- /bindings/haskell/src/Unicorn/CPU/Sparc.chs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | {-| 4 | Module : Unicorn.CPU.Sparc 5 | Description : Definitions for the SPARC architecture. 6 | Copyright : (c) Adrian Herrera, 2016 7 | License : GPL-2 8 | 9 | Definitions for the SPARC architecture. 10 | -} 11 | module Unicorn.CPU.Sparc 12 | ( 13 | Register(..) 14 | ) where 15 | 16 | import Unicorn.Internal.Core (Reg) 17 | 18 | {# context lib = "unicorn" #} 19 | 20 | #include 21 | 22 | -- | SPARC registers. 23 | {# enum uc_sparc_reg as Register 24 | { underscoreToCase } 25 | omit (UC_SPARC_REG_INVALID 26 | , UC_SPARC_REG_ENDING 27 | ) 28 | with prefix = "UC_SPARC_REG_" 29 | deriving (Show, Eq, Bounded) 30 | #} 31 | 32 | instance Reg Register 33 | -------------------------------------------------------------------------------- /bindings/haskell/src/Unicorn/Internal/Util.hs: -------------------------------------------------------------------------------- 1 | {-| 2 | Module : Unicorn.Internal.Util 3 | Description : Utility (aka helper) functions for the Unicorn emulator. 4 | Copyright : (c) Adrian Herrera, 2016 5 | License : GPL-2 6 | -} 7 | module Unicorn.Internal.Util where 8 | 9 | import Data.Bits 10 | import Foreign 11 | 12 | -- | Combine a list of Enums by performing a bitwise-OR. 13 | combineEnums :: (Enum a, Num b, Bits b) 14 | => [a] 15 | -> b 16 | combineEnums = 17 | foldr ((.|.) <$> enumToNum) 0 18 | 19 | -- | Cast a pointer and then peek inside it. 20 | castPtrAndPeek :: Storable a 21 | => Ptr b 22 | -> IO a 23 | castPtrAndPeek = 24 | peek . castPtr 25 | 26 | -- | Convert an 'Eum' to a 'Num'. 27 | enumToNum :: (Enum a, Num b) 28 | => a 29 | -> b 30 | enumToNum = 31 | fromIntegral . fromEnum 32 | -------------------------------------------------------------------------------- /bindings/haskell/src/cbits/unicorn_wrapper.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "unicorn_wrapper.h" 4 | 5 | void uc_close_wrapper(uc_engine *uc) { 6 | uc_close(uc); 7 | } 8 | 9 | void uc_close_dummy(uc_engine *uc) { 10 | } 11 | 12 | uc_err uc_reg_write_wrapper(uc_engine *uc, int regid, const int64_t *value) { 13 | return uc_reg_write(uc, regid, (const void*) value); 14 | } 15 | 16 | uc_err uc_reg_read_wrapper(uc_engine *uc, int regid, int64_t *value) { 17 | return uc_reg_read(uc, regid, (void*) value); 18 | } 19 | 20 | uc_err uc_reg_write_batch_wrapper(uc_engine *uc, int *regs, int64_t *vals, int count) { 21 | void **valsPtr = malloc(sizeof(void*) * count); 22 | int i; 23 | 24 | for (i = 0; i < count; ++i) { 25 | valsPtr[i] = (void*) &vals[i]; 26 | } 27 | 28 | uc_err ret = uc_reg_write_batch(uc, regs, (void *const*) valsPtr, count); 29 | free(valsPtr); 30 | 31 | return ret; 32 | } 33 | 34 | uc_err uc_reg_read_batch_wrapper(uc_engine *uc, int *regs, int64_t *vals, int count) { 35 | void **valsPtr = malloc(sizeof(void*) * count); 36 | int i; 37 | 38 | for (i = 0; i < count; ++i) { 39 | valsPtr[i] = (void*) &vals[i]; 40 | } 41 | 42 | uc_err ret = uc_reg_read_batch(uc, regs, valsPtr, count); 43 | free(valsPtr); 44 | 45 | return ret; 46 | } 47 | 48 | void uc_free_wrapper(void *mem) { 49 | uc_free(mem); 50 | } 51 | -------------------------------------------------------------------------------- /bindings/haskell/src/include/unicorn_wrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef UNICORN_WRAPPER_H 2 | #define UNICORN_WRAPPER_H 3 | 4 | #include 5 | #include 6 | 7 | /* 8 | * Wrap Unicorn's uc_close function and ignore the returned error code. 9 | */ 10 | void uc_close_wrapper(uc_engine *uc); 11 | 12 | /* 13 | * Doesn't actually do anything. 14 | */ 15 | void uc_close_dummy(uc_engine *uc); 16 | 17 | /* 18 | * Wrappers for register read/write functions that accept int64_t pointers. 19 | */ 20 | uc_err uc_reg_write_wrapper(uc_engine *uc, int regid, const int64_t *value); 21 | uc_err uc_reg_read_wrapper(uc_engine *uc, int regid, int64_t *value); 22 | uc_err uc_reg_write_batch_wrapper(uc_engine *uc, int *regs, int64_t *vals, int count); 23 | uc_err uc_reg_read_batch_wrapper(uc_engine *uc, int *regs, int64_t *vals, int count); 24 | 25 | /* 26 | * Wrap Unicorn's uc_free function and ignore the returned error code. 27 | */ 28 | void uc_free_wrapper(void *context); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /bindings/java/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /bindings/java/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | find_package(JNI) 4 | 5 | if (JNI_FOUND) 6 | message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}") 7 | message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}") 8 | else() 9 | message(FATAL_ERROR "JNI not found, please try to update JAVA_HOME accordingly") 10 | endif() 11 | 12 | add_library(unicorn_java SHARED unicorn_Unicorn.c) 13 | 14 | message("${CMAKE_CURRENT_SOURCE_DIR}/bindings/java/target/headers") 15 | 16 | if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/target/headers") 17 | message(FATAL_ERROR "bindings/java/target/headers not generated, please generate them firstly") 18 | endif() 19 | 20 | target_include_directories(unicorn_java PRIVATE target/headers ${JNI_INCLUDE_DIRS}) 21 | target_link_libraries(unicorn_java PRIVATE unicorn ${JNI_LIBRARIES}) -------------------------------------------------------------------------------- /bindings/java/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for the native JNI library. Automatically called by Maven. 2 | 3 | JAVA_HOME ?= $(shell java -XshowSettings:properties -version 2>&1 | sed -n 's/ *java.home = //p') 4 | 5 | ifeq ($(JAVA_HOME),) 6 | $(error JAVA_HOME could not be determined; please set it manually (make JAVA_HOME=...)) 7 | endif 8 | 9 | JAVA_INC := $(JAVA_HOME)/include 10 | JAVA_PLATFORM_INC := $(shell dirname `find $(JAVA_INC) -name jni_md.h`) 11 | UNICORN_INC := ../../include 12 | 13 | OS := $(shell uname) 14 | ifeq ($(OS),Darwin) 15 | LIB_EXT=.dylib 16 | else ifeq ($(OS),Linux) 17 | LIB_EXT=.so 18 | else 19 | LIB_EXT=.dll 20 | endif 21 | 22 | all: libunicorn_java$(LIB_EXT) 23 | 24 | CC=gcc 25 | CFLAGS=-fPIC 26 | LDFLAGS=-shared -fPIC 27 | # May also use -lunicorn to dynamically link against the installed unicorn 28 | LIBS=../../build/libunicorn.a 29 | INCS=-I target/headers -I$(JAVA_INC) -I$(JAVA_PLATFORM_INC) -I$(UNICORN_INC) 30 | 31 | OBJS=unicorn_Unicorn.o 32 | 33 | unicorn_Unicorn.o: unicorn_Unicorn.c target/headers/unicorn_Unicorn.h 34 | $(CC) -O2 -Wall -Wextra -Wno-unused-parameter -c $(CFLAGS) $(INCS) $< -o $@ 35 | 36 | libunicorn_java$(LIB_EXT): $(OBJS) 37 | $(CC) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) 38 | 39 | gen_const: 40 | cd .. && python3 const_generator.py java 41 | 42 | clean: 43 | rm -f libunicorn_java$(LIB_EXT) 44 | rm -f $(OBJS) 45 | 46 | .PHONY: all clean 47 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/Arm_CP.java: -------------------------------------------------------------------------------- 1 | package unicorn; 2 | 3 | /** ARM coprocessor register for MRC, MCR, MRRC, MCRR */ 4 | public class Arm_CP { 5 | public int cp, is64, sec, crn, crm, opc1, opc2; 6 | public long val; 7 | 8 | public Arm_CP(int cp, int is64, int sec, int crn, int crm, int opc1, 9 | int opc2) { 10 | this(cp, is64, sec, crn, crm, opc1, opc2, 0); 11 | } 12 | 13 | public Arm_CP(int cp, int is64, int sec, int crn, int crm, int opc1, 14 | int opc2, long val) { 15 | this.cp = cp; 16 | this.is64 = is64; 17 | this.sec = sec; 18 | this.crn = crn; 19 | this.crm = crm; 20 | this.opc1 = opc1; 21 | this.opc2 = opc2; 22 | this.val = val; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "Arm_CP [cp=" + cp + ", is64=" + is64 + ", sec=" + sec + 28 | ", crn=" + crn + ", crm=" + crm + ", opc1=" + opc1 + ", opc2=" + 29 | opc2 + ", val=" + val + "]"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/BlockHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Callback for {@code UC_HOOK_BLOCK} */ 25 | public interface BlockHook extends Hook { 26 | /** Called on each basic block within the hooked range. 27 | * 28 | * @param u {@link Unicorn} instance firing this hook 29 | * @param address address of the first instruction in the block 30 | * @param size size of the block, in bytes 31 | * @param user user data provided when registering this hook 32 | */ 33 | public void hook(Unicorn u, long address, int size, Object user); 34 | } 35 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/CodeHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Callback for {@code UC_HOOK_CODE} */ 25 | public interface CodeHook extends Hook { 26 | /** Called on each instruction within the hooked range. 27 | * 28 | * @param u {@link Unicorn} instance firing this hook 29 | * @param address address of the instruction 30 | * @param size size of the instruction, in bytes 31 | * @param user user data provided when registering this hook 32 | */ 33 | public void hook(Unicorn u, long address, int size, Object user); 34 | } 35 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/CpuidHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2023 Robert Xiao 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Callback for {@code UC_HOOK_INSN} with {@code UC_X86_INS_CPUID} */ 25 | public interface CpuidHook extends InstructionHook { 26 | /** Called to handle an x86 CPUID instruction. 27 | * 28 | * @param u {@link Unicorn} instance firing this hook 29 | * @param user user data provided when registering this hook 30 | * @return 1 to skip the instruction (marking it as handled), 31 | * 0 to let QEMU handle it 32 | */ 33 | public int hook(Unicorn u, Object user); 34 | } 35 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/EdgeGeneratedHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2023 Robert Xiao 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Callback for {@code UC_HOOK_EDGE_GENERATED} */ 25 | public interface EdgeGeneratedHook extends Hook { 26 | /** Called whenever a jump is made to a new (untranslated) basic block. 27 | * 28 | * @param u {@link Unicorn} instance firing this hook 29 | * @param cur_tb newly translated block being entered 30 | * @param prev_tb previous block being exited 31 | * @param user user data provided when registering this hook 32 | */ 33 | public void hook(Unicorn u, TranslationBlock cur_tb, 34 | TranslationBlock prev_tb, Object user); 35 | } 36 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/Hook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Base interface for all Unicorn hooks */ 25 | public interface Hook { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/InHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Callback for {@code UC_HOOK_INSN} with {@code UC_X86_INS_IN} */ 25 | public interface InHook extends InstructionHook { 26 | /** Called to handle an x86 IN instruction. 27 | * 28 | * @param u {@link Unicorn} instance firing this hook 29 | * @param port I/O port number 30 | * @param size size of the request (1, 2, or 4 bytes) 31 | * @param user user data provided when registering this hook 32 | * @return value of the I/O request 33 | */ 34 | public int hook(Unicorn u, int port, int size, Object user); 35 | } 36 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/InstructionHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Base interface for {@code UC_HOOK_INSN} hooks */ 25 | public interface InstructionHook extends Hook { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/InterruptHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Callback for {@code UC_HOOK_INTR} */ 25 | public interface InterruptHook extends Hook { 26 | /** Called when a CPU interrupt occurs. 27 | * 28 | * @param u {@link Unicorn} instance firing this hook 29 | * @param intno CPU-specific interrupt number 30 | * @param user user data provided when registering this hook 31 | */ 32 | public void hook(Unicorn u, int intno, Object user); 33 | } 34 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/MemRegion.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2016 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | public class MemRegion { 25 | public long begin; 26 | public long end; 27 | public int perms; 28 | 29 | public MemRegion(long begin, long end, int perms) { 30 | this.begin = begin; 31 | this.end = end; 32 | this.perms = perms; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return String.format("MemRegion [begin=0x%x, end=0x%x, perms=%d]", 38 | begin, end, perms); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/OutHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Callback for {@code UC_HOOK_INSN} with {@code UC_X86_INS_OUT} */ 25 | public interface OutHook extends InstructionHook { 26 | /** Called to handle an x86 OUT instruction. 27 | * 28 | * @param u {@link Unicorn} instance firing this hook 29 | * @param port I/O port number 30 | * @param size size of the request (1, 2, or 4 bytes) 31 | * @param user user data provided when registering this hook 32 | */ 33 | public void hook(Unicorn u, int port, int size, int value, Object user); 34 | } 35 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/SyscallHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Callback for {@code UC_HOOK_INSN} with {@code UC_X86_INS_SYSCALL} or 25 | * {@code UC_X86_INS_SYSENTER} */ 26 | public interface SyscallHook extends InstructionHook { 27 | /** Called to handle an x86 SYSCALL or SYSENTER instruction. 28 | * 29 | * @param u {@link Unicorn} instance firing this hook 30 | * @param user user data provided when registering this hook 31 | */ 32 | public void hook(Unicorn u, Object user); 33 | } 34 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/TranslationBlock.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2023 Robert Xiao 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** uc_tb */ 25 | public class TranslationBlock { 26 | public long pc; 27 | public int icount; 28 | public int size; 29 | 30 | public TranslationBlock(long pc, int icount, int size) { 31 | this.pc = pc; 32 | this.icount = icount; 33 | this.size = size; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return String.format("TranslationBlock [pc=0x%x, icount=%d, size=%d]", 39 | pc, icount, size); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/UnicornException.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2015 Chris Eagle 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | public class UnicornException extends RuntimeException { 25 | public UnicornException() { 26 | super(); 27 | } 28 | 29 | public UnicornException(String msg) { 30 | super(msg); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /bindings/java/src/main/java/unicorn/X86_MSR.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Java bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2023 Robert Xiao 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | package unicorn; 23 | 24 | /** Model-specific register */ 25 | public class X86_MSR { 26 | public int rid; 27 | public long value; 28 | 29 | public X86_MSR(int rid) { 30 | this(rid, 0); 31 | } 32 | 33 | public X86_MSR(int rid, long value) { 34 | this.rid = rid; 35 | this.value = value; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "X86_MSR [rid=" + rid + ", value=" + value + "]"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /bindings/pascal/unicorn/M68kConst.pas: -------------------------------------------------------------------------------- 1 | // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT 2 | 3 | unit M68kConst; 4 | 5 | interface 6 | 7 | const 8 | // M68K CPU 9 | 10 | UC_CPU_M68K_M5206 = 0; 11 | UC_CPU_M68K_M68000 = 1; 12 | UC_CPU_M68K_M68020 = 2; 13 | UC_CPU_M68K_M68030 = 3; 14 | UC_CPU_M68K_M68040 = 4; 15 | UC_CPU_M68K_M68060 = 5; 16 | UC_CPU_M68K_M5208 = 6; 17 | UC_CPU_M68K_CFV4E = 7; 18 | UC_CPU_M68K_ANY = 8; 19 | UC_CPU_M68K_ENDING = 9; 20 | 21 | // M68K registers 22 | 23 | UC_M68K_REG_INVALID = 0; 24 | UC_M68K_REG_A0 = 1; 25 | UC_M68K_REG_A1 = 2; 26 | UC_M68K_REG_A2 = 3; 27 | UC_M68K_REG_A3 = 4; 28 | UC_M68K_REG_A4 = 5; 29 | UC_M68K_REG_A5 = 6; 30 | UC_M68K_REG_A6 = 7; 31 | UC_M68K_REG_A7 = 8; 32 | UC_M68K_REG_D0 = 9; 33 | UC_M68K_REG_D1 = 10; 34 | UC_M68K_REG_D2 = 11; 35 | UC_M68K_REG_D3 = 12; 36 | UC_M68K_REG_D4 = 13; 37 | UC_M68K_REG_D5 = 14; 38 | UC_M68K_REG_D6 = 15; 39 | UC_M68K_REG_D7 = 16; 40 | UC_M68K_REG_SR = 17; 41 | UC_M68K_REG_PC = 18; 42 | UC_M68K_REG_ENDING = 19; 43 | 44 | implementation 45 | end. -------------------------------------------------------------------------------- /bindings/python/MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include src * 2 | recursive-include prebuilt * 3 | graft unicorn/lib 4 | graft unicorn/include 5 | global-include *.a 6 | global-include *.so.2 7 | global-include *.*lib 8 | global-include *.dll 9 | global-include *.h 10 | -------------------------------------------------------------------------------- /bindings/python/prebuilt/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/bindings/python/prebuilt/.gitkeep -------------------------------------------------------------------------------- /bindings/python/unicorn/__init__.py: -------------------------------------------------------------------------------- 1 | # Forwarding defs for compatibility 2 | from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const, riscv_const, s390x_const, tricore_const 3 | from .unicorn_const import * 4 | from .unicorn import Uc, ucsubclass, uc_version, uc_arch_supported, version_bind, debug, UcError, __version__ 5 | -------------------------------------------------------------------------------- /bindings/python/unicorn/m68k_const.py: -------------------------------------------------------------------------------- 1 | # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.py] 2 | 3 | # M68K CPU 4 | 5 | UC_CPU_M68K_M5206 = 0 6 | UC_CPU_M68K_M68000 = 1 7 | UC_CPU_M68K_M68020 = 2 8 | UC_CPU_M68K_M68030 = 3 9 | UC_CPU_M68K_M68040 = 4 10 | UC_CPU_M68K_M68060 = 5 11 | UC_CPU_M68K_M5208 = 6 12 | UC_CPU_M68K_CFV4E = 7 13 | UC_CPU_M68K_ANY = 8 14 | UC_CPU_M68K_ENDING = 9 15 | 16 | # M68K registers 17 | 18 | UC_M68K_REG_INVALID = 0 19 | UC_M68K_REG_A0 = 1 20 | UC_M68K_REG_A1 = 2 21 | UC_M68K_REG_A2 = 3 22 | UC_M68K_REG_A3 = 4 23 | UC_M68K_REG_A4 = 5 24 | UC_M68K_REG_A5 = 6 25 | UC_M68K_REG_A6 = 7 26 | UC_M68K_REG_A7 = 8 27 | UC_M68K_REG_D0 = 9 28 | UC_M68K_REG_D1 = 10 29 | UC_M68K_REG_D2 = 11 30 | UC_M68K_REG_D3 = 12 31 | UC_M68K_REG_D4 = 13 32 | UC_M68K_REG_D5 = 14 33 | UC_M68K_REG_D6 = 15 34 | UC_M68K_REG_D7 = 16 35 | UC_M68K_REG_SR = 17 36 | UC_M68K_REG_PC = 18 37 | UC_M68K_REG_ENDING = 19 38 | -------------------------------------------------------------------------------- /bindings/python/unicorn/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/bindings/python/unicorn/py.typed -------------------------------------------------------------------------------- /bindings/python/unicorn/unicorn.py: -------------------------------------------------------------------------------- 1 | import sys as _sys 2 | 3 | from .unicorn_const import ( 4 | UC_VERSION_MAJOR as __MAJOR, 5 | UC_VERSION_MINOR as __MINOR, 6 | UC_VERSION_PATCH as __PATCH 7 | ) 8 | 9 | __version__ = "%u.%u.%u" % (__MAJOR, __MINOR, __PATCH) 10 | 11 | if _sys.version_info.major == 2: 12 | from .unicorn_py2 import * 13 | else: 14 | from .unicorn_py3 import * 15 | -------------------------------------------------------------------------------- /bindings/python/unicorn/unicorn_py3/__init__.py: -------------------------------------------------------------------------------- 1 | from .unicorn import * 2 | -------------------------------------------------------------------------------- /bindings/python/unicorn/unicorn_py3/arch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/bindings/python/unicorn/unicorn_py3/arch/__init__.py -------------------------------------------------------------------------------- /bindings/ruby/Makefile: -------------------------------------------------------------------------------- 1 | # Ruby binding for Unicorn engine. Sascha Schirra 2 | 3 | .PHONY: gen_const 4 | 5 | # Use bundle install && rake to install gem and test 6 | install: gen_const 7 | cd unicorn_gem && rake build 8 | cd unicorn_gem && gem install --local pkg/unicorn-engine-2.1.1.gem 9 | 10 | gen_const: 11 | cd .. && python3 const_generator.py ruby 12 | -------------------------------------------------------------------------------- /bindings/ruby/README.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Software requirements 4 | 5 | ### Linux 6 | - ruby >= 1.9.3 7 | - rubygems 8 | - make 9 | - gcc 10 | 11 | ### Mac OS 12 | - ruby >= 1.9.3 13 | - rubygems 14 | - make 15 | - XCode 16 | 17 | ## Install unicorn 18 | * cd path_to_unicorn 19 | * ./make.sh install 20 | 21 | ## Install ruby binding 22 | * cd bindings/ruby 23 | * make install 24 | -------------------------------------------------------------------------------- /bindings/ruby/unicorn_gem/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /bindings/ruby/unicorn_gem/Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | task :default => :spec 3 | -------------------------------------------------------------------------------- /bindings/ruby/unicorn_gem/ext/extconf.rb: -------------------------------------------------------------------------------- 1 | require 'mkmf' 2 | 3 | extension_name = 'unicorn_engine' 4 | 5 | dir_config(extension_name) 6 | pkg_config('unicorn') 7 | have_library('unicorn') 8 | 9 | create_makefile(extension_name) 10 | -------------------------------------------------------------------------------- /bindings/ruby/unicorn_gem/ext/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Ruby bindings for the Unicorn Emulator Engine 4 | 5 | Copyright(c) 2016 Sascha Schirra 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | version 2 as published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | */ 21 | 22 | typedef struct uc_x86_float80 { 23 | uint64_t mantissa; 24 | uint16_t exponent; 25 | } uc_x86_float80; 26 | 27 | 28 | struct hook { 29 | uc_hook trace; 30 | VALUE cb; 31 | VALUE ud; 32 | VALUE rUc; 33 | }; 34 | -------------------------------------------------------------------------------- /bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb: -------------------------------------------------------------------------------- 1 | # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.rb] 2 | 3 | module UnicornEngine 4 | 5 | # M68K CPU 6 | 7 | UC_CPU_M68K_M5206 = 0 8 | UC_CPU_M68K_M68000 = 1 9 | UC_CPU_M68K_M68020 = 2 10 | UC_CPU_M68K_M68030 = 3 11 | UC_CPU_M68K_M68040 = 4 12 | UC_CPU_M68K_M68060 = 5 13 | UC_CPU_M68K_M5208 = 6 14 | UC_CPU_M68K_CFV4E = 7 15 | UC_CPU_M68K_ANY = 8 16 | UC_CPU_M68K_ENDING = 9 17 | 18 | # M68K registers 19 | 20 | UC_M68K_REG_INVALID = 0 21 | UC_M68K_REG_A0 = 1 22 | UC_M68K_REG_A1 = 2 23 | UC_M68K_REG_A2 = 3 24 | UC_M68K_REG_A3 = 4 25 | UC_M68K_REG_A4 = 5 26 | UC_M68K_REG_A5 = 6 27 | UC_M68K_REG_A6 = 7 28 | UC_M68K_REG_A7 = 8 29 | UC_M68K_REG_D0 = 9 30 | UC_M68K_REG_D1 = 10 31 | UC_M68K_REG_D2 = 11 32 | UC_M68K_REG_D3 = 12 33 | UC_M68K_REG_D4 = 13 34 | UC_M68K_REG_D5 = 14 35 | UC_M68K_REG_D6 = 15 36 | UC_M68K_REG_D7 = 16 37 | UC_M68K_REG_SR = 17 38 | UC_M68K_REG_PC = 18 39 | UC_M68K_REG_ENDING = 19 40 | end -------------------------------------------------------------------------------- /bindings/ruby/unicorn_gem/lib/unicorn_engine/version.rb: -------------------------------------------------------------------------------- 1 | module Unicorn 2 | VERSION = "2.1.1" 3 | end 4 | -------------------------------------------------------------------------------- /bindings/ruby/unicorn_gem/pkg/.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.gem 11 | -------------------------------------------------------------------------------- /bindings/ruby/unicorn_gem/unicorn-engine.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'unicorn_engine/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "unicorn-engine" 8 | spec.version = Unicorn::VERSION 9 | spec.authors = ["Sascha Schirra"] 10 | spec.email = ["sashs@scoding.de"] 11 | spec.license = 'GPL-2.0' 12 | spec.summary = %q{Ruby binding for Unicorn-Engine} 13 | spec.description = %q{Ruby binding for Unicorn-Engine } 14 | spec.homepage = "https://unicorn-engine.org" 15 | 16 | spec.files = Dir["lib/unicorn_engine/*.rb"] + Dir["ext/unicorn.c"] + Dir["ext/unicorn.h"] + Dir["ext/types.h"] + Dir["ext/extconf.rb"] 17 | spec.require_paths = ["lib","ext"] 18 | spec.extensions = ["ext/extconf.rb"] 19 | spec.add_development_dependency "bundler", "~> 1.11" 20 | spec.add_development_dependency "rake", "~> 10.0" 21 | end 22 | -------------------------------------------------------------------------------- /bindings/rust/src/m68k.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | 3 | // M68K registers 4 | #[repr(C)] 5 | #[derive(PartialEq, Debug, Clone, Copy)] 6 | pub enum RegisterM68K { 7 | INVALID = 0, 8 | A0, 9 | A1, 10 | A2, 11 | A3, 12 | A4, 13 | A5, 14 | A6, 15 | A7, 16 | D0, 17 | D1, 18 | D2, 19 | D3, 20 | D4, 21 | D5, 22 | D6, 23 | D7, 24 | SR, 25 | PC, 26 | ENDING, 27 | } 28 | 29 | impl From for i32 { 30 | fn from(r: RegisterM68K) -> Self { 31 | r as i32 32 | } 33 | } 34 | 35 | #[repr(i32)] 36 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 37 | pub enum M68kCpuModel { 38 | UC_CPU_M68K_M5206 = 0, 39 | UC_CPU_M68K_M68000 = 1, 40 | UC_CPU_M68K_M68020 = 2, 41 | UC_CPU_M68K_M68030 = 3, 42 | UC_CPU_M68K_M68040 = 4, 43 | UC_CPU_M68K_M68060 = 5, 44 | UC_CPU_M68K_M5208 = 6, 45 | UC_CPU_M68K_CFV4E = 7, 46 | UC_CPU_M68K_ANY = 8, 47 | } 48 | 49 | impl From for i32 { 50 | fn from(value: M68kCpuModel) -> Self { 51 | value as i32 52 | } 53 | } 54 | 55 | impl From<&M68kCpuModel> for i32 { 56 | fn from(value: &M68kCpuModel) -> Self { 57 | (*value) as i32 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /bindings/vb6/.gitattributes: -------------------------------------------------------------------------------- 1 | *.frm eol=crlf 2 | *.bas eol=crlf 3 | *.cls eol=crlf 4 | *.ctl eol=crlf 5 | *.vbp eol=crlf 6 | *.txt eol=crlf 7 | *.cpp eol=crlf 8 | *.tli eol=crlf 9 | *.tlh eol=crlf 10 | *.vcproj eol=crlf 11 | *.sln eol=crlf 12 | -------------------------------------------------------------------------------- /bindings/vb6/Project1.vbp: -------------------------------------------------------------------------------- 1 | Type=Exe 2 | Form=Form1.frm 3 | Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\Windows\SysWOW64\stdole2.tlb#OLE Automation 4 | Module=uc_def; uc_def.bas 5 | Module=misc; misc.bas 6 | Class=ucIntel32; ucIntel32.cls 7 | Class=CMemRegion; CMemRegion.cls 8 | IconForm="Form1" 9 | Startup="Form1" 10 | HelpFile="" 11 | ExeName32="vb6Test.exe" 12 | Command32="" 13 | Name="Project1" 14 | HelpContextID="0" 15 | CompatibleMode="0" 16 | MajorVer=1 17 | MinorVer=0 18 | RevisionVer=0 19 | AutoIncrementVer=0 20 | ServerSupportFiles=0 21 | VersionCompanyName="sandsprite" 22 | CompilationType=0 23 | OptimizationType=0 24 | FavorPentiumPro(tm)=0 25 | CodeViewDebugInfo=-1 26 | NoAliasing=0 27 | BoundsCheck=0 28 | OverflowCheck=0 29 | FlPointCheck=0 30 | FDIVCheck=0 31 | UnroundedFP=0 32 | StartMode=0 33 | Unattended=0 34 | Retained=0 35 | ThreadPerObject=0 36 | MaxNumberOfThreads=1 37 | 38 | [MS Transaction Server] 39 | AutoRefresh=1 40 | 41 | [fastBuild] 42 | fullPath=%ap%\vb6Test.exe 43 | -------------------------------------------------------------------------------- /bindings/vb6/Project1.vbw: -------------------------------------------------------------------------------- 1 | Form1 = 39, 35, 1148, 674, , 22, 22, 1090, 631, C 2 | uc_def = 56, 12, 1177, 758, 3 | misc = 44, 44, 1121, 685, 4 | ucIntel32 = 88, 33, 1136, 684, 5 | CMemRegion = 110, 110, 1026, 639, 6 | -------------------------------------------------------------------------------- /bindings/vb6/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/bindings/vb6/screenshot.png -------------------------------------------------------------------------------- /bindings/vb6/ucvbshim.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ucvbshim", "ucvbshim.vcproj", "{6FC797B7-2985-49C8-92CD-CA985AF3511C}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {6FC797B7-2985-49C8-92CD-CA985AF3511C}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {6FC797B7-2985-49C8-92CD-CA985AF3511C}.Debug|Win32.Build.0 = Debug|Win32 14 | {6FC797B7-2985-49C8-92CD-CA985AF3511C}.Release|Win32.ActiveCfg = Release|Win32 15 | {6FC797B7-2985-49C8-92CD-CA985AF3511C}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /bindings/zig/README.md: -------------------------------------------------------------------------------- 1 | # Unicorn-engine-Zig 2 | 3 | [Zig](https://ziglang.org/) bindings for the [Unicorn](http://www.unicorn-engine.org/) emulator with utility functions. 4 | 5 | *Unicorn* is a lightweight multi-platform, multi-architecture CPU emulator framework 6 | based on [QEMU](http://www.qemu.org/). 7 | 8 | ## How to use 9 | 10 | Using the [Zig Build System](https://ziglang.org/learn/build-system/), you can include 11 | the following into your local `build.zig.zon` 12 | 13 | ``` zig 14 | .{ 15 | .dependencies = .{ 16 | .unicorn = .{ 17 | .url = "https://github.com/unicorn-engine/unicorn/archive/.tar.gz", 18 | .hash = "", 19 | } 20 | }, 21 | } 22 | ``` 23 | 24 | Note that currently the only module exported publicly is `unicorn-sys` 25 | -------------------------------------------------------------------------------- /bindings/zig/tools/zigcc.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | zig cc -fno-sanitize=all %* -------------------------------------------------------------------------------- /bindings/zig/tools/zigcc.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | `which zig` cc -fno-sanitize=all $@ -------------------------------------------------------------------------------- /bindings/zig/unicorn/m68k_const.zig: -------------------------------------------------------------------------------- 1 | // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT 2 | 3 | pub const m68kConst = enum(c_int) { 4 | 5 | // M68K CPU 6 | 7 | CPU_M68K_M5206 = 0, 8 | CPU_M68K_M68000 = 1, 9 | CPU_M68K_M68020 = 2, 10 | CPU_M68K_M68030 = 3, 11 | CPU_M68K_M68040 = 4, 12 | CPU_M68K_M68060 = 5, 13 | CPU_M68K_M5208 = 6, 14 | CPU_M68K_CFV4E = 7, 15 | CPU_M68K_ANY = 8, 16 | CPU_M68K_ENDING = 9, 17 | 18 | // M68K registers 19 | 20 | M68K_REG_INVALID = 0, 21 | M68K_REG_A0 = 1, 22 | M68K_REG_A1 = 2, 23 | M68K_REG_A2 = 3, 24 | M68K_REG_A3 = 4, 25 | M68K_REG_A4 = 5, 26 | M68K_REG_A5 = 6, 27 | M68K_REG_A6 = 7, 28 | M68K_REG_A7 = 8, 29 | M68K_REG_D0 = 9, 30 | M68K_REG_D1 = 10, 31 | M68K_REG_D2 = 11, 32 | M68K_REG_D3 = 12, 33 | M68K_REG_D4 = 13, 34 | M68K_REG_D5 = 14, 35 | M68K_REG_D6 = 15, 36 | M68K_REG_D7 = 16, 37 | M68K_REG_SR = 17, 38 | M68K_REG_PC = 18, 39 | M68K_REG_ENDING = 19, 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = "unicorn", 3 | .version = "2.1.3", 4 | .paths = .{""}, 5 | } 6 | -------------------------------------------------------------------------------- /cmake/mingw-w64.cmake: -------------------------------------------------------------------------------- 1 | # cross compile 2 | SET(CMAKE_SYSTEM_NAME Windows) 3 | 4 | # set the compiler 5 | SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) 6 | SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) 7 | SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) 8 | 9 | # set the compiler search path 10 | SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) 11 | 12 | # adjust the default behaviour of the FIND_XXX() commands: 13 | # search headers and libraries in the target environment, search 14 | # programs in the host environment 15 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 16 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 17 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 18 | -------------------------------------------------------------------------------- /cmake/zig.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_CROSSCOMPILING TRUE) 2 | # set the compiler 3 | if(WIN32) 4 | SET(ZIG_CC ${CMAKE_SOURCE_DIR}/bindings/zig/tools/zigcc.cmd) 5 | else() 6 | SET(ZIG_CC ${CMAKE_SOURCE_DIR}/bindings/zig/tools/zigcc.sh) 7 | endif() 8 | SET(CMAKE_C_COMPILER_ID ${ZIG_CC}) 9 | SET(CMAKE_C_COMPILER ${ZIG_CC}) 10 | -------------------------------------------------------------------------------- /docs/BHUSA2015-unicorn.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/docs/BHUSA2015-unicorn.pdf -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | Documention of Unicorn engine. 2 | 3 | * How to compile & install Unicorn. 4 | 5 | http://unicorn-engine.org/docs/ 6 | 7 | * Tutorial on programming with C & Python languages. 8 | 9 | http://unicorn-engine.org/docs/tutorial.html 10 | 11 | * Compare Unicorn & QEMU 12 | 13 | http://unicorn-engine.org/docs/beyond_qemu.html 14 | 15 | * Uncorn-Engine Documentation 16 | 17 | https://github.com/kabeor/Unicorn-Engine-Documentation 18 | -------------------------------------------------------------------------------- /docs/Testing.md: -------------------------------------------------------------------------------- 1 | # Testing in Unicorn 2 | 3 | Unicorn focus on the testing to reduce bugs and ensure the expected behaviors. The `tests/` directory contains a few subdirectories for testing purposes. 4 | 5 | - `unit/`: C unit tests since Unicorn 2. 6 | - `regress/`: The regression tests written in Python and C, imported from Unicorn 1. 7 | - `rust-tests/`: The tests written in rust. 8 | - `fuzz/`: The fuzz drivers for OSS-Fuzz. 9 | - `benchmarks/`: The benchmark suite imported from Unicorn 1. 10 | 11 | ## Contribution Guide 12 | 13 | Generally, it is ideal to add new tests whenever a PR is made. `unit/` should be the first place for the new tests to go. -------------------------------------------------------------------------------- /docs/unicorn-logo-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/docs/unicorn-logo-text.png -------------------------------------------------------------------------------- /docs/unicorn-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/docs/unicorn-logo.png -------------------------------------------------------------------------------- /docs/unicorn1-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/docs/unicorn1-logo.png -------------------------------------------------------------------------------- /docs/unicorn1-logo.txt: -------------------------------------------------------------------------------- 1 | /\'. _,. 2 | |:\ \. .'_/ 3 | _.- |(\\ \ .'_.' 4 | _.-' ,__\\ \\_),/ _/ 5 | _:.' .:::::::.___ ,' 6 | // ' ./::::::\. 16 | */ 17 | 18 | /* 19 | * Modified by the GLib Team and others 1997-2000. See the AUTHORS 20 | * file for a list of people on the GLib Team. See the ChangeLog 21 | * files for a list of changes. These files are distributed with 22 | * GLib at ftp://ftp.gtk.org/pub/gtk/. 23 | */ 24 | 25 | #ifndef __G_NODE_H__ 26 | #define __G_NODE_H__ 27 | 28 | #include "gmem.h" 29 | 30 | /* Tree traverse orders */ 31 | typedef enum 32 | { 33 | G_IN_ORDER, 34 | G_PRE_ORDER, 35 | G_POST_ORDER, 36 | G_LEVEL_ORDER 37 | } GTraverseType; 38 | 39 | #endif /* __G_NODE_H__ */ 40 | -------------------------------------------------------------------------------- /glib_compat/gpattern.h: -------------------------------------------------------------------------------- 1 | /* GLIB - Library of useful routines for C programming 2 | * Copyright (C) 1995-1997, 1999 Peter Mattis, Red Hat, Inc. 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, see . 16 | */ 17 | 18 | #ifndef __G_PATTERN_H__ 19 | #define __G_PATTERN_H__ 20 | 21 | #include "gtypes.h" 22 | 23 | typedef struct _GPatternSpec GPatternSpec; 24 | 25 | GPatternSpec* g_pattern_spec_new (const gchar *pattern); 26 | void g_pattern_spec_free (GPatternSpec *pspec); 27 | gboolean g_pattern_match (GPatternSpec *pspec, 28 | guint string_length, 29 | const gchar *string, 30 | const gchar *string_reversed); 31 | gboolean g_pattern_match_string (GPatternSpec *pspec, 32 | const gchar *string); 33 | 34 | #endif /* __G_PATTERN_H__ */ 35 | -------------------------------------------------------------------------------- /glib_compat/grand.h: -------------------------------------------------------------------------------- 1 | /* GLIB - Library of useful routines for C programming 2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, see . 16 | */ 17 | 18 | /* 19 | * Modified by the GLib Team and others 1997-2000. See the AUTHORS 20 | * file for a list of people on the GLib Team. See the ChangeLog 21 | * files for a list of changes. These files are distributed with 22 | * GLib at ftp://ftp.gtk.org/pub/gtk/. 23 | */ 24 | 25 | #ifndef __G_RAND_H__ 26 | #define __G_RAND_H__ 27 | 28 | #include "gtypes.h" 29 | 30 | typedef struct _GRand GRand; 31 | 32 | GRand *g_rand_new_with_seed(guint32 seed); 33 | GRand *g_rand_new_with_seed_array (const guint32 *seed, guint seed_length); 34 | GRand *g_rand_new(void); 35 | guint32 g_rand_int(GRand *rand_); 36 | 37 | #endif /* __G_RAND_H__ */ 38 | -------------------------------------------------------------------------------- /glib_compat/gtestutils.c: -------------------------------------------------------------------------------- 1 | /* GLib testing utilities 2 | * Copyright (C) 2007 Imendio AB 3 | * Authors: Tim Janik, Sven Herzberg 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, see . 17 | */ 18 | 19 | #include "gtestutils.h" 20 | #include 21 | #include 22 | 23 | void 24 | g_assertion_message_expr (const char *file, 25 | int line, 26 | const char *expr) 27 | { 28 | if (!expr) 29 | printf("%s:%d code should not be reached", file, line); 30 | else 31 | printf("%s:%d assertion failed: %s", file, line, expr); 32 | 33 | abort(); 34 | } 35 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/unicorn-engine/unicorn 2 | 3 | go 1.17 4 | 5 | -------------------------------------------------------------------------------- /include/list.h: -------------------------------------------------------------------------------- 1 | #ifndef UC_LLIST_H 2 | #define UC_LLIST_H 3 | 4 | #include "unicorn/platform.h" 5 | 6 | typedef void (*delete_fn)(void *data); 7 | 8 | struct list_item { 9 | struct list_item *next; 10 | void *data; 11 | }; 12 | 13 | struct list { 14 | struct list_item *head, *tail; 15 | delete_fn delete_fn; 16 | }; 17 | 18 | // create a new list 19 | struct list *list_new(void); 20 | 21 | // removed linked list nodes but does not free their content 22 | void list_clear(struct list *list); 23 | 24 | // insert a new item at the begin of the list. 25 | void *list_insert(struct list *list, void *data); 26 | 27 | // append a new item at the end of the list. 28 | void *list_append(struct list *list, void *data); 29 | 30 | // returns true if entry was removed, false otherwise 31 | bool list_remove(struct list *list, void *data); 32 | 33 | // returns true if the data exists in the list 34 | bool list_exists(struct list *list, void *data); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/qemu.h: -------------------------------------------------------------------------------- 1 | /* By Dang Hoang Vu , 2015 */ 2 | /* Modified for Unicorn Engine by Chen Huitao, 2020 */ 3 | 4 | #ifndef UC_QEMU_H 5 | #define UC_QEMU_H 6 | 7 | struct uc_struct; 8 | 9 | #define OPC_BUF_SIZE 640 10 | 11 | #include "sysemu/sysemu.h" 12 | #include "sysemu/cpus.h" 13 | #include "exec/cpu-common.h" 14 | #include "exec/memory.h" 15 | 16 | #include "qemu/thread.h" 17 | #include "hw/core/cpu.h" 18 | 19 | #include "vl.h" 20 | 21 | // This struct is originally from qemu/include/exec/ramblock.h 22 | // Temporarily moved here since there is circular inclusion. 23 | struct RAMBlock { 24 | struct MemoryRegion *mr; 25 | uint8_t *host; 26 | ram_addr_t offset; 27 | ram_addr_t used_length; 28 | ram_addr_t max_length; 29 | uint32_t flags; 30 | /* RCU-enabled, writes protected by the ramlist lock */ 31 | QLIST_ENTRY(RAMBlock) next; 32 | size_t page_size; 33 | }; 34 | 35 | typedef struct { 36 | MemoryRegion *mr; 37 | void *buffer; 38 | hwaddr addr; 39 | hwaddr len; 40 | } BounceBuffer; 41 | 42 | // This struct is originally from qemu/include/exec/ramlist.h 43 | typedef struct RAMList { 44 | bool freed; 45 | RAMBlock *mru_block; 46 | RAMBlock *last_block; 47 | QLIST_HEAD(, RAMBlock) blocks; 48 | } RAMList; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/unicorn/m68k.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2014-2017 */ 3 | /* This file is released under LGPL2. 4 | See COPYING.LGPL2 in root directory for more details 5 | */ 6 | 7 | #ifndef UNICORN_M68K_H 8 | #define UNICORN_M68K_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #ifdef _MSC_VER 15 | #pragma warning(disable : 4201) 16 | #endif 17 | 18 | //> M68K CPU 19 | typedef enum uc_cpu_m68k { 20 | UC_CPU_M68K_M5206 = 0, 21 | UC_CPU_M68K_M68000, 22 | UC_CPU_M68K_M68020, 23 | UC_CPU_M68K_M68030, 24 | UC_CPU_M68K_M68040, 25 | UC_CPU_M68K_M68060, 26 | UC_CPU_M68K_M5208, 27 | UC_CPU_M68K_CFV4E, 28 | UC_CPU_M68K_ANY, 29 | 30 | UC_CPU_M68K_ENDING 31 | } uc_cpu_m68k; 32 | 33 | //> M68K registers 34 | typedef enum uc_m68k_reg { 35 | UC_M68K_REG_INVALID = 0, 36 | 37 | UC_M68K_REG_A0, 38 | UC_M68K_REG_A1, 39 | UC_M68K_REG_A2, 40 | UC_M68K_REG_A3, 41 | UC_M68K_REG_A4, 42 | UC_M68K_REG_A5, 43 | UC_M68K_REG_A6, 44 | UC_M68K_REG_A7, 45 | 46 | UC_M68K_REG_D0, 47 | UC_M68K_REG_D1, 48 | UC_M68K_REG_D2, 49 | UC_M68K_REG_D3, 50 | UC_M68K_REG_D4, 51 | UC_M68K_REG_D5, 52 | UC_M68K_REG_D6, 53 | UC_M68K_REG_D7, 54 | 55 | UC_M68K_REG_SR, 56 | UC_M68K_REG_PC, 57 | 58 | UC_M68K_REG_ENDING, // <-- mark the end of the list of registers 59 | } uc_m68k_reg; 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /msvc/aarch64-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_AARCH64 1 3 | #define TARGET_NAME "aarch64" 4 | #define TARGET_ARM 1 5 | #define CONFIG_SOFTMMU 1 6 | -------------------------------------------------------------------------------- /msvc/aarch64eb-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_AARCH64 1 3 | #define TARGET_NAME "aarch64eb" 4 | #define TARGET_ARM 1 5 | #define TARGET_WORDS_BIGENDIAN 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/arm-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_ARM 1 3 | #define TARGET_NAME "arm" 4 | #define TARGET_ARM 1 5 | #define CONFIG_SOFTMMU 1 6 | -------------------------------------------------------------------------------- /msvc/armeb-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_ARM 1 3 | #define TARGET_NAME "armeb" 4 | #define TARGET_ARM 1 5 | #define TARGET_WORDS_BIGENDIAN 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/config-host.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define HOST_I386 1 3 | #define CONFIG_WIN32 1 4 | #define CONFIG_TCG 1 5 | #define CONFIG_CPUID_H 1 6 | // #define CONFIG_INT128 1 7 | #define CONFIG_CMPXCHG128 1 8 | // #define CONFIG_ATOMIC64 1 9 | #define CONFIG_PLUGIN 1 10 | -------------------------------------------------------------------------------- /msvc/m68k-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_M68K 1 3 | #define TARGET_NAME "m68k" 4 | #define TARGET_M68K 1 5 | #define TARGET_WORDS_BIGENDIAN 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/mips-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_ABI_MIPSO32 1 3 | #define TARGET_MIPS 1 4 | #define TARGET_NAME "mips" 5 | #define TARGET_MIPS 1 6 | #define TARGET_WORDS_BIGENDIAN 1 7 | #define CONFIG_SOFTMMU 1 8 | -------------------------------------------------------------------------------- /msvc/mips64-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_ABI_MIPSN64 1 3 | #define TARGET_MIPS64 1 4 | #define TARGET_NAME "mips64" 5 | #define TARGET_MIPS 1 6 | #define TARGET_WORDS_BIGENDIAN 1 7 | #define CONFIG_SOFTMMU 1 8 | -------------------------------------------------------------------------------- /msvc/mips64el-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_ABI_MIPSN64 1 3 | #define TARGET_MIPS64 1 4 | #define TARGET_NAME "mips64el" 5 | #define TARGET_MIPS 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/mipsel-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_ABI_MIPSO32 1 3 | #define TARGET_MIPS 1 4 | #define TARGET_NAME "mipsel" 5 | #define TARGET_MIPS 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/ppc-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_PPC 1 3 | #define TARGET_NAME "ppc" 4 | #define TARGET_PPC 1 5 | #define TARGET_WORDS_BIGENDIAN 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/ppc64-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_PPC64 1 3 | #define TARGET_NAME "ppc64" 4 | #define TARGET_PPC 1 5 | #define TARGET_WORDS_BIGENDIAN 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/riscv32-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_RISCV32 1 3 | #define TARGET_NAME "riscv32" 4 | #define TARGET_RISCV 1 5 | #define CONFIG_SOFTMMU 1 6 | #define TARGET_SUPPORTS_MTTCG 1 7 | -------------------------------------------------------------------------------- /msvc/riscv64-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_RISCV64 1 3 | #define TARGET_NAME "riscv64" 4 | #define TARGET_RISCV 1 5 | #define CONFIG_SOFTMMU 1 6 | #define TARGET_SUPPORTS_MTTCG 1 7 | -------------------------------------------------------------------------------- /msvc/s390x-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_S390X 1 3 | #define TARGET_NAME "s390x" 4 | #define TARGET_S390X 1 5 | #define TARGET_SYSTBL_ABI common,64 6 | #define TARGET_WORDS_BIGENDIAN 1 7 | #define CONFIG_SOFTMMU 1 8 | #define TARGET_SUPPORTS_MTTCG 1 9 | -------------------------------------------------------------------------------- /msvc/sparc-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_SPARC 1 3 | #define TARGET_NAME "sparc" 4 | #define TARGET_SPARC 1 5 | #define TARGET_WORDS_BIGENDIAN 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/sparc64-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_SPARC64 1 3 | #define TARGET_NAME "sparc64" 4 | #define TARGET_SPARC 1 5 | #define TARGET_WORDS_BIGENDIAN 1 6 | #define CONFIG_SOFTMMU 1 7 | -------------------------------------------------------------------------------- /msvc/tricore-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_TRICORE 1 3 | #define TARGET_NAME "tricore" 4 | #define TARGET_TRICORE 1 5 | #define CONFIG_SOFTMMU 1 6 | -------------------------------------------------------------------------------- /msvc/unicorn/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | BOOL APIENTRY DllMain( HMODULE hModule, 4 | DWORD ul_reason_for_call, 5 | LPVOID lpReserved 6 | ) 7 | { 8 | switch (ul_reason_for_call) 9 | { 10 | case DLL_PROCESS_ATTACH: 11 | case DLL_THREAD_ATTACH: 12 | case DLL_THREAD_DETACH: 13 | case DLL_PROCESS_DETACH: 14 | break; 15 | } 16 | return TRUE; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /msvc/x86_64-softmmu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define TARGET_X86_64 1 3 | #define TARGET_NAME "x86_64" 4 | #define TARGET_I386 1 5 | #define CONFIG_SOFTMMU 1 6 | -------------------------------------------------------------------------------- /qemu/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is a file format and collection of text editor plugins 2 | # for maintaining consistent coding styles between different editors 3 | # and IDEs. Most popular editors support this either natively or via 4 | # plugin. 5 | # 6 | # Check https://editorconfig.org for details. 7 | 8 | root = true 9 | 10 | [*] 11 | end_of_line = lf 12 | insert_final_newline = true 13 | charset = utf-8 14 | 15 | [*.mak] 16 | indent_style = tab 17 | indent_size = 8 18 | file_type_emacs = makefile 19 | 20 | [Makefile*] 21 | indent_style = tab 22 | indent_size = 8 23 | file_type_emacs = makefile 24 | 25 | [*.{c,h}] 26 | indent_style = space 27 | indent_size = 4 28 | 29 | [*.sh] 30 | indent_style = space 31 | indent_size = 4 32 | 33 | [*.{s,S}] 34 | indent_style = tab 35 | indent_size = 8 36 | file_type_emacs = asm 37 | 38 | [*.{vert,frag}] 39 | file_type_emacs = glsl 40 | 41 | [*.json] 42 | indent_style = space 43 | file_type_emacs = python 44 | -------------------------------------------------------------------------------- /qemu/LICENSE: -------------------------------------------------------------------------------- 1 | The QEMU distribution includes both the QEMU emulator and 2 | various firmware files. These are separate programs that are 3 | distributed together for our users' convenience, and they have 4 | separate licenses. 5 | 6 | The following points clarify the license of the QEMU emulator: 7 | 8 | 1) The QEMU emulator as a whole is released under the GNU General 9 | Public License, version 2. 10 | 11 | 2) Parts of the QEMU emulator have specific licenses which are compatible 12 | with the GNU General Public License, version 2. Hence each source file 13 | contains its own licensing information. Source files with no licensing 14 | information are released under the GNU General Public License, version 15 | 2 or (at your option) any later version. 16 | 17 | As of July 2013, contributions under version 2 of the GNU General Public 18 | License (and no later version) are only accepted for the following files 19 | or directories: bsd-user/, linux-user/, hw/vfio/, hw/xen/xen_pt*. 20 | 21 | 3) The Tiny Code Generator (TCG) is mostly under the BSD or MIT licenses; 22 | but some parts may be GPLv2 or other licenses. Again, see the 23 | specific licensing information in each source file. 24 | 25 | 4) QEMU is a trademark of Fabrice Bellard. 26 | 27 | Fabrice Bellard and the QEMU team 28 | -------------------------------------------------------------------------------- /qemu/VERSION: -------------------------------------------------------------------------------- 1 | 5.0.1 2 | -------------------------------------------------------------------------------- /qemu/include/crypto/init.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU Crypto initialization 3 | * 4 | * Copyright (c) 2015 Red Hat, Inc. 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | * 19 | */ 20 | 21 | #ifndef QCRYPTO_INIT_H 22 | #define QCRYPTO_INIT_H 23 | 24 | #include "qapi/error.h" 25 | 26 | int qcrypto_init(Error **errp); 27 | 28 | #endif /* QCRYPTO_INIT_H */ 29 | -------------------------------------------------------------------------------- /qemu/include/crypto/random.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU Crypto random number provider 3 | * 4 | * Copyright (c) 2015-2016 Red Hat, Inc. 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | * 19 | */ 20 | 21 | #ifndef QCRYPTO_RANDOM_H 22 | #define QCRYPTO_RANDOM_H 23 | 24 | /** 25 | * qcrypto_random_init: 26 | * 27 | * Initializes the handles used by qcrypto_random_bytes 28 | * 29 | * Returns 0 on success, -1 on error 30 | */ 31 | int qcrypto_random_init(void); 32 | 33 | #endif /* QCRYPTO_RANDOM_H */ 34 | -------------------------------------------------------------------------------- /qemu/include/exec/cputlb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Common CPU TLB handling 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef CPUTLB_H 21 | #define CPUTLB_H 22 | 23 | #include "exec/cpu-common.h" 24 | 25 | /* cputlb.c */ 26 | void tlb_protect_code(struct uc_struct *uc, ram_addr_t ram_addr); 27 | void tlb_unprotect_code(struct uc_struct *uc, ram_addr_t ram_addr); 28 | #endif 29 | -------------------------------------------------------------------------------- /qemu/include/exec/hwaddr.h: -------------------------------------------------------------------------------- 1 | /* Define hwaddr if it exists. */ 2 | 3 | #ifndef HWADDR_H 4 | #define HWADDR_H 5 | 6 | 7 | #define HWADDR_BITS 64 8 | /* hwaddr is the type of a physical address (its size can 9 | be different from 'target_ulong'). */ 10 | 11 | typedef uint64_t hwaddr; 12 | #define HWADDR_MAX UINT64_MAX 13 | #define TARGET_FMT_plx "%016" PRIx64 14 | #define HWADDR_PRId PRId64 15 | #define HWADDR_PRIi PRIi64 16 | #define HWADDR_PRIo PRIo64 17 | #define HWADDR_PRIu PRIu64 18 | #define HWADDR_PRIx PRIx64 19 | #define HWADDR_PRIX PRIX64 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /qemu/include/exec/ramblock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Declarations for cpu physical memory functions 3 | * 4 | * Copyright 2011 Red Hat, Inc. and/or its affiliates 5 | * 6 | * Authors: 7 | * Avi Kivity 8 | * 9 | * This work is licensed under the terms of the GNU GPL, version 2 or 10 | * later. See the COPYING file in the top-level directory. 11 | * 12 | */ 13 | 14 | /* 15 | * This header is for use by exec.c and memory.c ONLY. Do not include it. 16 | * The functions declared here will be removed soon. 17 | */ 18 | 19 | #ifndef QEMU_EXEC_RAMBLOCK_H 20 | #define QEMU_EXEC_RAMBLOCK_H 21 | 22 | #include "cpu-common.h" 23 | #include "qemu.h" 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /qemu/include/exec/ramlist.h: -------------------------------------------------------------------------------- 1 | #ifndef RAMLIST_H 2 | #define RAMLIST_H 3 | 4 | #include "qemu/queue.h" 5 | #include "qemu/thread.h" 6 | //#include "qemu/rcu.h" 7 | //#include "qemu/rcu_queue.h" 8 | 9 | #define DIRTY_MEMORY_VGA 0 10 | #define DIRTY_MEMORY_CODE 1 11 | #define DIRTY_MEMORY_MIGRATION 2 12 | #define DIRTY_MEMORY_NUM 3 /* num of dirty bits */ 13 | 14 | #define INTERNAL_RAMBLOCK_FOREACH(block) \ 15 | QLIST_FOREACH(block, &uc->ram_list.blocks, next) 16 | /* Never use the INTERNAL_ version except for defining other macros */ 17 | #define RAMBLOCK_FOREACH(block) INTERNAL_RAMBLOCK_FOREACH(block) 18 | 19 | #endif /* RAMLIST_H */ 20 | -------------------------------------------------------------------------------- /qemu/include/exec/target_page.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Target page sizes and friends for non target files 3 | * 4 | * Copyright (c) 2017 Red Hat Inc 5 | * 6 | * Authors: 7 | * David Alan Gilbert 8 | * Juan Quintela 9 | * 10 | * This work is licensed under the terms of the GNU GPL, version 2 or later. 11 | * See the COPYING file in the top-level directory. 12 | */ 13 | 14 | #ifndef EXEC_TARGET_PAGE_H 15 | #define EXEC_TARGET_PAGE_H 16 | 17 | struct uc_struct; 18 | 19 | size_t qemu_target_page_size(struct uc_struct *uc); 20 | int qemu_target_page_bits(struct uc_struct *uc); 21 | int qemu_target_page_bits_min(void); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /qemu/include/exec/tb-context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Internal structs that QEMU exports to TCG 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef QEMU_TB_CONTEXT_H 21 | #define QEMU_TB_CONTEXT_H 22 | 23 | #include "qemu/thread.h" 24 | #include "qemu/qht.h" 25 | 26 | #define CODE_GEN_HTABLE_BITS 15 27 | #define CODE_GEN_HTABLE_SIZE (1 << CODE_GEN_HTABLE_BITS) 28 | 29 | typedef struct TranslationBlock TranslationBlock; 30 | typedef struct TBContext TBContext; 31 | 32 | struct TBContext { 33 | struct qht htable; 34 | 35 | /* statistics */ 36 | unsigned tb_flush_count; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /qemu/include/hw/mips/cpudevs.h: -------------------------------------------------------------------------------- 1 | #ifndef HW_MIPS_CPUDEVS_H 2 | #define HW_MIPS_CPUDEVS_H 3 | 4 | #include "target/mips/cpu-qom.h" 5 | 6 | /* Definitions for MIPS CPU internal devices. */ 7 | 8 | /* addr.c */ 9 | uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr); 10 | uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr); 11 | uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr); 12 | bool mips_um_ksegs_enabled(void); 13 | void mips_um_ksegs_enable(void); 14 | 15 | /* mips_int.c */ 16 | void cpu_mips_irq_init_cpu(MIPSCPU *cpu); 17 | 18 | /* mips_timer.c */ 19 | void cpu_mips_clock_init(MIPSCPU *cpu); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /qemu/include/qemu/crc32c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Castagnoli CRC32C Checksum Algorithm 3 | * 4 | * Polynomial: 0x11EDC6F41 5 | * 6 | * Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman 7 | * "Optimization of Cyclic Redundancy-Check Codes with 24 8 | * and 32 Parity Bits",IEEE Transactions on Communication, 9 | * Volume 41, Number 6, June 1993 10 | * 11 | * Copyright (c) 2013 Red Hat, Inc., 12 | * 13 | * Authors: 14 | * Jeff Cody 15 | * 16 | * Based on the Linux kernel cryptographic crc32c module, 17 | * 18 | * Copyright (c) 2004 Cisco Systems, Inc. 19 | * Copyright (c) 2008 Herbert Xu 20 | * 21 | * This program is free software; you can redistribute it and/or modify it 22 | * under the terms of the GNU General Public License as published by the Free 23 | * Software Foundation; either version 2 of the License, or (at your option) 24 | * any later version. 25 | * 26 | */ 27 | 28 | #ifndef QEMU_CRC32C_H 29 | #define QEMU_CRC32C_H 30 | 31 | 32 | uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length); 33 | 34 | uint32_t crc32(uint32_t crc, const uint8_t *data, unsigned int length); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /qemu/include/qemu/ctype.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU TCG support 3 | * 4 | * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 | * See the COPYING file in the top-level directory. 6 | */ 7 | 8 | #ifndef QEMU_CTYPE_H 9 | #define QEMU_CTYPE_H 10 | 11 | #define qemu_isalnum(c) isalnum((unsigned char)(c)) 12 | #define qemu_isalpha(c) isalpha((unsigned char)(c)) 13 | #define qemu_iscntrl(c) iscntrl((unsigned char)(c)) 14 | #define qemu_isdigit(c) isdigit((unsigned char)(c)) 15 | #define qemu_isgraph(c) isgraph((unsigned char)(c)) 16 | #define qemu_islower(c) islower((unsigned char)(c)) 17 | #define qemu_isprint(c) isprint((unsigned char)(c)) 18 | #define qemu_ispunct(c) ispunct((unsigned char)(c)) 19 | #define qemu_isspace(c) isspace((unsigned char)(c)) 20 | #define qemu_isupper(c) isupper((unsigned char)(c)) 21 | #define qemu_isxdigit(c) isxdigit((unsigned char)(c)) 22 | #define qemu_tolower(c) tolower((unsigned char)(c)) 23 | #define qemu_toupper(c) toupper((unsigned char)(c)) 24 | #define qemu_isascii(c) isascii((unsigned char)(c)) 25 | #define qemu_toascii(c) toascii((unsigned char)(c)) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /qemu/include/qemu/cutils.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_CUTILS_H 2 | #define QEMU_CUTILS_H 3 | 4 | /** 5 | * pstrcpy: 6 | * @buf: buffer to copy string into 7 | * @buf_size: size of @buf in bytes 8 | * @str: string to copy 9 | * 10 | * Copy @str into @buf, including the trailing NUL, but do not 11 | * write more than @buf_size bytes. The resulting buffer is 12 | * always NUL terminated (even if the source string was too long). 13 | * If @buf_size is zero or negative then no bytes are copied. 14 | * 15 | * This function is similar to strncpy(), but avoids two of that 16 | * function's problems: 17 | * * if @str fits in the buffer, pstrcpy() does not zero-fill the 18 | * remaining space at the end of @buf 19 | * * if @str is too long, pstrcpy() will copy the first @buf_size-1 20 | * bytes and then add a NUL 21 | */ 22 | void pstrcpy(char *buf, int buf_size, const char *str); 23 | /** 24 | * pstrcat: 25 | * @buf: buffer containing existing string 26 | * @buf_size: size of @buf in bytes 27 | * @s: string to concatenate to @buf 28 | * 29 | * Append a copy of @s to the string already in @buf, but do not 30 | * allow the buffer to overflow. If the existing contents of @buf 31 | * plus @str would total more than @buf_size bytes, then write 32 | * as much of @str as will fit followed by a NUL terminator. 33 | * 34 | * @buf must already contain a NUL-terminated string, or the 35 | * behaviour is undefined. 36 | * 37 | * Returns: @buf. 38 | */ 39 | char *pstrcat(char *buf, int buf_size, const char *s); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /qemu/include/qemu/processor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016, Emilio G. Cota 3 | * 4 | * License: GNU GPL, version 2. 5 | * See the COPYING file in the top-level directory. 6 | */ 7 | #ifndef QEMU_PROCESSOR_H 8 | #define QEMU_PROCESSOR_H 9 | 10 | #include "qemu/atomic.h" 11 | 12 | #if defined(__i386__) || defined(__x86_64__) 13 | # define cpu_relax() asm volatile("rep; nop" ::: "memory") 14 | 15 | #elif defined(__aarch64__) 16 | # define cpu_relax() asm volatile("yield" ::: "memory") 17 | 18 | #elif defined(__powerpc64__) 19 | /* set Hardware Multi-Threading (HMT) priority to low; then back to medium */ 20 | # define cpu_relax() asm volatile("or 1, 1, 1;" \ 21 | "or 2, 2, 2;" ::: "memory") 22 | 23 | #else 24 | # define cpu_relax() barrier() 25 | #endif 26 | 27 | #endif /* QEMU_PROCESSOR_H */ 28 | -------------------------------------------------------------------------------- /qemu/include/qemu/thread-posix.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_THREAD_POSIX_H 2 | #define QEMU_THREAD_POSIX_H 3 | 4 | #include 5 | #include 6 | 7 | struct QemuThread { 8 | pthread_t thread; 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /qemu/include/qemu/thread-win32.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_THREAD_WIN32_H 2 | #define QEMU_THREAD_WIN32_H 3 | 4 | #include 5 | 6 | typedef struct QemuThreadData QemuThreadData; 7 | struct QemuThread { 8 | QemuThreadData *data; 9 | unsigned tid; 10 | }; 11 | 12 | /* Only valid for joinable threads. */ 13 | HANDLE qemu_thread_get_handle(struct QemuThread *thread); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /qemu/include/qemu/thread.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_THREAD_H 2 | #define QEMU_THREAD_H 3 | 4 | #include "unicorn/platform.h" 5 | #include "qemu/processor.h" 6 | 7 | struct uc_struct; 8 | typedef struct QemuThread QemuThread; 9 | 10 | #if defined(_WIN32) && !defined(__MINGW32__) 11 | #include "qemu/thread-win32.h" 12 | #else 13 | #include "qemu/thread-posix.h" 14 | #endif 15 | 16 | #define QEMU_THREAD_JOINABLE 0 17 | #define QEMU_THREAD_DETACHED 1 18 | 19 | int qemu_thread_create(struct uc_struct *uc, QemuThread *thread, const char *name, 20 | void *(*start_routine)(void *), 21 | void *arg, int mode); 22 | void *qemu_thread_join(QemuThread *thread); 23 | void qemu_thread_exit(struct uc_struct *uc, void *retval); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /qemu/include/qemu/units.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IEC binary prefixes definitions 3 | * 4 | * Copyright (C) 2015 Nikunj A Dadhania, IBM Corporation 5 | * Copyright (C) 2018 Philippe Mathieu-Daudé 6 | * 7 | * SPDX-License-Identifier: GPL-2.0-or-later 8 | */ 9 | 10 | #ifndef QEMU_UNITS_H 11 | #define QEMU_UNITS_H 12 | 13 | #define KiB (INT64_C(1) << 10) 14 | #define MiB (INT64_C(1) << 20) 15 | #define GiB (INT64_C(1) << 30) 16 | #define TiB (INT64_C(1) << 40) 17 | #define PiB (INT64_C(1) << 50) 18 | #define EiB (INT64_C(1) << 60) 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /qemu/include/sysemu/cpus.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_CPUS_H 2 | #define QEMU_CPUS_H 3 | 4 | #include "qemu/timer.h" 5 | #include "hw/core/cpu.h" 6 | 7 | /* cpus.c */ 8 | bool qemu_in_vcpu_thread(void); 9 | void qemu_init_cpu_loop(void); 10 | void resume_all_vcpus(struct uc_struct* uc); 11 | void cpu_stop_current(struct uc_struct* uc); 12 | void cpu_ticks_init(void); 13 | 14 | /* Unblock cpu */ 15 | void qemu_cpu_kick_self(void); 16 | 17 | void cpu_synchronize_all_states(void); 18 | void cpu_synchronize_all_post_reset(void); 19 | void cpu_synchronize_all_post_init(void); 20 | void cpu_synchronize_all_pre_loadvm(void); 21 | 22 | void qtest_clock_warp(int64_t dest); 23 | 24 | void list_cpus(const char *optarg); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /qemu/include/sysemu/memory_mapping.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU memory mapping 3 | * 4 | * Copyright Fujitsu, Corp. 2011, 2012 5 | * 6 | * Authors: 7 | * Wen Congyang 8 | * 9 | * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 | * See the COPYING file in the top-level directory. 11 | * 12 | */ 13 | 14 | #ifndef MEMORY_MAPPING_H 15 | #define MEMORY_MAPPING_H 16 | 17 | #include "qemu/queue.h" 18 | #include "exec/cpu-defs.h" 19 | #include "exec/memory.h" 20 | 21 | /* The physical and virtual address in the memory mapping are contiguous. */ 22 | typedef struct MemoryMapping { 23 | hwaddr phys_addr; 24 | target_ulong virt_addr; 25 | ram_addr_t length; 26 | QTAILQ_ENTRY(MemoryMapping) next; 27 | } MemoryMapping; 28 | 29 | struct MemoryMappingList { 30 | unsigned int num; 31 | MemoryMapping *last_mapping; 32 | QTAILQ_HEAD(, MemoryMapping) head; 33 | }; 34 | 35 | /* 36 | * add or merge the memory region [phys_addr, phys_addr + length) into the 37 | * memory mapping's list. The region's virtual address starts with virt_addr, 38 | * and is contiguous. The list is sorted by phys_addr. 39 | */ 40 | void memory_mapping_list_add_merge_sorted(MemoryMappingList *list, 41 | hwaddr phys_addr, 42 | hwaddr virt_addr, 43 | ram_addr_t length); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /qemu/include/sysemu/sysemu.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSEMU_H 2 | #define SYSEMU_H 3 | 4 | struct uc_struct; 5 | 6 | void qemu_system_reset_request(struct uc_struct*); 7 | void qemu_system_shutdown_request(struct uc_struct*); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /qemu/include/sysemu/tcg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU TCG support 3 | * 4 | * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 | * See the COPYING file in the top-level directory. 6 | */ 7 | 8 | #ifndef SYSEMU_TCG_H 9 | #define SYSEMU_TCG_H 10 | 11 | #include 12 | #include 13 | //#include "uc_priv.h" 14 | 15 | struct uc_struct; 16 | 17 | void tcg_exec_init(struct uc_struct *uc, uint32_t tb_size); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /qemu/target/arm/README: -------------------------------------------------------------------------------- 1 | code under arm/ is from arm-softmmu/target/arm/*.inc.c 2 | code under aarch64/ is from aarch64-softmmu/target/aarch64/*.inc.c 3 | 4 | WARNING: these code are autogen from scripts/decodetree.py, DO NOT modify them. 5 | 6 | -------------------------------------------------------------------------------- /qemu/target/arm/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ARM cpu parameters for qemu. 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * SPDX-License-Identifier: LGPL-2.0+ 6 | */ 7 | 8 | #ifndef ARM_CPU_PARAM_H 9 | #define ARM_CPU_PARAM_H 1 10 | 11 | #ifdef TARGET_AARCH64 12 | # define TARGET_LONG_BITS 64 13 | # define TARGET_PHYS_ADDR_SPACE_BITS 48 14 | # define TARGET_VIRT_ADDR_SPACE_BITS 48 15 | #else 16 | # define TARGET_LONG_BITS 32 17 | # define TARGET_PHYS_ADDR_SPACE_BITS 40 18 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 19 | #endif 20 | 21 | /* 22 | * ARMv7 and later CPUs have 4K pages minimum, but ARMv5 and v6 23 | * have to support 1K tiny pages. 24 | */ 25 | # define TARGET_PAGE_BITS_VARY 26 | # define TARGET_PAGE_BITS_MIN 10 27 | 28 | #define NB_MMU_MODES 12 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /qemu/target/arm/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015 */ 3 | 4 | #ifndef UC_QEMU_TARGET_ARM_H 5 | #define UC_QEMU_TARGET_ARM_H 6 | 7 | // functions to read & write registers 8 | uc_err reg_read_arm(void *env, int mode, unsigned int regid, void *value, 9 | size_t *size); 10 | uc_err reg_read_aarch64(void *env, int mode, unsigned int regid, void *value, 11 | size_t *size); 12 | uc_err reg_write_arm(void *env, int mode, unsigned int regid, const void *value, 13 | size_t *size, int *setpc); 14 | uc_err reg_write_aarch64(void *env, int mode, unsigned int regid, 15 | const void *value, size_t *size, int *setpc); 16 | 17 | void uc_init_arm(struct uc_struct *uc); 18 | void uc_init_aarch64(struct uc_struct *uc); 19 | #endif 20 | -------------------------------------------------------------------------------- /qemu/target/i386/TODO: -------------------------------------------------------------------------------- 1 | Correctness issues: 2 | 3 | - some eflags manipulation incorrectly reset the bit 0x2. 4 | - SVM: test, cpu save/restore, SMM save/restore. 5 | - x86_64: lcall/ljmp intel/amd differences ? 6 | - better code fetch (different exception handling + CS.limit support) 7 | - user/kernel PUSHL/POPL in helper.c 8 | - add missing cpuid tests 9 | - return UD exception if LOCK prefix incorrectly used 10 | - test ldt limit < 7 ? 11 | - fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret) 12 | - full support of segment limit/rights 13 | - full x87 exception support 14 | - improve x87 bit exactness (use bochs code ?) 15 | - DRx register support 16 | - CR0.AC emulation 17 | - SSE alignment checks 18 | 19 | Optimizations/Features: 20 | 21 | - add SVM nested paging support 22 | - add VMX support 23 | - add AVX support 24 | - add SSE5 support 25 | - fxsave/fxrstor AMD extensions 26 | - improve monitor/mwait support 27 | - faster EFLAGS update: consider SZAP, C, O can be updated separately 28 | with a bit field in CC_OP and more state variables. 29 | - evaluate x87 stack pointer statically 30 | - find a way to avoid translating several time the same TB if CR0.TS 31 | is set or not. 32 | -------------------------------------------------------------------------------- /qemu/target/i386/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * i386 cpu parameters for qemu. 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * SPDX-License-Identifier: LGPL-2.0+ 6 | */ 7 | 8 | #ifndef I386_CPU_PARAM_H 9 | #define I386_CPU_PARAM_H 1 10 | 11 | #ifdef TARGET_X86_64 12 | # define TARGET_LONG_BITS 64 13 | # define TARGET_PHYS_ADDR_SPACE_BITS 52 14 | /* 15 | * ??? This is really 48 bits, sign-extended, but the only thing 16 | * accessible to userland with bit 48 set is the VSYSCALL, and that 17 | * is handled via other mechanisms. 18 | */ 19 | # define TARGET_VIRT_ADDR_SPACE_BITS 47 20 | #else 21 | # define TARGET_LONG_BITS 32 22 | # define TARGET_PHYS_ADDR_SPACE_BITS 36 23 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 24 | #endif 25 | #define TARGET_PAGE_BITS 12 26 | #define NB_MMU_MODES 3 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /qemu/target/i386/machine.c: -------------------------------------------------------------------------------- 1 | #include "qemu/osdep.h" 2 | #include "cpu.h" 3 | #include "exec/exec-all.h" 4 | 5 | #include "sysemu/tcg.h" 6 | 7 | void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f) 8 | { 9 | CPU_LDoubleU temp; 10 | 11 | temp.d = f; 12 | *pmant = temp.l.lower; 13 | *pexp = temp.l.upper; 14 | } 15 | 16 | floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper) 17 | { 18 | CPU_LDoubleU temp; 19 | 20 | temp.l.upper = upper; 21 | temp.l.lower = mant; 22 | return temp.d; 23 | } 24 | -------------------------------------------------------------------------------- /qemu/target/i386/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015 */ 3 | /* Modified for Unicorn Engine by Chen Huitao, 2020 */ 4 | 5 | #ifndef UC_QEMU_TARGET_I386_H 6 | #define UC_QEMU_TARGET_I386_H 7 | 8 | // functions to read & write registers 9 | uc_err reg_read_x86_64(void *env, int mode, unsigned int regid, void *value, 10 | size_t *size); 11 | uc_err reg_write_x86_64(void *env, int mode, unsigned int regid, 12 | const void *value, size_t *size, int *setpc); 13 | 14 | void uc_init_x86_64(struct uc_struct *uc); 15 | #endif 16 | -------------------------------------------------------------------------------- /qemu/target/m68k/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * m68k cpu parameters for qemu. 3 | * 4 | * Copyright (c) 2005-2007 CodeSourcery 5 | * SPDX-License-Identifier: LGPL-2.0+ 6 | */ 7 | 8 | #ifndef M68K_CPU_PARAM_H 9 | #define M68K_CPU_PARAM_H 1 10 | 11 | #define TARGET_LONG_BITS 32 12 | /* 13 | * Coldfire Linux uses 8k pages 14 | * and m68k linux uses 4k pages 15 | * use the smallest one 16 | */ 17 | #define TARGET_PAGE_BITS 12 18 | #define TARGET_PHYS_ADDR_SPACE_BITS 32 19 | #define TARGET_VIRT_ADDR_SPACE_BITS 32 20 | #define NB_MMU_MODES 2 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /qemu/target/m68k/qregs.def: -------------------------------------------------------------------------------- 1 | DEFO32(PC, pc) 2 | DEFO32(SR, sr) 3 | DEFO32(CC_OP, cc_op) 4 | DEFO32(CC_X, cc_x) 5 | DEFO32(CC_C, cc_c) 6 | DEFO32(CC_N, cc_n) 7 | DEFO32(CC_V, cc_v) 8 | DEFO32(CC_Z, cc_z) 9 | DEFO32(MACSR, macsr) 10 | DEFO32(MAC_MASK, mac_mask) 11 | -------------------------------------------------------------------------------- /qemu/target/m68k/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015 */ 3 | 4 | #ifndef UC_QEMU_TARGET_M68K_H 5 | #define UC_QEMU_TARGET_M68K_H 6 | 7 | // functions to read & write registers 8 | uc_err reg_read_m68k(void *env, int mode, unsigned int regid, void *value, 9 | size_t *size); 10 | uc_err reg_write_m68k(void *env, int mode, unsigned int regid, 11 | const void *value, size_t *size, int *setpc); 12 | 13 | void uc_init_m68k(struct uc_struct *uc); 14 | #endif 15 | -------------------------------------------------------------------------------- /qemu/target/mips/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIPS cpu parameters for qemu. 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0+ 5 | */ 6 | 7 | #ifndef MIPS_CPU_PARAM_H 8 | #define MIPS_CPU_PARAM_H 1 9 | 10 | #ifdef TARGET_MIPS64 11 | # define TARGET_LONG_BITS 64 12 | #else 13 | # define TARGET_LONG_BITS 32 14 | #endif 15 | #ifdef TARGET_MIPS64 16 | #define TARGET_PHYS_ADDR_SPACE_BITS 48 17 | #define TARGET_VIRT_ADDR_SPACE_BITS 48 18 | #else 19 | #define TARGET_PHYS_ADDR_SPACE_BITS 40 20 | #define TARGET_VIRT_ADDR_SPACE_BITS 32 21 | #endif 22 | #define TARGET_PAGE_BITS 12 23 | #define NB_MMU_MODES 4 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /qemu/target/mips/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015 */ 3 | 4 | #ifndef UC_QEMU_TARGET_MIPS_H 5 | #define UC_QEMU_TARGET_MIPS_H 6 | 7 | // functions to read & write registers 8 | uc_err reg_read_mips(void *env, int mode, unsigned int regid, void *value, 9 | size_t *size); 10 | uc_err reg_read_mipsel(void *env, int mode, unsigned int regid, void *value, 11 | size_t *size); 12 | uc_err reg_read_mips64(void *env, int mode, unsigned int regid, void *value, 13 | size_t *size); 14 | uc_err reg_read_mips64el(void *env, int mode, unsigned int regid, void *value, 15 | size_t *size); 16 | 17 | uc_err reg_write_mips(void *env, int mode, unsigned int regid, 18 | const void *value, size_t *size, int *setpc); 19 | uc_err reg_write_mipsel(void *env, int mode, unsigned int regid, 20 | const void *value, size_t *size, int *setpc); 21 | uc_err reg_write_mips64(void *env, int mode, unsigned int regid, 22 | const void *value, size_t *size, int *setpc); 23 | uc_err reg_write_mips64el(void *env, int mode, unsigned int regid, 24 | const void *value, size_t *size, int *setpc); 25 | 26 | void uc_init_mips(struct uc_struct *uc); 27 | void uc_init_mipsel(struct uc_struct *uc); 28 | void uc_init_mips64(struct uc_struct *uc); 29 | void uc_init_mips64el(struct uc_struct *uc); 30 | #endif 31 | -------------------------------------------------------------------------------- /qemu/target/ppc/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PowerPC cpu parameters for qemu. 3 | * 4 | * Copyright (c) 2007 Jocelyn Mayer 5 | * SPDX-License-Identifier: LGPL-2.0+ 6 | */ 7 | 8 | #ifndef PPC_CPU_PARAM_H 9 | #define PPC_CPU_PARAM_H 1 10 | 11 | #ifdef TARGET_PPC64 12 | # define TARGET_LONG_BITS 64 13 | /* 14 | * Note that the official physical address space bits is 62-M where M 15 | * is implementation dependent. I've not looked up M for the set of 16 | * cpus we emulate at the system level. 17 | */ 18 | #define TARGET_PHYS_ADDR_SPACE_BITS 62 19 | /* 20 | * Note that the PPC environment architecture talks about 80 bit virtual 21 | * addresses, with segmentation. Obviously that's not all visible to a 22 | * single process, which is all we're concerned with here. 23 | */ 24 | # ifdef TARGET_ABI32 25 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 26 | # else 27 | # define TARGET_VIRT_ADDR_SPACE_BITS 64 28 | # endif 29 | #else 30 | # define TARGET_LONG_BITS 32 31 | # define TARGET_PHYS_ADDR_SPACE_BITS 36 32 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 33 | #endif 34 | #define TARGET_PAGE_BITS 12 35 | #define NB_MMU_MODES 10 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /qemu/target/ppc/mfrom_table_gen.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include "qemu/osdep.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | double d; 8 | uint8_t n; 9 | int i; 10 | 11 | printf("static const uint8_t mfrom_ROM_table[602] =\n{\n "); 12 | for (i = 0; i < 602; i++) { 13 | /* 14 | * Extremely decomposed: 15 | * -T0 / 256 16 | * T0 = 256 * log10(10 + 1.0) + 0.5 17 | */ 18 | d = -i; 19 | d /= 256.0; 20 | d = exp10(d); 21 | d += 1.0; 22 | d = log10(d); 23 | d *= 256; 24 | d += 0.5; 25 | n = d; 26 | printf("%3d, ", n); 27 | if ((i & 7) == 7) { 28 | printf("\n "); 29 | } 30 | } 31 | printf("\n};\n"); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /qemu/target/ppc/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015 */ 3 | 4 | #ifndef UC_QEMU_TARGET_PPC_H 5 | #define UC_QEMU_TARGET_PPC_H 6 | 7 | // functions to read & write registers 8 | uc_err reg_read_ppc(void *env, int mode, unsigned int regid, void *value, 9 | size_t *size); 10 | uc_err reg_read_ppc64(void *env, int mode, unsigned int regid, void *value, 11 | size_t *size); 12 | uc_err reg_write_ppc(void *env, int mode, unsigned int regid, const void *value, 13 | size_t *size, int *setpc); 14 | uc_err reg_write_ppc64(void *env, int mode, unsigned int regid, 15 | const void *value, size_t *size, int *setpc); 16 | 17 | void uc_init_ppc(struct uc_struct *uc); 18 | void uc_init_ppc64(struct uc_struct *uc); 19 | #endif 20 | -------------------------------------------------------------------------------- /qemu/target/riscv/README: -------------------------------------------------------------------------------- 1 | code under riscv32/ is from riscv32-softmmu/target/riscv/*.inc.c 2 | code under riscv64/ is from riscv64-softmmu/target/riscv/*.inc.c 3 | 4 | WARNING: these code are autogen from scripts/decodetree.py, DO NOT modify them. 5 | -------------------------------------------------------------------------------- /qemu/target/riscv/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RISC-V cpu parameters for qemu. 3 | * 4 | * Copyright (c) 2017-2018 SiFive, Inc. 5 | * SPDX-License-Identifier: GPL-2.0+ 6 | */ 7 | 8 | #ifndef RISCV_CPU_PARAM_H 9 | #define RISCV_CPU_PARAM_H 1 10 | 11 | #if defined(TARGET_RISCV64) 12 | # define TARGET_LONG_BITS 64 13 | # define TARGET_PHYS_ADDR_SPACE_BITS 56 /* 44-bit PPN */ 14 | # define TARGET_VIRT_ADDR_SPACE_BITS 48 /* sv48 */ 15 | #elif defined(TARGET_RISCV32) 16 | # define TARGET_LONG_BITS 32 17 | # define TARGET_PHYS_ADDR_SPACE_BITS 34 /* 22-bit PPN */ 18 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 /* sv32 */ 19 | #endif 20 | #define TARGET_PAGE_BITS 12 /* 4 KiB Pages */ 21 | #define NB_MMU_MODES 4 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /qemu/target/riscv/cpu_user.h: -------------------------------------------------------------------------------- 1 | #ifndef TARGET_RISCV_CPU_USER_H 2 | #define TARGET_RISCV_CPU_USER_H 3 | 4 | #define xRA 1 /* return address (aka link register) */ 5 | #define xSP 2 /* stack pointer */ 6 | #define xGP 3 /* global pointer */ 7 | #define xTP 4 /* thread pointer */ 8 | 9 | #define xA0 10 /* gpr[10-17] are syscall arguments */ 10 | #define xA1 11 11 | #define xA2 12 12 | #define xA3 13 13 | #define xA4 14 14 | #define xA5 15 15 | #define xA6 16 16 | #define xA7 17 /* syscall number for RVI ABI */ 17 | #define xT0 5 /* syscall number for RVE ABI */ 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /qemu/target/riscv/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015 */ 3 | /* Modified for Unicorn Engine by Chen Huitao, 2020 */ 4 | 5 | #ifndef UC_QEMU_TARGET_RISCV_H 6 | #define UC_QEMU_TARGET_RISCV_H 7 | 8 | // functions to read & write registers 9 | uc_err reg_read_riscv32(void *env, int mode, unsigned int regid, void *value, 10 | size_t *size); 11 | uc_err reg_read_riscv64(void *env, int mode, unsigned int regid, void *value, 12 | size_t *size); 13 | uc_err reg_write_riscv32(void *env, int mode, unsigned int regid, 14 | const void *value, size_t *size, int *setpc); 15 | uc_err reg_write_riscv64(void *env, int mode, unsigned int regid, 16 | const void *value, size_t *size, int *setpc); 17 | 18 | void uc_init_riscv32(struct uc_struct *uc); 19 | void uc_init_riscv64(struct uc_struct *uc); 20 | #endif 21 | -------------------------------------------------------------------------------- /qemu/target/s390x/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * S/390 cpu parameters for qemu. 3 | * 4 | * Copyright (c) 2009 Ulrich Hecht 5 | * SPDX-License-Identifier: GPL-2.0+ 6 | */ 7 | 8 | #ifndef S390_CPU_PARAM_H 9 | #define S390_CPU_PARAM_H 1 10 | 11 | #define TARGET_LONG_BITS 64 12 | #define TARGET_PAGE_BITS 12 13 | #define TARGET_PHYS_ADDR_SPACE_BITS 64 14 | #define TARGET_VIRT_ADDR_SPACE_BITS 64 15 | #define NB_MMU_MODES 4 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /qemu/target/s390x/cpu_features_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CPU features/facilities for s390 3 | * 4 | * Copyright IBM Corp. 2016, 2018 5 | * Copyright Red Hat, Inc. 2019 6 | * 7 | * Author(s): Michael Mueller 8 | * David Hildenbrand 9 | * 10 | * This work is licensed under the terms of the GNU GPL, version 2 or (at 11 | * your option) any later version. See the COPYING file in the top-level 12 | * directory. 13 | */ 14 | 15 | #ifndef TARGET_S390X_CPU_FEATURES_DEF_H 16 | #define TARGET_S390X_CPU_FEATURES_DEF_H 17 | 18 | #define DEF_FEAT(_FEAT, ...) S390_FEAT_##_FEAT, 19 | typedef enum { 20 | #include "cpu_features_def.inc.h" 21 | S390_FEAT_MAX, 22 | } S390Feat; 23 | #undef DEF_FEAT 24 | 25 | #endif /* TARGET_S390X_CPU_FEATURES_DEF_H */ 26 | -------------------------------------------------------------------------------- /qemu/target/s390x/s390-tod.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TOD (Time Of Day) clock 3 | * 4 | * Copyright 2018 Red Hat, Inc. 5 | * Author(s): David Hildenbrand 6 | * 7 | * This work is licensed under the terms of the GNU GPL, version 2 or later. 8 | * See the COPYING file in the top-level directory. 9 | */ 10 | 11 | #ifndef TARGET_S390_TOD_H 12 | #define TARGET_S390_TOD_H 13 | 14 | /* The value of the TOD clock for 1.1.1970. */ 15 | #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL 16 | 17 | /* Converts ns to s390's clock format */ 18 | static inline uint64_t time2tod(uint64_t ns) 19 | { 20 | return (ns << 9) / 125 + (((ns & 0xff80000000000000ull) / 125) << 9); 21 | } 22 | 23 | /* Converts s390's clock format to ns */ 24 | static inline uint64_t tod2time(uint64_t t) 25 | { 26 | return ((t >> 9) * 125) + (((t & 0x1ff) * 125) >> 9); 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /qemu/target/s390x/tcg-stub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU TCG support -- s390x specific function stubs. 3 | * 4 | * Copyright (C) 2018 Red Hat Inc 5 | * 6 | * Authors: 7 | * David Hildenbrand 8 | * 9 | * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 | * See the COPYING file in the top-level directory. 11 | */ 12 | 13 | #include "qemu/osdep.h" 14 | #include "qemu-common.h" 15 | #include "cpu.h" 16 | #include "tcg_s390x.h" -------------------------------------------------------------------------------- /qemu/target/s390x/tcg_s390x.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU TCG support -- s390x specific functions. 3 | * 4 | * Copyright 2018 Red Hat, Inc. 5 | * 6 | * Authors: 7 | * David Hildenbrand 8 | * 9 | * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 | * See the COPYING file in the top-level directory. 11 | */ 12 | 13 | #ifndef TCG_S390X_H 14 | #define TCG_S390X_H 15 | 16 | void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque); 17 | void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, 18 | uint32_t code, uintptr_t ra); 19 | void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc, 20 | uintptr_t ra); 21 | void QEMU_NORETURN tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc, 22 | uintptr_t ra); 23 | 24 | #endif /* TCG_S390X_H */ 25 | -------------------------------------------------------------------------------- /qemu/target/s390x/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015-2021 */ 3 | 4 | #ifndef UC_QEMU_TARGET_S390X_H 5 | #define UC_QEMU_TARGET_S390X_H 6 | 7 | // functions to read & write registers 8 | uc_err reg_read_s390x(void *env, int mode, unsigned int regid, void *value, 9 | size_t *size); 10 | uc_err reg_write_s390x(void *env, int mode, unsigned int regid, 11 | const void *value, size_t *size, int *setpc); 12 | 13 | void uc_init_s390x(struct uc_struct *uc); 14 | #endif 15 | -------------------------------------------------------------------------------- /qemu/target/sparc/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Sparc cpu parameters for qemu. 3 | * 4 | * SPDX-License-Identifier: LGPL-2.0+ 5 | */ 6 | 7 | #ifndef SPARC_CPU_PARAM_H 8 | #define SPARC_CPU_PARAM_H 1 9 | 10 | #ifdef TARGET_SPARC64 11 | # define TARGET_LONG_BITS 64 12 | # define TARGET_PAGE_BITS 13 /* 8k */ 13 | # define TARGET_PHYS_ADDR_SPACE_BITS 41 14 | # ifdef TARGET_ABI32 15 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 16 | # else 17 | # define TARGET_VIRT_ADDR_SPACE_BITS 44 18 | # endif 19 | # define NB_MMU_MODES 6 20 | #else 21 | # define TARGET_LONG_BITS 32 22 | # define TARGET_PAGE_BITS 12 /* 4k */ 23 | # define TARGET_PHYS_ADDR_SPACE_BITS 36 24 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 25 | # define NB_MMU_MODES 3 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /qemu/target/sparc/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015 */ 3 | 4 | #ifndef UC_QEMU_TARGET_SPARC_H 5 | #define UC_QEMU_TARGET_SPARC_H 6 | 7 | // functions to read & write registers 8 | uc_err reg_read_sparc(void *env, int mode, unsigned int regid, void *value, 9 | size_t *size); 10 | uc_err reg_read_sparc64(void *env, int mode, unsigned int regid, void *value, 11 | size_t *size); 12 | uc_err reg_write_sparc(void *env, int mode, unsigned int regid, 13 | const void *value, size_t *size, int *setpc); 14 | uc_err reg_write_sparc64(void *env, int mode, unsigned int regid, 15 | const void *value, size_t *size, int *setpc); 16 | 17 | void uc_init_sparc(struct uc_struct *uc); 18 | void uc_init_sparc64(struct uc_struct *uc); 19 | #endif 20 | -------------------------------------------------------------------------------- /qemu/target/tricore/cpu-param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TriCore cpu parameters for qemu. 3 | * 4 | * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn 5 | * SPDX-License-Identifier: LGPL-2.1+ 6 | */ 7 | 8 | #ifndef TRICORE_CPU_PARAM_H 9 | #define TRICORE_CPU_PARAM_H 1 10 | 11 | #define TARGET_LONG_BITS 32 12 | #define TARGET_PAGE_BITS 14 13 | #define TARGET_PHYS_ADDR_SPACE_BITS 32 14 | #define TARGET_VIRT_ADDR_SPACE_BITS 32 15 | #define NB_MMU_MODES 3 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /qemu/target/tricore/tricore-defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, see . 16 | */ 17 | 18 | #ifndef QEMU_TRICORE_DEFS_H 19 | #define QEMU_TRICORE_DEFS_H 20 | 21 | #define TRICORE_TLB_MAX 128 22 | 23 | #endif /* QEMU_TRICORE_DEFS_H */ 24 | -------------------------------------------------------------------------------- /qemu/target/tricore/unicorn.h: -------------------------------------------------------------------------------- 1 | /* Unicorn Emulator Engine */ 2 | /* By Nguyen Anh Quynh , 2015 */ 3 | 4 | /* 5 | Modified for Unicorn Engine by Eric Poole , 2022 6 | Copyright 2022 Aptiv 7 | */ 8 | 9 | #ifndef UC_QEMU_TARGET_TRICORE_H 10 | #define UC_QEMU_TARGET_TRICORE_H 11 | 12 | // functions to read & write registers 13 | uc_err reg_read_tricore(void *env, int mode, unsigned int regid, void *value, 14 | size_t *size); 15 | uc_err reg_write_tricore(void *env, int mode, unsigned int regid, 16 | const void *value, size_t *size, int *setpc); 17 | 18 | void uc_init_tricore(struct uc_struct *uc); 19 | #endif 20 | -------------------------------------------------------------------------------- /qemu/tcg/aarch64/tcg-target.opc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Linaro 3 | * 4 | * This work is licensed under the terms of the GNU GPL, version 2 or 5 | * (at your option) any later version. 6 | * 7 | * See the COPYING file in the top-level directory for details. 8 | * 9 | * Target-specific opcodes for host vector expansion. These will be 10 | * emitted by tcg_expand_vec_op. For those familiar with GCC internals, 11 | * consider these to be UNSPEC with names. 12 | */ 13 | 14 | DEF(aa64_sshl_vec, 1, 2, 0, IMPLVEC) 15 | -------------------------------------------------------------------------------- /qemu/trace/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Helper functions for guest memory tracing 3 | * 4 | * Copyright (C) 2016 Lluís Vilanova 5 | * 6 | * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 | * See the COPYING file in the top-level directory. 8 | */ 9 | 10 | #ifndef TRACE__MEM_H 11 | #define TRACE__MEM_H 12 | 13 | #include "tcg/tcg.h" 14 | 15 | 16 | /** 17 | * trace_mem_get_info: 18 | * 19 | * Return a value for the 'info' argument in guest memory access traces. 20 | */ 21 | static uint16_t trace_mem_get_info(MemOp op, unsigned int mmu_idx, bool store); 22 | 23 | /** 24 | * trace_mem_build_info: 25 | * 26 | * Return a value for the 'info' argument in guest memory access traces. 27 | */ 28 | static uint16_t trace_mem_build_info(int size_shift, bool sign_extend, 29 | MemOp endianness, bool store, 30 | unsigned int mmuidx); 31 | 32 | 33 | #include "mem-internal.h" 34 | 35 | #endif /* TRACE__MEM_H */ 36 | -------------------------------------------------------------------------------- /qemu/util/pagesize.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pagesize.c - query the host about its page size 3 | * 4 | * Copyright (C) 2017, Emilio G. Cota 5 | * License: GNU GPL, version 2 or later. 6 | * See the COPYING file in the top-level directory. 7 | */ 8 | 9 | #include "qemu/osdep.h" 10 | 11 | #include 12 | 13 | void init_real_host_page_size(struct uc_struct *uc) 14 | { 15 | uc->qemu_real_host_page_size = getpagesize(); 16 | } 17 | -------------------------------------------------------------------------------- /qemu/util/qemu-timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU System Emulator 3 | * 4 | * Copyright (c) 2003-2008 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "qemu/osdep.h" 26 | #include "qemu/timer.h" 27 | #include "uc_priv.h" 28 | #include "sysemu/cpus.h" 29 | #include "qemu/queue.h" 30 | 31 | int64_t qemu_clock_get_ns(QEMUClockType type) 32 | { 33 | return get_clock(); 34 | } 35 | -------------------------------------------------------------------------------- /qemu/util/setjmp-wrapper-win32.asm: -------------------------------------------------------------------------------- 1 | EXTERN _setjmp: proc 2 | PUBLIC _setjmp_wrapper 3 | 4 | _TEXT SEGMENT 5 | 6 | _setjmp_wrapper PROC 7 | 8 | ; Why do we need this wrapper? 9 | ; Short answer: Windows default implementation of setjmp/longjmp is incompatible with generated code. 10 | ; A longer answer: https://blog.lazym.io/2020/09/21/Unicorn-Devblog-setjmp-longjmp-on-Windows/. 11 | 12 | ; From qemu os-win32 comments: 13 | ; > On w64, setjmp is implemented by _setjmp which needs a second parameter. 14 | ; > If this parameter is NULL, longjump does no stack unwinding. 15 | ; > That is what we need for QEMU. Passing the value of register rsp (default) 16 | ; > lets longjmp try a stack unwinding which will crash with generated code. 17 | ; It's true indeed, but MSVC doesn't has a setjmp signature which receives two arguements. 18 | ; Therefore, we add a wrapper to keep the second argument zero. 19 | xor rdx, rdx 20 | jmp _setjmp 21 | 22 | _setjmp_wrapper ENDP 23 | 24 | _TEXT ENDS 25 | 26 | END -------------------------------------------------------------------------------- /qemu/vl.h: -------------------------------------------------------------------------------- 1 | #ifndef VL_H_ 2 | #define VL_H_ 3 | 4 | int machine_initialize(struct uc_struct *uc); 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | See [this](../docs/Testing.md) -------------------------------------------------------------------------------- /tests/benchmarks/cow/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -Wall -Werror -I../../../include 2 | CFLAGS += -D__USE_MINGW_ANSI_STDIO=1 3 | LDLIBS += -L../../../build -lgsl -lgslcblas -lm -lunicorn 4 | 5 | UNAME_S := $(shell uname -s) 6 | LDLIBS += -pthread 7 | ifeq ($(UNAME_S), Linux) 8 | LDLIBS += -lrt 9 | endif 10 | 11 | #EXECUTE_VARS = LD_LIBRARY_PATH=../../cmocka/src:../../build/ DYLD_LIBRARY_PATH=../../build/ 12 | EXECUTE_VARS = LD_LIBRARY_PATH=../../../build/cmocka/src:../../../build/ DYLD_LIBRARY_PATH=../../../build/ 13 | 14 | TESTS_SOURCE = $(wildcard *.c) 15 | TESTS = $(TESTS_SOURCE:%.c=%) 16 | 17 | .PHONY: all clean test 18 | 19 | test: $(TESTS) 20 | 21 | all: $(TESTS) 22 | 23 | clean: 24 | rm -f $(TESTS) 25 | -------------------------------------------------------------------------------- /tests/benchmarks/cow/binary.S: -------------------------------------------------------------------------------- 1 | USE64 2 | DEFAULT REL 3 | 4 | SECTION .text 5 | loop: 6 | xor rcx, rcx 7 | write: 8 | mov [rbx+rcx*8], rsi 9 | inc rcx 10 | mov rdi, rax 11 | sub rdi, rcx 12 | jnz write 13 | jmp loop 14 | -------------------------------------------------------------------------------- /tests/fuzz/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -L ../../ -I ../../include 2 | 3 | UNAME_S := $(shell uname -s) 4 | LDFLAGS += -pthread 5 | ifeq ($(UNAME_S), Linux) 6 | LDFLAGS += -lrt 7 | endif 8 | 9 | LDFLAGS += ../../libunicorn.a 10 | 11 | 12 | ALL_TESTS_SOURCES = $(wildcard fuzz*.c) 13 | ALL_TESTS = $(ALL_TESTS_SOURCES:%.c=%) 14 | 15 | .PHONY: all 16 | all: ${ALL_TESTS} 17 | 18 | .PHONY: clean 19 | clean: 20 | rm -rf ${ALL_TESTS} 21 | 22 | fuzz%: fuzz%.c 23 | $(CC) $(CFLAGS) $^ onedir.c $(LDFLAGS) -o $@ 24 | -------------------------------------------------------------------------------- /tests/fuzz/dlcorpus.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | #change to script directory 3 | cd `dirname $0` 4 | ls fuzz_emu*.c | sed 's/.c//' | while read target 5 | do 6 | #download public corpus 7 | wget "https://storage.googleapis.com/unicorn-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/unicorn_$target/public.zip" 8 | unzip -q public.zip -d corpus_$target 9 | #run target on corpus 10 | ./$target corpus_$target 11 | done 12 | -------------------------------------------------------------------------------- /tests/fuzz/fuzz_emu.options: -------------------------------------------------------------------------------- 1 | [libfuzzer] 2 | max_len = 4096 3 | -------------------------------------------------------------------------------- /tests/fuzz/onefile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 6 | 7 | int main(int argc, char** argv) 8 | { 9 | FILE * fp; 10 | uint8_t *Data; 11 | size_t Size; 12 | 13 | if (argc != 2) { 14 | return 1; 15 | } 16 | //opens the file, get its size, and reads it into a buffer 17 | fp = fopen(argv[1], "rb"); 18 | if (fp == NULL) { 19 | return 2; 20 | } 21 | if (fseek(fp, 0L, SEEK_END) != 0) { 22 | fclose(fp); 23 | return 2; 24 | } 25 | Size = ftell(fp); 26 | if (Size == (size_t) -1) { 27 | fclose(fp); 28 | return 2; 29 | } 30 | if (fseek(fp, 0L, SEEK_SET) != 0) { 31 | fclose(fp); 32 | return 2; 33 | } 34 | Data = malloc(Size); 35 | if (Data == NULL) { 36 | fclose(fp); 37 | return 2; 38 | } 39 | if (fread(Data, Size, 1, fp) != 1) { 40 | fclose(fp); 41 | return 2; 42 | } 43 | 44 | //lauch fuzzer 45 | LLVMFuzzerTestOneInput(Data, Size); 46 | fclose(fp); 47 | return 0; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /tests/regress/.gitignore: -------------------------------------------------------------------------------- 1 | !*.c 2 | 3 | arm_enable_vfp 4 | map_crash 5 | sigill 6 | sigill2 7 | block_test 8 | map_write 9 | ro_mem_test 10 | nr_mem_test 11 | timeout_segfault 12 | rep_movsb 13 | mips_kseg0_1 14 | eflags_nosync 15 | 00opcode_uc_crash 16 | eflags_noset 17 | invalid_read_in_cpu_tb_exec 18 | invalid_write_in_cpu_tb_exec_x86_64 19 | x86_16_segfault 20 | mips_invalid_read_of_size_4_when_tracing 21 | invalid_read_in_tb_flush_x86_64 22 | sparc_jump_to_zero 23 | mips_delay_slot_code_hook 24 | threaded_emu_start 25 | emu_stop_in_hook_overrun 26 | mips_branch_likely_issue 27 | emu_clear_errors 28 | 001-bad_condition_code_0xe 29 | 002-qemu__fatal__unimplemented_control_register_write_0xffb___0x0 30 | 003-qemu__fatal__wdebug_not_implemented 31 | 004-segmentation_fault_1 32 | 005-qemu__fatal__illegal_instruction__0000___00000404 33 | 006-qemu__fatal__illegal_instruction__0421___00040026 34 | 35 | rw_hookstack 36 | hook_extrainvoke 37 | sysenter_hook_x86 38 | 39 | memleak_* 40 | mem_* 41 | -------------------------------------------------------------------------------- /tests/regress/001-bad_condition_code_0xe.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define HARDWARE_ARCHITECTURE UC_ARCH_ARM 4 | #define HARDWARE_MODE 16 5 | #define MEMORY_STARTING_ADDRESS 8192 6 | #define MEMORY_SIZE 4096 7 | #define MEMORY_PERMISSIONS 6 8 | #define BINARY_CODE "\x56\xe8\x46\x46\x80\xf6\x8c\x56\xff\xbf\xcd\x90\xda\xa0\xed\xe8\x46\x43\x45\xe5\x80\x90\x44\x46\x04" 9 | 10 | static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { 11 | printf("hook_code(…) called\n"); 12 | } 13 | 14 | int main(int argc, char **argv, char **envp) { 15 | uc_engine *uc; 16 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 17 | printf("uc_open(…) failed\n"); 18 | return 1; 19 | } 20 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 21 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 22 | printf("uc_mem_write(…) failed\n"); 23 | return 1; 24 | } 25 | uc_hook trace; 26 | uc_hook_add(uc, &trace, UC_HOOK_CODE, hook_code, NULL, (uint64_t)MEMORY_STARTING_ADDRESS, (uint64_t)(MEMORY_STARTING_ADDRESS + 1)); 27 | printf("uc_emu_start(…)\n"); 28 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 0); 29 | printf("done\n"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/regress/002-qemu__fatal__unimplemented_control_register_write_0xffb___0x0.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define HARDWARE_ARCHITECTURE UC_ARCH_M68K 4 | #define HARDWARE_MODE 1073741824 5 | #define MEMORY_STARTING_ADDRESS 8388608 6 | #define MEMORY_SIZE 2097152 7 | #define MEMORY_PERMISSIONS 7 8 | #define BINARY_CODE "\xaf\x80\x4e\x7b\xff\xfb\x80\x4e\x3e\x80" 9 | 10 | static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { 11 | printf("hook_code(…) called\n"); 12 | } 13 | 14 | int main(int argc, char **argv, char **envp) { 15 | uc_engine *uc; 16 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 17 | printf("uc_open(…) failed\n"); 18 | return 1; 19 | } 20 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 21 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 22 | printf("uc_mem_write(…) failed\n"); 23 | return 1; 24 | } 25 | uc_hook trace; 26 | uc_hook_add(uc, &trace, UC_HOOK_CODE, hook_code, NULL, (uint64_t)MEMORY_STARTING_ADDRESS, (uint64_t)(MEMORY_STARTING_ADDRESS + 1)); 27 | printf("uc_emu_start(…)\n"); 28 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 0); 29 | printf("done\n"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/regress/003-qemu__fatal__wdebug_not_implemented.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define HARDWARE_ARCHITECTURE UC_ARCH_M68K 4 | #define HARDWARE_MODE 1073741824 5 | #define MEMORY_STARTING_ADDRESS 1048576 6 | #define MEMORY_SIZE 403456 7 | #define MEMORY_PERMISSIONS 7 8 | #define BINARY_CODE "\x42\xc7\xfb\xfb\x54\x36" 9 | 10 | static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { 11 | printf("hook_code(…) called\n"); 12 | } 13 | 14 | int main(int argc, char **argv, char **envp) { 15 | uc_engine *uc; 16 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 17 | printf("uc_open(…) failed\n"); 18 | return 1; 19 | } 20 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 21 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 22 | printf("uc_mem_write(…) failed\n"); 23 | return 1; 24 | } 25 | uc_hook trace; 26 | uc_hook_add(uc, &trace, UC_HOOK_CODE, hook_code, NULL, (uint64_t)MEMORY_STARTING_ADDRESS, (uint64_t)(MEMORY_STARTING_ADDRESS + 1)); 27 | printf("uc_emu_start(…)\n"); 28 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 0); 29 | printf("done\n"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/regress/004-segmentation_fault_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define HARDWARE_ARCHITECTURE UC_ARCH_ARM 4 | #define HARDWARE_MODE 16 5 | #define MEMORY_STARTING_ADDRESS 1024 6 | #define MEMORY_SIZE 1796096 7 | #define MEMORY_PERMISSIONS 7 8 | #define BINARY_CODE "\x20\xbf\xbf\xbf\xbf\xdd\x5d\x74\x5e\x66\x72\x10" 9 | 10 | static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { 11 | printf("hook_code(…) called\n"); 12 | } 13 | 14 | int main(int argc, char **argv, char **envp) { 15 | uc_engine *uc; 16 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 17 | printf("uc_open(…) failed\n"); 18 | return 1; 19 | } 20 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 21 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 22 | printf("uc_mem_write(…) failed\n"); 23 | return 1; 24 | } 25 | uc_hook trace; 26 | uc_hook_add(uc, &trace, UC_HOOK_CODE, hook_code, NULL, (uint64_t)MEMORY_STARTING_ADDRESS, (uint64_t)(MEMORY_STARTING_ADDRESS + 1)); 27 | printf("uc_emu_start(…)\n"); 28 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 0); 29 | printf("done\n"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/regress/005-qemu__fatal__illegal_instruction__0000___00000404.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define HARDWARE_ARCHITECTURE UC_ARCH_M68K 4 | #define HARDWARE_MODE 1073741824 5 | #define MEMORY_STARTING_ADDRESS 1024 6 | #define MEMORY_SIZE 1044480 7 | #define MEMORY_PERMISSIONS 5 8 | #define BINARY_CODE "\x4c\x4c" 9 | 10 | static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { 11 | printf("hook_code(…) called\n"); 12 | } 13 | 14 | int main(int argc, char **argv, char **envp) { 15 | uc_engine *uc; 16 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 17 | printf("uc_open(…) failed\n"); 18 | return 1; 19 | } 20 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 21 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 22 | printf("uc_mem_write(…) failed\n"); 23 | return 1; 24 | } 25 | uc_hook trace; 26 | uc_hook_add(uc, &trace, UC_HOOK_CODE, hook_code, NULL, (uint64_t)MEMORY_STARTING_ADDRESS, (uint64_t)(MEMORY_STARTING_ADDRESS + 1)); 27 | printf("uc_emu_start(…)\n"); 28 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 0); 29 | printf("done\n"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/regress/006-qemu__fatal__illegal_instruction__0421___00040026.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define HARDWARE_ARCHITECTURE UC_ARCH_M68K 4 | #define HARDWARE_MODE 1073741824 5 | #define MEMORY_STARTING_ADDRESS 262144 6 | #define MEMORY_SIZE 403456 7 | #define MEMORY_PERMISSIONS 7 8 | #define BINARY_CODE "\xe2\x86\x09\xbc\xf2\x17\x09\xca\xca\xca\xca\x09\x09\x09\xf2\x17\x09\x20\x09\x09\xf2\x08\x09\x03\x09\xca\x6b\x6b\x6b\x1e\xca\xca\x86\x09\x09\xf2\x17\x09\x04\x21\x09\x09\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf2" 9 | 10 | static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { 11 | printf("hook_code(…) called\n"); 12 | } 13 | 14 | int main(int argc, char **argv, char **envp) { 15 | uc_engine *uc; 16 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 17 | printf("uc_open(…) failed\n"); 18 | return 1; 19 | } 20 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 21 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 22 | printf("uc_mem_write(…) failed\n"); 23 | return 1; 24 | } 25 | uc_hook trace; 26 | uc_hook_add(uc, &trace, UC_HOOK_CODE, hook_code, NULL, (uint64_t)MEMORY_STARTING_ADDRESS, (uint64_t)(MEMORY_STARTING_ADDRESS + 1)); 27 | printf("uc_emu_start(…)\n"); 28 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 0); 29 | printf("done\n"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/regress/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -Wall -Werror -I../../include 2 | CFLAGS += -D__USE_MINGW_ANSI_STDIO=1 3 | LDLIBS += -L../../ -lm -lunicorn 4 | 5 | UNAME_S := $(shell uname -s) 6 | LDLIBS += -pthread 7 | ifeq ($(UNAME_S), Linux) 8 | LDLIBS += -lrt 9 | endif 10 | 11 | EXECUTE_VARS = LD_LIBRARY_PATH=../../cmocka/src:../../ DYLD_LIBRARY_PATH=../../ 12 | 13 | TESTS_SOURCE = $(wildcard *.c) 14 | TESTS = $(TESTS_SOURCE:%.c=%) 15 | 16 | .PHONY: all clean test 17 | 18 | test: $(TESTS) 19 | 20 | all: $(TESTS) 21 | 22 | clean: 23 | rm -f $(TESTS) 24 | -------------------------------------------------------------------------------- /tests/regress/arm64_reg_rw_w0_w30.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.arm64_const import * 4 | 5 | 6 | class Arm64RegReadWriteW0ThroughW30(regress.RegressTest): 7 | """ 8 | Testing the functionality to read/write 32-bit registers in AArch64 9 | See issue #716 10 | """ 11 | 12 | def runTest(self): 13 | uc = Uc(UC_ARCH_ARM64, UC_MODE_ARM) 14 | 15 | expected = 0x1234567890abcdef 16 | 17 | uc.reg_write(UC_ARM64_REG_X0, expected) 18 | self.assertEqual(uc.reg_read(UC_ARM64_REG_X0), expected) 19 | self.assertEqual(uc.reg_read(UC_ARM64_REG_W0), expected & 0xffffffff) 20 | 21 | # ---------------------------------------------------------- 22 | 23 | expected = 0xa1b2c3d4e5f6a7b8 24 | 25 | uc.reg_write(UC_ARM64_REG_X30, expected) 26 | self.assertEqual(uc.reg_read(UC_ARM64_REG_W30), expected & 0xffffffff) 27 | 28 | expected_lo = 0xaabbccdd 29 | 30 | uc.reg_write(UC_ARM64_REG_W30, expected_lo) 31 | self.assertEqual(uc.reg_read(UC_ARM64_REG_X30), (expected & ~0xffffffff) | expected_lo) 32 | self.assertEqual(uc.reg_read(UC_ARM64_REG_W30), expected_lo) 33 | 34 | 35 | if __name__ == '__main__': 36 | regress.main() 37 | -------------------------------------------------------------------------------- /tests/regress/arm_bxeq_hang.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.arm_const import * 4 | 5 | 6 | class BxHang(regress.RegressTest): 7 | def runTest(self): 8 | uc = Uc(UC_ARCH_ARM, UC_MODE_ARM) 9 | uc.mem_map(0x1000, 0x1000) 10 | uc.mem_write(0x1000, b'\x1e\xff\x2f\x01\x00\x00\xa0\xe1') # bxeq lr; mov r0, r0 11 | uc.count = 0 12 | 13 | def hook_block(uc, addr, *args): 14 | regress.logger.debug('enter block %#06x', addr) 15 | uc.count += 1 16 | 17 | uc.reg_write(UC_ARM_REG_LR, 0x1004) 18 | uc.hook_add(UC_HOOK_BLOCK, hook_block) 19 | 20 | regress.logger.debug('block should only run once') 21 | uc.emu_start(0x1000, 0x1004) 22 | 23 | self.assertEqual(uc.count, 1) 24 | 25 | 26 | if __name__ == '__main__': 27 | regress.main() 28 | -------------------------------------------------------------------------------- /tests/regress/arm_fp_vfp_disabled.py: -------------------------------------------------------------------------------- 1 | # Added by Peter Mackay, relating to issue 571 2 | # ARM NEON/VFP support seems to exist but is disabled by default 3 | # https://github.com/unicorn-engine/unicorn/issues/571 4 | 5 | import regress 6 | from unicorn import * 7 | from unicorn.arm_const import * 8 | 9 | CODE = ( 10 | b'\x11\xEE\x50\x1F' # MRC p15, #0, r1, c1, c0, #2 11 | b'\x41\xF4\x70\x01' # ORR r1, r1, #(0xf << 20) 12 | b'\x01\xEE\x50\x1F' # MCR p15, #0, r1, c1, c0, #2 13 | b'\x4F\xF0\x00\x01' # MOV r1, #0 14 | b'\x07\xEE\x95\x1F' # MCR p15, #0, r1, c7, c5, #4 15 | b'\x4F\xF0\x80\x40' # MOV r0,#0x40000000 16 | b'\xE8\xEE\x10\x0A' # FMXR FPEXC, r0 17 | b'\x2d\xed\x02\x8b' # vpush {d8} 18 | ) 19 | 20 | BASE = 0x1000 21 | 22 | 23 | class FpVfpDisabled(regress.RegressTest): 24 | 25 | def runTest(self): 26 | mem_size = 0x1000 27 | 28 | uc = Uc(UC_ARCH_ARM, UC_MODE_THUMB) 29 | 30 | uc.mem_map(BASE, mem_size) 31 | uc.mem_write(BASE, CODE) 32 | uc.reg_write(UC_ARM_REG_SP, BASE + mem_size - 4) 33 | 34 | uc.emu_start(BASE + 1, BASE + len(CODE)) 35 | 36 | 37 | if __name__ == '__main__': 38 | regress.main() 39 | -------------------------------------------------------------------------------- /tests/regress/arm_movr12_hang.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.arm_const import * 4 | 5 | 6 | class MovHang(regress.RegressTest): 7 | 8 | # NOTE: This test was failing when workflow was using ubuntu-latest + qemu. Fixed once switched to native arm runner 9 | def runTest(self): 10 | uc = Uc(UC_ARCH_ARM, UC_MODE_ARM) 11 | uc.mem_map(0x1000, 0x1000) 12 | uc.mem_write(0x1000, b'\x00\xc0\x00\xe3') # movw r12, #0 13 | 14 | def hook_block(uc, addr, *args): 15 | regress.logger.debug('enter block 0x%#06x', addr) 16 | uc.count += 1 17 | 18 | uc.reg_write(UC_ARM_REG_R12, 0x123) 19 | self.assertEqual(0x123, uc.reg_read(UC_ARM_REG_R12)) 20 | 21 | uc.hook_add(UC_HOOK_BLOCK, hook_block) 22 | uc.count = 0 23 | 24 | # print 'block should only run once' 25 | uc.emu_start(0x1000, 0x1004, timeout=500) 26 | 27 | self.assertEqual(0x0, uc.reg_read(UC_ARM_REG_R12)) 28 | self.assertEqual(uc.count, 1) 29 | 30 | 31 | if __name__ == '__main__': 32 | regress.main() 33 | -------------------------------------------------------------------------------- /tests/regress/arm_vldr_invalid.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | 4 | 5 | class VldrPcInsn(regress.RegressTest): 6 | 7 | def runTest(self): 8 | uc = Uc(UC_ARCH_ARM, UC_MODE_ARM) 9 | 10 | uc.mem_map(0x1000, 0x1000) 11 | uc.mem_write(0x1000, b'\xed\x9f\x8a\x3d') # vldr s16, [pc, #244] 12 | 13 | with self.assertRaises(UcError) as ex: 14 | uc.emu_start(0x1000, 0x1004) 15 | 16 | self.assertEqual(UC_ERR_INSN_INVALID, ex.exception.errno) 17 | 18 | 19 | if __name__ == '__main__': 20 | regress.main() 21 | -------------------------------------------------------------------------------- /tests/regress/arm_wfi_first_insn_of_tb.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | 4 | CODE = ( 5 | b'\x00\x00\x8a\xe0' # ADD R0, R10, R0 6 | b'\xff\xff\xff\xea' # B L0 7 | b'\x00\x00\x8a\xe0' # L0: ADD R0, R10, R0 <-- we stop here, the first instruction of the next TB 8 | ) 9 | 10 | BASE = 0x1000 11 | 12 | 13 | class TestARMFirstInsn(regress.RegressTest): 14 | def runTest(self): 15 | mu = Uc(UC_ARCH_ARM, UC_MODE_ARM) 16 | 17 | mu.mem_map(BASE, 0x1000) 18 | mu.mem_write(BASE, CODE) 19 | 20 | mu.emu_start(BASE, BASE + len(CODE) - 4) 21 | 22 | 23 | if __name__ == '__main__': 24 | regress.main() 25 | -------------------------------------------------------------------------------- /tests/regress/bad_ram.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | 6 | class BadRam(regress.RegressTest): 7 | def runTest(self): 8 | PAGE_SIZE = 0x5000 9 | CODE_ADDR = 0x400000 10 | RSP_ADDR = 0x200000 11 | 12 | CODE = b"\xCA\x24\x5D" # retf 0x5d24 13 | 14 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 15 | 16 | mu.mem_map(CODE_ADDR, PAGE_SIZE) 17 | mu.mem_map(RSP_ADDR, PAGE_SIZE) 18 | 19 | mu.mem_write(CODE_ADDR, CODE) 20 | mu.reg_write(UC_X86_REG_RSP, RSP_ADDR) 21 | 22 | # make sure we bump into an exception 23 | with self.assertRaises(UcError) as raisedEx: 24 | mu.emu_start(CODE_ADDR, CODE_ADDR + PAGE_SIZE) 25 | 26 | # make sure it is an exception with the errno we expect 27 | self.assertEqual(raisedEx.exception.errno, UC_ERR_READ_UNMAPPED) 28 | 29 | 30 | if __name__ == '__main__': 31 | regress.main() 32 | -------------------------------------------------------------------------------- /tests/regress/crash_tb.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | CODE_ADDR = 0x0 6 | binary1 = b'\xb8\x02\x00\x00\x00' 7 | binary2 = b'\xb8\x01\x00\x00\x00' 8 | 9 | 10 | class CrashTB(regress.RegressTest): 11 | 12 | def runTest(self): 13 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 14 | 15 | mu.mem_map(CODE_ADDR, 2 * 1024 * 1024) 16 | 17 | # write machine code to be emulated to memory 18 | mu.mem_write(CODE_ADDR, binary1) 19 | 20 | # emu for maximum 1 sec. 21 | mu.emu_start(CODE_ADDR, len(binary1), UC_SECOND_SCALE) 22 | 23 | self.assertEqual(0x2, mu.reg_read(UC_X86_REG_RAX)) 24 | 25 | # write machine code to be emulated to memory 26 | mu.mem_write(CODE_ADDR, binary2) 27 | 28 | # emu for maximum 1 sec. 29 | mu.emu_start(CODE_ADDR, len(binary2), UC_SECOND_SCALE) 30 | 31 | self.assertEqual(0x1, mu.reg_read(UC_X86_REG_RAX)) 32 | 33 | 34 | if __name__ == '__main__': 35 | regress.main() 36 | -------------------------------------------------------------------------------- /tests/regress/deadlock_1.py: -------------------------------------------------------------------------------- 1 | # From issue #1 of Ryan Hileman 2 | 3 | import regress 4 | from unicorn import * 5 | 6 | CODE = b"\x90\x91\x92" 7 | 8 | 9 | class DeadLock(regress.RegressTest): 10 | 11 | def runTest(self): 12 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 13 | mu.mem_map(0x100000, 4 * 1024) 14 | mu.mem_write(0x100000, CODE) 15 | 16 | with self.assertRaises(UcError): 17 | mu.emu_start(0x100000, 0x1000 + len(CODE)) 18 | 19 | 20 | if __name__ == '__main__': 21 | regress.main() 22 | -------------------------------------------------------------------------------- /tests/regress/emu_stop_segfault.py: -------------------------------------------------------------------------------- 1 | """ See https://github.com/unicorn-engine/unicorn/issues/65 """ 2 | 3 | import regress 4 | import unicorn 5 | 6 | 7 | class EmuStopSegFault(regress.RegressTest): 8 | 9 | def runTest(self): 10 | ADDR = 0x10101000 11 | mu = unicorn.Uc(unicorn.UC_ARCH_X86, unicorn.UC_MODE_32) 12 | mu.mem_map(ADDR, 1024 * 4) 13 | mu.mem_write(ADDR, b'\x41') 14 | mu.emu_start(ADDR, ADDR + 1, count=1) 15 | # The following should not trigger a null pointer dereference 16 | self.assertEqual(None, mu.emu_stop()) 17 | 18 | 19 | if __name__ == '__main__': 20 | regress.main() 21 | -------------------------------------------------------------------------------- /tests/regress/ensure_typedef_consts_generated.py: -------------------------------------------------------------------------------- 1 | """ 2 | See https://github.com/unicorn-engine/unicorn/issues/161 3 | 4 | Ensure that constants which are specified via a typedef, rather than an enum, 5 | are included in the bindings by the script for autogenerating mappings for 6 | constants. 7 | """ 8 | 9 | import regress 10 | import unicorn 11 | 12 | 13 | class TestTypedefs(regress.RegressTest): 14 | def runTest(self): 15 | prop = 'UC_HOOK_MEM_UNMAPPED' 16 | 17 | try: 18 | getattr(unicorn, prop) 19 | except AttributeError: 20 | self.fail("Definition for %s not generated" % prop) 21 | 22 | 23 | if __name__ == '__main__': 24 | regress.main() 25 | -------------------------------------------------------------------------------- /tests/regress/fpu_mem_write.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | CODE = ( 6 | b'\x9b\xd9\x3c\x24' # fstcw WORD PTR [esp] 7 | b'\x59' # pop ecx 8 | ) 9 | 10 | BASE = 0x00000000 11 | STACK = 0x00000f00 12 | 13 | 14 | def hook_mem_write(uc, access, address, size, value, user_data): 15 | regress.logger.debug("mem WRITE to: %#x, size = %u, value = %#x", address, size, value) 16 | return True 17 | 18 | 19 | class FpuWrite(regress.RegressTest): 20 | 21 | def runTest(self): 22 | mu = Uc(UC_ARCH_X86, UC_MODE_32) 23 | 24 | mu.mem_map(BASE, 0x1000) 25 | mu.mem_write(BASE, CODE) 26 | mu.reg_write(UC_X86_REG_ESP, STACK) 27 | 28 | mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_write) 29 | mu.emu_start(BASE, BASE + len(CODE), count=2) 30 | 31 | self.assertSequenceEqual(b'\x00' * 2, mu.mem_read(STACK, 2)) 32 | 33 | 34 | if __name__ == '__main__': 35 | regress.main() 36 | -------------------------------------------------------------------------------- /tests/regress/hook_add_crash.py: -------------------------------------------------------------------------------- 1 | """ https://github.com/unicorn-engine/unicorn/issues/165 """ 2 | 3 | import regress 4 | from unicorn import * 5 | 6 | 7 | class TestHook(regress.RegressTest): 8 | def test_excessive_hooks(self): 9 | mu = Uc(UC_ARCH_X86, UC_MODE_32) 10 | 11 | for _ in range(1337): 12 | mu.hook_add(UC_HOOK_MEM_READ_UNMAPPED, lambda *args, **kwargs: None) 13 | 14 | 15 | if __name__ == '__main__': 16 | regress.main() 17 | -------------------------------------------------------------------------------- /tests/regress/hook_raises_exception.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import Uc, UC_ARCH_X86, UC_MODE_64, UC_HOOK_CODE 3 | 4 | CODE = b"\x90" * 3 5 | CODE_ADDR = 0x1000 6 | 7 | 8 | class HookCounter: 9 | """Counts number of hook calls.""" 10 | 11 | def __init__(self): 12 | self.hook_calls = 0 13 | 14 | def bad_code_hook(self, uc, address, size, data): 15 | self.hook_calls += 1 16 | raise ValueError("Something went wrong") 17 | 18 | def good_code_hook(self, uc, address, size, data): 19 | self.hook_calls += 1 20 | 21 | 22 | class TestExceptionInHook(regress.RegressTest): 23 | 24 | def test_exception_in_hook(self): 25 | uc = Uc(UC_ARCH_X86, UC_MODE_64) 26 | uc.mem_map(CODE_ADDR, 0x1000) 27 | uc.mem_write(CODE_ADDR, CODE) 28 | 29 | counter = HookCounter() 30 | uc.hook_add(UC_HOOK_CODE, counter.good_code_hook, begin=CODE_ADDR, end=CODE_ADDR + len(CODE)) 31 | uc.hook_add(UC_HOOK_CODE, counter.bad_code_hook, begin=CODE_ADDR, end=CODE_ADDR + len(CODE)) 32 | 33 | self.assertRaises(ValueError, uc.emu_start, CODE_ADDR, CODE_ADDR + len(CODE)) 34 | # Make sure hooks calls finish before raising (hook_calls == 2) 35 | self.assertEqual(counter.hook_calls, 2) 36 | 37 | 38 | if __name__ == "__main__": 39 | regress.main() 40 | -------------------------------------------------------------------------------- /tests/regress/hook_readonly_write_local.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | PAGE_SIZE = 0x1000 6 | ACCESS_ADDR = 0x1000 7 | 8 | CODE = ( 9 | b'\xA1\x00\x10\x00\x00' # mov eax, [0x1000] 10 | b'\xA1\x00\x10\x00\x00' # mov eax, [0x1000] 11 | ) 12 | 13 | BASE = 0x00000000 14 | 15 | 16 | def hook_mem_read(uc, access, address, size, value, data): 17 | regress.logger.debug("Reading at %#x", address) 18 | # BUG: unicorn will segfault when calling "uc.mem_write" to write to a location that was mapped only as UC_PROT_READ 19 | uc.mem_write(address, CODE) 20 | 21 | 22 | class REP(regress.RegressTest): 23 | def runTest(self): 24 | mu = Uc(UC_ARCH_X86, UC_MODE_32) 25 | 26 | mu.mem_map(BASE, PAGE_SIZE) 27 | mu.mem_write(BASE, CODE) 28 | mu.mem_map(ACCESS_ADDR, PAGE_SIZE, UC_PROT_READ) 29 | mu.hook_add(UC_HOOK_MEM_READ, hook_mem_read, begin=ACCESS_ADDR, end=ACCESS_ADDR + PAGE_SIZE) 30 | 31 | mu.emu_start(BASE, BASE + len(CODE)) 32 | 33 | self.assertEqual(0x001000a1, mu.reg_read(UC_X86_REG_EAX)) 34 | 35 | 36 | if __name__ == '__main__': 37 | regress.main() 38 | -------------------------------------------------------------------------------- /tests/regress/invalid_read_in_cpu_tb_exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { 4 | printf("hook_block(%p, %"PRIx64", %d, %p)\n", uc, address, size, user_data); 5 | } 6 | 7 | /* 8 | * Disassembly according to capstone: 9 | * add byte ptr [rip - 1], 0x30 10 | * jmp 0x1000000 11 | */ 12 | #define BINARY "\x80\x05\xff\xff\xff\xff\x30\xeb\xf7\x30" 13 | #define MEMORY_SIZE 2 * 1024 * 1024 14 | #define STARTING_ADDRESS 0x1000000 15 | 16 | int main(int argc, char **argv, char **envp) { 17 | uc_engine *uc; 18 | if (uc_open(UC_ARCH_X86, UC_MODE_64, &uc)) { 19 | printf("uc_open(…) failed\n"); 20 | return 1; 21 | } 22 | uc_mem_map(uc, STARTING_ADDRESS, MEMORY_SIZE, UC_PROT_ALL); 23 | if (uc_mem_write(uc, STARTING_ADDRESS, BINARY, sizeof(BINARY) - 1)) { 24 | printf("uc_mem_write(…) failed\n"); 25 | return 1; 26 | } 27 | uc_hook hook; 28 | uc_hook_add(uc, &hook, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); 29 | printf("uc_emu_start(…)\n"); 30 | uc_emu_start(uc, STARTING_ADDRESS, STARTING_ADDRESS + sizeof(BINARY) - 1, 0, 20); 31 | printf("done\n"); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/regress/invalid_read_in_tb_flush_x86_64.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define HARDWARE_ARCHITECTURE UC_ARCH_X86 4 | #define HARDWARE_MODE UC_MODE_64 5 | 6 | #define MEMORY_STARTING_ADDRESS 0x1000000 7 | #define MEMORY_SIZE 2 * 1024 * 1024 8 | #define MEMORY_PERMISSIONS UC_PROT_READ 9 | 10 | #define BINARY_CODE "\x90" 11 | 12 | int main(int argc, char **argv, char **envp) { 13 | uc_engine *uc; 14 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 15 | printf("uc_open(…) failed\n"); 16 | return 1; 17 | } 18 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 19 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 20 | printf("uc_mem_write(…) failed\n"); 21 | return 1; 22 | } 23 | printf("uc_emu_start(…)\n"); 24 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 20); 25 | printf("done\n"); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /tests/regress/invalid_write_in_cpu_tb_exec_x86_64.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * Disassembly according to capstone: 5 | * mulx rsp, rsp, rdx 6 | */ 7 | #define BINARY "\xc4\xe2\xdb\xf6\xe2" 8 | #define MEMORY_SIZE 2 * 1024 * 1024 9 | #define STARTING_ADDRESS 0x1000000 10 | 11 | int main(int argc, char **argv, char **envp) { 12 | uc_engine *uc; 13 | if (uc_open(UC_ARCH_X86, UC_MODE_64, &uc)) { 14 | printf("uc_open(…) failed\n"); 15 | return 1; 16 | } 17 | uc_mem_map(uc, STARTING_ADDRESS, MEMORY_SIZE, UC_PROT_ALL); 18 | if (uc_mem_write(uc, STARTING_ADDRESS, BINARY, sizeof(BINARY) - 1)) { 19 | printf("uc_mem_write(…) failed\n"); 20 | return 1; 21 | } 22 | printf("uc_emu_start(…)\n"); 23 | uc_emu_start(uc, STARTING_ADDRESS, STARTING_ADDRESS + sizeof(BINARY) - 1, 0, 20); 24 | printf("done\n"); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /tests/regress/jmp_ebx_hang.py: -------------------------------------------------------------------------------- 1 | """ See https://github.com/unicorn-engine/unicorn/issues/82 """ 2 | 3 | import regress 4 | from unicorn import * 5 | from unicorn.x86_const import * 6 | 7 | CODE_ADDR = 0x10101000 8 | CODE = b'\xff\xe3' # jmp ebx 9 | 10 | 11 | class JumEbxHang(regress.RegressTest): 12 | def runTest(self): 13 | mu = Uc(UC_ARCH_X86, UC_MODE_32) 14 | 15 | mu.mem_map(CODE_ADDR, 1024 * 4) 16 | mu.mem_write(CODE_ADDR, CODE) 17 | # If EBX is zero then an exception is raised, as expected 18 | mu.reg_write(UC_X86_REG_EBX, 0x0) 19 | 20 | regress.logger.debug(">>> jmp ebx (ebx = 0)") 21 | with self.assertRaises(UcError) as m: 22 | mu.emu_start(CODE_ADDR, CODE_ADDR + 2, count=1) 23 | 24 | self.assertEqual(m.exception.errno, UC_ERR_FETCH_UNMAPPED) 25 | 26 | regress.logger.debug(">>> jmp ebx (ebx = 0xaa96a47f)") 27 | mu = Uc(UC_ARCH_X86, UC_MODE_32) 28 | mu.mem_map(CODE_ADDR, 1024 * 4) 29 | # If we write this address to EBX then the emulator hangs on emu_start 30 | mu.reg_write(UC_X86_REG_EBX, 0xaa96a47f) 31 | mu.mem_write(CODE_ADDR, CODE) 32 | 33 | with self.assertRaises(UcError) as m: 34 | mu.emu_start(CODE_ADDR, CODE_ADDR + 2, count=1) 35 | 36 | self.assertEqual(m.exception.errno, UC_ERR_FETCH_UNMAPPED) 37 | 38 | 39 | if __name__ == '__main__': 40 | regress.main() 41 | -------------------------------------------------------------------------------- /tests/regress/map_crash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define UC_BUG_WRITE_SIZE 13000 7 | #define UC_BUG_WRITE_ADDR 0x1000 8 | 9 | int main(void) 10 | { 11 | int size; 12 | uint8_t *buf; 13 | uc_engine *uc; 14 | uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uc); 15 | if (err) { 16 | fprintf (stderr, "Cannot initialize unicorn\n"); 17 | return 1; 18 | } 19 | size = UC_BUG_WRITE_SIZE; 20 | buf = malloc (size); 21 | if (!buf) { 22 | fprintf (stderr, "Cannot allocate\n"); 23 | return 1; 24 | } 25 | memset (buf, 0, size); 26 | if (!uc_mem_map (uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) { 27 | uc_mem_write (uc, UC_BUG_WRITE_ADDR, buf, size); 28 | } 29 | uc_close(uc); 30 | free(buf); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tests/regress/map_write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define ADDR 0x00400000 6 | #define SIZE 1024*64 7 | #define OVERFLOW 1 8 | 9 | int main(void) 10 | { 11 | uc_engine *uc = NULL; 12 | uint8_t *buf = NULL, *buf2 = NULL; 13 | int i; 14 | uc_err err; 15 | 16 | err = uc_open (UC_ARCH_X86, UC_MODE_64, &uc); 17 | if (err) { 18 | printf ("uc_open %d\n", err); 19 | goto exit; 20 | } 21 | err = uc_mem_map (uc, ADDR, SIZE, UC_PROT_ALL); 22 | if (err) { 23 | printf ("uc_mem_map %d\n", err); 24 | goto exit; 25 | } 26 | buf = calloc (SIZE*2, 1); 27 | buf2 = calloc (SIZE, 1); 28 | for (i=0;i= 0x80000000, you need to enable the virtual TLB 20 | # See https://github.com/unicorn-engine/unicorn/pull/2111 for more details 21 | uc.ctl_set_tlb_mode(UC_TLB_VIRTUAL) 22 | 23 | ADDRESS = 0x0120003000 24 | 25 | uc.reg_write(UC_MIPS_REG_PC, ADDRESS) 26 | uc.reg_write(UC_MIPS_REG_GP, 0x123) 27 | uc.reg_write(UC_MIPS_REG_RA, 0x456) 28 | 29 | uc.mem_map(ADDRESS, 4 * 1024) 30 | uc.mem_write(ADDRESS, code) 31 | 32 | # This will raise an exception if MIPS64 fails 33 | uc.emu_start(ADDRESS, 0, count=2) 34 | 35 | self.assertEqual(uc.reg_read(UC_MIPS_REG_PC),0x0120003000 + 8) 36 | 37 | 38 | if __name__ == '__main__': 39 | regress.main() 40 | -------------------------------------------------------------------------------- /tests/regress/mips_branch_delay.py: -------------------------------------------------------------------------------- 1 | import regress 2 | import sys 3 | import unittest 4 | from capstone import * 5 | from unicorn import * 6 | 7 | CODE = ( 8 | b'\x00\x00\xa4\x12' # beq $a0, $s5, 0x4008a0 9 | b'\x6a\x00\x82\x28' # slti $v0, $a0, 0x6a 10 | b'\x00\x00\x00\x00' # nop 11 | ) 12 | 13 | BASE = 0x400000 14 | 15 | 16 | class MipsBranchDelay(regress.RegressTest): 17 | 18 | @unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher") 19 | def runTest(self): 20 | md = Cs(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_LITTLE_ENDIAN) 21 | 22 | def disas(code, addr): 23 | for insn in md.disasm(code, addr): 24 | regress.logger.debug('%#x: %-8s %s', insn.address, insn.mnemonic, insn.op_str) 25 | 26 | def hook_code(uc, addr, size, _): 27 | disas(uc.mem_read(addr, size), addr) 28 | 29 | regress.logger.debug('Input instructions:') 30 | disas(CODE, BASE) 31 | 32 | regress.logger.debug('Hooked instructions:') 33 | 34 | uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN) 35 | uc.hook_add(UC_HOOK_CODE, hook_code) 36 | uc.mem_map(BASE, 0x1000) 37 | uc.mem_write(BASE, CODE) 38 | 39 | self.assertEqual(None, uc.emu_start(BASE, BASE + len(CODE))) 40 | 41 | 42 | if __name__ == '__main__': 43 | regress.main() 44 | -------------------------------------------------------------------------------- /tests/regress/mips_cp1.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.mips_const import * 4 | 5 | CODE = b'\x44\x43\xF8\x00' # cfc1 $v1, FCSR 6 | BASE = 0x416CB0 7 | 8 | 9 | class TestMipsCp1(regress.RegressTest): 10 | def runTest(self): 11 | uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN) 12 | 13 | uc.mem_map(BASE & ~(0x1000 - 1), 0x1000) 14 | uc.mem_write(BASE, CODE) 15 | 16 | # set a wrong value in v1 17 | uc.reg_write(UC_MIPS_REG_V1, 0x0badc0de) 18 | 19 | uc.emu_start(BASE, BASE + len(CODE)) 20 | 21 | # default FCSR value should be 0 22 | self.assertEqual(0x0000, uc.reg_read(UC_MIPS_REG_V1)) 23 | 24 | 25 | if __name__ == '__main__': 26 | regress.main() 27 | -------------------------------------------------------------------------------- /tests/regress/mips_invalid_read_of_size_4_when_tracing.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { 4 | printf("tracing\n"); 5 | } 6 | 7 | #define HARDWARE_ARCHITECTURE UC_ARCH_MIPS 8 | #define HARDWARE_MODE UC_MODE_MIPS32 9 | 10 | #define MEMORY_STARTING_ADDRESS 0x1000000 11 | #define MEMORY_SIZE 2 * 1024 * 1024 12 | #define MEMORY_PERMISSIONS UC_PROT_ALL 13 | 14 | #define BINARY_CODE "00000000000000000000000000AA" 15 | 16 | int main(int argc, char **argv, char **envp) { 17 | uc_engine *uc; 18 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 19 | printf("uc_open(…) failed\n"); 20 | return 1; 21 | } 22 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 23 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 24 | printf("uc_mem_write(…) failed\n"); 25 | return 1; 26 | } 27 | uc_hook trace; 28 | uc_hook_add(uc, &trace, UC_HOOK_CODE, hook_code, NULL, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + 1); 29 | printf("uc_emu_start(…)\n"); 30 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 0); 31 | printf("done\n"); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/regress/mips_kernel_mmu.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.mips_const import * 4 | 5 | CODE = b'\x34\x21\x34\x56' # ori $at, $at, 0x3456 6 | BASE = 0x10000000 7 | 8 | 9 | class MipsKernelMMU(regress.RegressTest): 10 | def test_syscall(self): 11 | uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN) 12 | 13 | uc.mem_map(BASE, 0x1000) 14 | uc.mem_write(BASE, CODE) 15 | uc.reg_write(UC_MIPS_REG_AT, 0) 16 | 17 | uc.emu_start(BASE, BASE + len(CODE)) 18 | 19 | self.assertEqual(0x3456, uc.reg_read(UC_MIPS_REG_AT)) 20 | 21 | 22 | if __name__ == '__main__': 23 | regress.main() 24 | -------------------------------------------------------------------------------- /tests/regress/mips_syscall_pc.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.mips_const import * 4 | 5 | CODE = b'\x0c\x00\x00\x00' # syscall 6 | BASE = 0x40000 7 | 8 | 9 | def intr_hook(uc, intno, data): 10 | regress.logger.debug('interrupt=%d, v0=%d, pc=%#010x', intno, uc.reg_read(UC_MIPS_REG_V0), 11 | uc.reg_read(UC_MIPS_REG_PC)) 12 | 13 | 14 | class MipsSyscall(regress.RegressTest): 15 | def test(self): 16 | uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN) 17 | 18 | uc.mem_map(BASE, 0x1000) 19 | uc.mem_write(BASE, CODE) 20 | uc.reg_write(UC_MIPS_REG_V0, 100) 21 | uc.hook_add(UC_HOOK_INTR, intr_hook) 22 | 23 | uc.emu_start(BASE, BASE + len(CODE)) 24 | 25 | self.assertEqual(0x40004, uc.reg_read(UC_MIPS_REG_PC)) 26 | 27 | 28 | if __name__ == '__main__': 29 | regress.main() 30 | -------------------------------------------------------------------------------- /tests/regress/mov_gs_eax.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | CODE = ( 6 | b'\x8e\xe8' # mov gs, eax 7 | b'\xb8\x01\x00\x00\x00' # mov eax, 1 8 | ) 9 | 10 | BASE = 0x1000 11 | 12 | 13 | class MovGsEax(regress.RegressTest): 14 | 15 | def runTest(self): 16 | uc = Uc(UC_ARCH_X86, UC_MODE_32) 17 | 18 | uc.mem_map(BASE, 0x1000) 19 | 20 | uc.mem_write(BASE, CODE) 21 | uc.reg_write(UC_X86_REG_EAX, 0xFFFFFFFF) 22 | 23 | with self.assertRaises(UcError) as ex_ctx: 24 | uc.emu_start(BASE, BASE + len(CODE)) 25 | 26 | self.assertEqual(UC_ERR_EXCEPTION, ex_ctx.exception.errno) 27 | 28 | 29 | if __name__ == '__main__': 30 | regress.main() 31 | -------------------------------------------------------------------------------- /tests/regress/movsd.py: -------------------------------------------------------------------------------- 1 | # By Ryan Hileman, issue #3 2 | 3 | import regress 4 | import sys 5 | import unittest 6 | from capstone import Cs, CS_ARCH_X86, CS_MODE_64 7 | from unicorn import * 8 | 9 | CODE = b'\xf2\x0f\x10\x05\xaa\x12\x00\x00' 10 | 11 | 12 | def dis(md, mem, addr): 13 | return '\n'.join(('%-16s %s' % (insn.mnemonic, insn.op_str) for insn in md.disasm(mem, addr))) 14 | 15 | 16 | def hook_code(uc, addr, size, md): 17 | mem = uc.mem_read(addr, size) 18 | 19 | regress.logger.debug('instruction size: %d', size) 20 | regress.logger.debug('instruction: %s %s', mem, dis(md, mem, addr)) 21 | regress.logger.debug('reference: %s %s', CODE, dis(md, CODE, addr)) 22 | 23 | 24 | class Movsd(regress.RegressTest): 25 | 26 | @unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher") 27 | def runTest(self): 28 | addr = 0x400000 29 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 30 | md = Cs(CS_ARCH_X86, CS_MODE_64) 31 | 32 | mu.hook_add(UC_HOOK_CODE, hook_code, md) 33 | mu.mem_map(addr, 8 * 1024 * 1024) 34 | mu.mem_write(addr, CODE) 35 | mu.emu_start(addr, addr + len(CODE)) 36 | 37 | 38 | if __name__ == '__main__': 39 | regress.main() 40 | -------------------------------------------------------------------------------- /tests/regress/osx_qemu_thread_create_crash.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | 4 | 5 | # OS X: OK with 2047 iterations. 6 | # OS X: Crashes at 2048:th iteration ("qemu: qemu_thread_create: Resource temporarily unavailable"). 7 | # Linux: No crashes observed. 8 | 9 | class ThreadCreateCrash(regress.RegressTest): 10 | def test(self): 11 | for _ in range(2048): 12 | Uc(UC_ARCH_X86, UC_MODE_64) 13 | 14 | 15 | if __name__ == '__main__': 16 | regress.main() 17 | -------------------------------------------------------------------------------- /tests/regress/potential_memory_leak.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import regress 3 | import sys 4 | import unittest 5 | from unicorn import * 6 | 7 | try: 8 | # Only available on Unix: https://docs.python.org/3/library/resource.html 9 | import resource 10 | except: 11 | pass 12 | 13 | ITERATIONS = 10000 14 | 15 | 16 | class MemoryLeak(regress.RegressTest): 17 | 18 | @unittest.skipIf(sys.platform == 'win32', reason='Test for Unix only') 19 | def test(self): 20 | if platform.system() == "Darwin": 21 | rusage_multiplier = 1 22 | elif platform.system() == "Linux": 23 | rusage_multiplier = 1024 24 | else: 25 | # resource.getrusage(...) is platform dependent. Only tested under OS X and Linux. 26 | self.skipTest('not OSx neither Linux') 27 | 28 | max_rss_before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss * rusage_multiplier 29 | 30 | for _ in range(ITERATIONS): 31 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 32 | mu.mem_map(0, 0x1000) 33 | mu.emu_start(0, 0) 34 | 35 | max_rss_after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss * rusage_multiplier 36 | rss_increase_per_iteration = (max_rss_after - max_rss_before) / ITERATIONS 37 | 38 | self.assertLess(rss_increase_per_iteration, 8000.0) 39 | 40 | 41 | if __name__ == '__main__': 42 | regress.main() 43 | -------------------------------------------------------------------------------- /tests/regress/pshufb.py: -------------------------------------------------------------------------------- 1 | # By Ryan Hileman, issue #91 2 | 3 | import regress 4 | from unicorn import * 5 | from unicorn.x86_const import * 6 | 7 | 8 | class Pshufb(regress.RegressTest): 9 | 10 | def runTest(self): 11 | uc = Uc(UC_ARCH_X86, UC_MODE_64) 12 | uc.ctl_set_cpu_model(UC_CPU_X86_HASWELL) 13 | 14 | uc.mem_map(0x2000, 0x1000) 15 | 16 | uc.mem_write(0x2000, b'\x66\x0f\x38\x00\xc1') # pshufb xmm0, xmm1 17 | 18 | # Invalid instruction -> test failed 19 | uc.emu_start(0x2000, 0x2005) 20 | 21 | 22 | if __name__ == '__main__': 23 | regress.main() 24 | -------------------------------------------------------------------------------- /tests/regress/reg_write_sign_extension.py: -------------------------------------------------------------------------------- 1 | """ See https://github.com/unicorn-engine/unicorn/issues/98 """ 2 | 3 | import regress 4 | from unicorn import * 5 | 6 | ADDR = 0xffaabbcc 7 | 8 | 9 | class RegWriteSignExt(regress.RegressTest): 10 | 11 | def hook_mem_invalid(self, mu, access, address, size, value, user_data): 12 | regress.logger.debug(">>> Access type: %u, expected value: 0x%x, actual value: 0x%x", access, ADDR, address) 13 | 14 | self.assertEqual(address, ADDR) 15 | 16 | mu.mem_map(address & 0xfffff000, 4 * 1024) 17 | mu.mem_write(address, b'\xcc') 18 | 19 | return True 20 | 21 | def runTest(self): 22 | mu = Uc(UC_ARCH_X86, UC_MODE_32) 23 | mu.reg_write(x86_const.UC_X86_REG_EBX, ADDR) 24 | 25 | mu.mem_map(0x10000000, 1024 * 4) 26 | # jmp ebx 27 | mu.mem_write(0x10000000, b'\xff\xe3') 28 | 29 | mu.hook_add(UC_HOOK_MEM_FETCH_UNMAPPED | UC_HOOK_MEM_FETCH_PROT, self.hook_mem_invalid) 30 | mu.emu_start(0x10000000, 0x10000000 + 2, count=1) 31 | 32 | 33 | if __name__ == '__main__': 34 | regress.main() 35 | -------------------------------------------------------------------------------- /tests/regress/regress.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import unittest 4 | 5 | 6 | class RegressTest(unittest.TestCase): 7 | """ Regress test case dummy class. """ 8 | 9 | 10 | def main(): 11 | unittest.main() 12 | 13 | 14 | def __setup_logger(name): 15 | """ Set up a unified logger for all tests. """ 16 | 17 | instance = logging.getLogger(name) 18 | instance.propagate = False 19 | 20 | if not instance.handlers: 21 | handler = logging.StreamHandler() 22 | formatter = logging.Formatter('[%(levelname)s] %(message)s') 23 | handler.setFormatter(formatter) 24 | instance.addHandler(handler) 25 | 26 | return instance 27 | 28 | 29 | logger = __setup_logger('UnicornRegress') 30 | logger.setLevel((os.getenv('REGRESS_LOG_LEVEL') or 'INFO').upper()) 31 | -------------------------------------------------------------------------------- /tests/regress/regress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | ./map_crash 5 | ./map_write 6 | ./sigill 7 | ./sigill2 8 | ./block_test 9 | ./ro_mem_test 10 | ./nr_mem_test 11 | ./timeout_segfault 12 | ./rep_movsb 13 | ./mem_unmap 14 | ./mem_protect 15 | ./mem_exec 16 | ./mem_map_large 17 | ./00opcode_uc_crash 18 | ./eflags_noset 19 | ./eflags_nosync 20 | ./mips_kseg0_1 21 | ./mem_double_unmap 22 | 23 | -------------------------------------------------------------------------------- /tests/regress/rep_hook.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | PAGE_SIZE = 0x1000 6 | 7 | CODE = b'\xf3\xaa' # rep stosb 8 | BASE = 0x00000000 9 | 10 | 11 | class TestRep(regress.RegressTest): 12 | 13 | def runTest(self): 14 | mu = Uc(UC_ARCH_X86, UC_MODE_32) 15 | 16 | mu.mem_map(BASE, PAGE_SIZE) 17 | mu.mem_write(BASE, CODE) 18 | 19 | mu.reg_write(UC_X86_REG_ECX, 8) 20 | mu.reg_write(UC_X86_REG_ESI, 0x10) 21 | mu.reg_write(UC_X86_REG_EDI, 0x20) 22 | 23 | def __hook_code(uc, addr, size, ud): 24 | regress.logger.debug('iterations remaining: %d', uc.reg_read(UC_X86_REG_ECX)) 25 | 26 | mu.hook_add(UC_HOOK_CODE, __hook_code) 27 | 28 | mu.emu_start(BASE, len(CODE)) 29 | 30 | self.assertEqual(0, mu.reg_read(UC_X86_REG_ECX)) 31 | 32 | 33 | if __name__ == '__main__': 34 | regress.main() 35 | -------------------------------------------------------------------------------- /tests/regress/segfault_on_stop.py: -------------------------------------------------------------------------------- 1 | import regress 2 | import unicorn 3 | 4 | 5 | class SegfaultOnStop(regress.RegressTest): 6 | def test(self): 7 | unicorn.Uc(unicorn.UC_ARCH_X86, unicorn.UC_MODE_64).emu_stop() 8 | self.assertTrue(True, "If not reached, then we have a crashing bug.") 9 | 10 | 11 | if __name__ == '__main__': 12 | regress.main() 13 | -------------------------------------------------------------------------------- /tests/regress/sigill.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define UC_BUG_WRITE_SIZE 128 7 | #define UC_BUG_WRITE_ADDR 0x1000 // fix this by change this to 0x2000 8 | 9 | int got_sigill = 0; 10 | 11 | void _interrupt(uc_engine *uc, uint32_t intno, void *user_data) 12 | { 13 | if (intno == 6) { 14 | uc_emu_stop(uc); 15 | got_sigill = 1; 16 | } 17 | } 18 | 19 | int main(void) 20 | { 21 | int size; 22 | uint8_t *buf; 23 | uc_engine *uc; 24 | uc_hook uh_trap; 25 | uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uc); 26 | if (err) { 27 | fprintf (stderr, "Cannot initialize unicorn\n"); 28 | return 1; 29 | } 30 | size = UC_BUG_WRITE_SIZE; 31 | buf = malloc (size); 32 | if (!buf) { 33 | fprintf (stderr, "Cannot allocate\n"); 34 | return 1; 35 | } 36 | memset (buf, 0, size); 37 | if (!uc_mem_map(uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) { 38 | uc_mem_write(uc, UC_BUG_WRITE_ADDR, 39 | (const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8); 40 | } 41 | uc_hook_add(uc, &uh_trap, UC_HOOK_INTR, _interrupt, NULL, 1, 0); 42 | uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1); 43 | uc_close(uc); 44 | free(buf); 45 | printf ("Correct: %s\n", got_sigill? "YES": "NO"); 46 | return got_sigill? 0: 1; 47 | } 48 | -------------------------------------------------------------------------------- /tests/regress/sigill2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define UC_BUG_WRITE_SIZE 128 7 | #define UC_BUG_WRITE_ADDR 0x2000 8 | 9 | int main(void) 10 | { 11 | int size; 12 | uc_engine *uc; 13 | 14 | uc_err err = uc_open (UC_ARCH_X86, UC_MODE_64, &uc); 15 | if (err) { 16 | fprintf (stderr, "Cannot initialize unicorn\n"); 17 | return 1; 18 | } 19 | size = UC_BUG_WRITE_SIZE; 20 | if (!uc_mem_map (uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) { 21 | uc_mem_write (uc, UC_BUG_WRITE_ADDR, 22 | (const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8); 23 | } 24 | err = uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1); 25 | uc_close(uc); 26 | printf ("Error = %u (%s)\n", err, uc_strerror(err)); 27 | return err? -1: 0; 28 | } 29 | -------------------------------------------------------------------------------- /tests/regress/sparc64.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.sparc_const import * 4 | 5 | CODE = ( 6 | b"\xb0\x06\x20\x01" # 0: b0 06 20 01 inc %i0 7 | b"\xb2\x06\x60\x01" # 4: b2 06 60 01 inc %i1 8 | ) 9 | 10 | BASE = 0x00000000 11 | 12 | 13 | class TestSparc64RegRead(regress.RegressTest): 14 | def runTest(self): 15 | uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC64 | UC_MODE_BIG_ENDIAN) 16 | 17 | uc.mem_map(BASE, 0x1000 ** 2) 18 | uc.mem_write(BASE, CODE) 19 | 20 | uc.reg_write(UC_SPARC_REG_SP, 100) 21 | 22 | uc.emu_start(BASE, BASE + len(CODE), count=2) 23 | 24 | regress.logger.debug('sp = %#x', uc.reg_read(UC_SPARC_REG_SP)) 25 | regress.logger.debug('i0 = %#x', uc.reg_read(UC_SPARC_REG_I0)) 26 | regress.logger.debug('i1 = %#x', uc.reg_read(UC_SPARC_REG_I1)) 27 | 28 | 29 | if __name__ == '__main__': 30 | regress.main() 31 | -------------------------------------------------------------------------------- /tests/regress/sparc_jump_to_zero.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define HARDWARE_ARCHITECTURE UC_ARCH_SPARC 4 | #define HARDWARE_MODE UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN 5 | 6 | #define MEMORY_STARTING_ADDRESS 0x1000000 7 | #define MEMORY_SIZE 2 * 1024 * 1024 8 | #define MEMORY_PERMISSIONS UC_PROT_ALL 9 | 10 | #define BINARY_CODE "\x02\xbc\x00\x00" 11 | 12 | int main(int argc, char **argv, char **envp) { 13 | uc_engine *uc; 14 | if (uc_open(HARDWARE_ARCHITECTURE, HARDWARE_MODE, &uc)) { 15 | printf("uc_open(…) failed\n"); 16 | return 1; 17 | } 18 | uc_mem_map(uc, MEMORY_STARTING_ADDRESS, MEMORY_SIZE, MEMORY_PERMISSIONS); 19 | if (uc_mem_write(uc, MEMORY_STARTING_ADDRESS, BINARY_CODE, sizeof(BINARY_CODE) - 1)) { 20 | printf("uc_mem_write(…) failed\n"); 21 | return 1; 22 | } 23 | printf("uc_emu_start(…)\n"); 24 | uc_emu_start(uc, MEMORY_STARTING_ADDRESS, MEMORY_STARTING_ADDRESS + sizeof(BINARY_CODE) - 1, 0, 20); 25 | printf("done\n"); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /tests/regress/test_old_ctl.py: -------------------------------------------------------------------------------- 1 | import regress 2 | import sys 3 | import unittest 4 | from unicorn import * 5 | from unicorn.x86_const import * 6 | 7 | 8 | # Very basic testing to ensure the old api exists 9 | @unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher") 10 | class OldCtl(regress.RegressTest): 11 | def runTest(self): 12 | mu = Uc(UC_ARCH_X86, UC_MODE_32) 13 | mu.ctl_tlb_mode(UC_TLB_CPU) 14 | mu.ctl_set_tlb_mode(UC_TLB_VIRTUAL) 15 | 16 | 17 | if __name__ == '__main__': 18 | regress.main() 19 | -------------------------------------------------------------------------------- /tests/regress/write_before_map.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | X86_CODE64 = b"\x90" # NOP 6 | 7 | 8 | class WriteBeforeMap(regress.RegressTest): 9 | def runTest(self): 10 | # Initialize emulator in X86-32bit mode 11 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 12 | 13 | # memory address where emulation starts 14 | ADDRESS = 0x1000000 15 | 16 | # write machine code to be emulated to memory 17 | with self.assertRaises(UcError) as raisedEx: 18 | mu.mem_write(ADDRESS, X86_CODE64) 19 | 20 | self.assertEqual(UC_ERR_WRITE_UNMAPPED, raisedEx.exception.errno) 21 | 22 | 23 | if __name__ == '__main__': 24 | regress.main() 25 | -------------------------------------------------------------------------------- /tests/regress/wrong_rip_arm.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.arm_const import * 4 | 5 | CODE = ( 6 | b'\x48\x31' # adds r1, #0x48 7 | b'\xff\x57' # ldrsb r7, [r7, r7] 8 | b'\x57\x5e' # ldrsh r7, [r2, r1] 9 | b'\x5a\x48' # ldr r0, [pc, #0x168] 10 | b'\xbf\x2f' # cmp r7, #0xbf 11 | b'\x2f\x62' # str r7, [r5, #0x20] 12 | b'\x69\x6e' # ldr r1, [r5, #0x64] 13 | b'\x2f\x73' # strb r7, [r5, #0xc] 14 | b'\x68\x48' # ldr r0, [pc, #0x1a0] 15 | 16 | b'\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05' # data? 17 | ) 18 | 19 | BASE = 0x00000000 20 | 21 | 22 | class WrongRIPArm(regress.RegressTest): 23 | 24 | def runTest(self): 25 | mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB) 26 | 27 | mu.mem_map(BASE, 2 * 1024 * 1024) 28 | # write machine code to be emulated to memory 29 | mu.mem_write(BASE, CODE) 30 | mu.reg_write(UC_ARM_REG_R13, 1 * 1024 * 1024) 31 | 32 | # emu for maximum 1 instruction. 33 | mu.emu_start(BASE | 0b1, BASE + len(CODE), count=1) 34 | 35 | self.assertEqual(0x48, mu.reg_read(UC_ARM_REG_R1)) 36 | self.assertEqual(0x2, mu.reg_read(UC_ARM_REG_R15)) 37 | 38 | 39 | if __name__ == '__main__': 40 | regress.main() 41 | -------------------------------------------------------------------------------- /tests/regress/wrong_sp_arm.py: -------------------------------------------------------------------------------- 1 | # By Ryan Hileman, issue #16 2 | 3 | import regress 4 | from unicorn import * 5 | from unicorn.arm_const import * 6 | from unicorn.arm64_const import * 7 | 8 | 9 | class WrongSPArm(regress.RegressTest): 10 | 11 | def test_32(self): 12 | with self.assertRaises(UcError): 13 | uc = Uc(UC_ARCH_ARM, UC_MODE_32) 14 | uc.reg_write(UC_ARM_REG_SP, 4) 15 | 16 | def test_64(self): 17 | uc = Uc(UC_ARCH_ARM64, UC_MODE_ARM) 18 | uc.reg_write(UC_ARM64_REG_SP, 4) 19 | self.assertEqual(0x4, uc.reg_read(UC_ARM64_REG_SP)) 20 | 21 | def test_arm(self): 22 | uc = Uc(UC_ARCH_ARM, UC_MODE_ARM) 23 | uc.reg_write(UC_ARM_REG_SP, 4) 24 | self.assertEqual(0x4, uc.reg_read(UC_ARM_REG_SP)) 25 | 26 | 27 | if __name__ == '__main__': 28 | regress.main() 29 | -------------------------------------------------------------------------------- /tests/regress/x86_16_segfault.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BINARY "\x90" 4 | #define MEMORY_SIZE 4 * 1024 5 | #define STARTING_ADDRESS 100 * 1024 6 | 7 | int main(int argc, char **argv, char **envp) { 8 | uc_engine *uc; 9 | if (uc_open(UC_ARCH_X86, UC_MODE_16, &uc)) { 10 | printf("uc_open(…) failed\n"); 11 | return 1; 12 | } 13 | uc_mem_map(uc, STARTING_ADDRESS, MEMORY_SIZE, UC_PROT_ALL); 14 | if (uc_mem_write(uc, STARTING_ADDRESS, BINARY, sizeof(BINARY) - 1)) { 15 | printf("uc_mem_write(…) failed\n"); 16 | return 1; 17 | } 18 | printf("uc_emu_start(…)\n"); 19 | uc_emu_start(uc, STARTING_ADDRESS, STARTING_ADDRESS + sizeof(BINARY) - 1, 0, 20); 20 | printf("done\n"); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /tests/regress/x86_64_eflags.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | 6 | class WrongEFLAGS(regress.RegressTest): 7 | def test_eflags(self): 8 | # xor r14,r14 9 | CODE = b'M1\xf6' 10 | 11 | uc = Uc(UC_ARCH_X86, UC_MODE_64) 12 | uc.reg_write(UC_X86_REG_RIP, 0x6000b0) 13 | uc.reg_write(UC_X86_REG_EFLAGS, 0x200) 14 | 15 | uc.mem_map(0x600000, 0x1000) 16 | uc.mem_write(0x6000b0, CODE) 17 | uc.emu_start(0x6000b0, 0, count=1) 18 | 19 | # Here's the original execution trace for this on actual hardware. 20 | # 21 | # (gdb) x/i $pc 22 | # => 0x6000b0: xor %r14,%r14 23 | # (gdb) p/x $eflags 24 | # $1 = 0x200 25 | # (gdb) p $eflags 26 | # $2 = [ IF ] 27 | # (gdb) si 28 | # 0x00000000006000b3 in ?? () 29 | # (gdb) p/x $eflags 30 | # $3 = 0x246 31 | # (gdb) p $eflags 32 | # $4 = [ PF ZF IF ] 33 | 34 | self.assertEqual(0x6000b3, uc.reg_read(UC_X86_REG_RIP)) 35 | self.assertEqual(0x246, uc.reg_read(UC_X86_REG_EFLAGS)) 36 | 37 | 38 | if __name__ == '__main__': 39 | regress.main() 40 | -------------------------------------------------------------------------------- /tests/regress/x86_eflags.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | 6 | class WrongEFLAGS2(regress.RegressTest): 7 | def test_eflags(self): 8 | # imul eax, ebx 9 | CODE = b'\x0f\xaf\xc3' 10 | 11 | uc = Uc(UC_ARCH_X86, UC_MODE_32) 12 | 13 | uc.reg_write(UC_X86_REG_EAX, 16) 14 | uc.reg_write(UC_X86_REG_EBX, 1) 15 | uc.reg_write(UC_X86_REG_EFLAGS, 0x292) 16 | 17 | uc.mem_map(0x600000, 0x1000) 18 | uc.mem_write(0x6000b0, CODE) 19 | uc.emu_start(0x6000b0, 0, count=1) 20 | 21 | # Here's the original execution trace for this on actual hardware. 22 | # 23 | # (gdb) x/i $eip 24 | # => 0x804aae5: imul eax,DWORD PTR [ebp-0x8] 25 | # (gdb) p/x $eax 26 | # $2 = 0x10 27 | # (gdb) x/wx $ebp-8 28 | # 0xbaaaad4c: 0x00000001 29 | # (gdb) p/x $eflags 30 | # $3 = 0x292 31 | # (gdb) si 32 | # 0x0804aae9 in ?? () 33 | # (gdb) p/x $eflags 34 | # $4 = 0x202 35 | 36 | self.assertEqual(0x202, uc.reg_read(UC_X86_REG_EFLAGS)) 37 | 38 | 39 | if __name__ == '__main__': 40 | regress.main() 41 | -------------------------------------------------------------------------------- /tests/regress/x86_fldt_fsqrt.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | 4 | CODE = ( 5 | b'\xb8\x00\x00\x00\x02' # mov eax, 0x2000000 6 | b'\xdb\x28' # fldt [eax] 7 | b'\xd9\xfa' # fsqrt 8 | ) 9 | 10 | BASE = 0x1000000 11 | 12 | DATA_ADDR = 0x2000000 13 | DATA = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' 14 | 15 | 16 | class FldtFsqrt(regress.RegressTest): 17 | def test_fldt_fsqrt(self): 18 | uc = Uc(UC_ARCH_X86, UC_MODE_32) 19 | 20 | uc.mem_map(BASE, 0x1000) 21 | uc.mem_write(BASE, CODE) 22 | 23 | uc.mem_map(DATA_ADDR, 0x1000) 24 | uc.mem_write(DATA_ADDR, DATA) 25 | 26 | uc.emu_start(BASE, BASE + len(CODE), 10000, 10) 27 | 28 | 29 | if __name__ == '__main__': 30 | regress.main() 31 | -------------------------------------------------------------------------------- /tests/regress/x86_ld_crash.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | CODE = ( 6 | b'\x8b\x83\xd4\x05\x00\x00' # mov eax, DWORD PTR [ebx+0x5d4] 7 | b'\x8b\x93\x80\x05\x00\x00' # mov edx, DWORD PTR [ebx+0x580] 8 | ) 9 | 10 | BASE = 0x47bb000 11 | PATT1 = b"\xaf\xaf\xaf\xaf" 12 | PATT2 = b"\xbf\xbf\xbf\xbf" 13 | 14 | 15 | class TestReadMem(regress.RegressTest): 16 | def runTest(self): 17 | uc = Uc(UC_ARCH_X86, UC_MODE_32) 18 | 19 | uc.mem_map(BASE, 0x1000) 20 | 21 | uc.mem_write(BASE, CODE) 22 | uc.mem_write(BASE + 0x5d4, PATT1) 23 | uc.mem_write(BASE + 0x580, PATT2) 24 | 25 | uc.reg_write(UC_X86_REG_EBX, BASE) 26 | 27 | uc.emu_start(BASE, BASE + len(CODE)) 28 | 29 | self.assertEqual(PATT1, uc.mem_read(BASE + 0x5d4, 4)) 30 | self.assertEqual(PATT2, uc.mem_read(BASE + 0x580, 4)) 31 | 32 | 33 | if __name__ == '__main__': 34 | regress.main() 35 | -------------------------------------------------------------------------------- /tests/regress/x86_self_modifying.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/tests/regress/x86_self_modifying.elf -------------------------------------------------------------------------------- /tests/regress/x86_self_modifying.py: -------------------------------------------------------------------------------- 1 | import os 2 | import regress 3 | from unicorn import * 4 | from unicorn.x86_const import * 5 | 6 | # The file we're loading is a full assembled ELF. 7 | # Source for it, along with assembly instructions, are in x86_self_modifying.s 8 | filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'x86_self_modifying.elf') 9 | 10 | CODE_ADDR = 0x08048000 11 | STACK_ADDR = 0x2000000 12 | with open(filename, 'rb') as f: 13 | CODE = f.read() 14 | CODE_SIZE = len(CODE) + (0x1000 - len(CODE) % 0x1000) 15 | STACK_SIZE = 0x8000 16 | 17 | ENTRY_POINT = 0x8048074 18 | 19 | 20 | def hook_intr(uc, intno, data): 21 | uc.emu_stop() 22 | 23 | 24 | class SelfModifying(regress.RegressTest): 25 | def test_self_modifying(self): 26 | uc = Uc(UC_ARCH_X86, UC_MODE_32) 27 | 28 | uc.mem_map(CODE_ADDR, CODE_SIZE, 5) 29 | uc.mem_map(STACK_ADDR, STACK_SIZE, 7) 30 | uc.mem_write(CODE_ADDR, CODE) 31 | uc.reg_write(UC_X86_REG_ESP, STACK_ADDR + STACK_SIZE) 32 | 33 | uc.hook_add(UC_HOOK_INTR, hook_intr) 34 | 35 | uc.emu_start(ENTRY_POINT, -1) 36 | 37 | retcode = uc.reg_read(UC_X86_REG_EBX) 38 | self.assertEqual(retcode, 65) 39 | 40 | 41 | if __name__ == '__main__': 42 | regress.main() 43 | -------------------------------------------------------------------------------- /tests/regress/x86_self_modifying.s: -------------------------------------------------------------------------------- 1 | # Assembly instructions (tested on ubuntu 16.04 x86_64): 2 | # $ as --32 x86_self_modifying.s -o x86_self_modifying.o 3 | # $ ld -melf_i386 -z execstack x86_self_modifying.o -o x86_self_modifying.elf 4 | 5 | # Test that it works. return code should be 65 6 | # $ ./x86_self_modifying.elf 7 | # $ echo $? 8 | # 65 9 | 10 | # Fix the entry point address in x86_self_modifying.py 11 | # $ readelf -h x86_self_modifying.elf | grep Entry 12 | # Entry point address: 0x8048074 13 | 14 | 15 | .intel_syntax noprefix 16 | 17 | .global _start 18 | _start: 19 | mov ebp, esp 20 | sub ebp, 0x4000 21 | mov edx, ebp 22 | 23 | lea esi, [self_modifying] 24 | mov edi, ebp 25 | mov ecx, 0x2d 26 | call memcpy 27 | add ebp, 0x2d 28 | xor ebx, ebx 29 | call edx 30 | 31 | mov eax, 1 32 | int 0x80 33 | 34 | memcpy: 35 | cmp ecx, 0 36 | je _end 37 | dec ecx 38 | mov al, byte ptr [esi+ecx] 39 | mov byte ptr [edi+ecx], al 40 | jmp memcpy 41 | 42 | _end: 43 | ret 44 | 45 | self_modifying: 46 | inc ebx 47 | call $+5 48 | pop esi 49 | dec byte ptr [esi+11] 50 | xor edx, edx 51 | sub esi, 6 52 | _loop_start: 53 | cmp edx, 5 54 | jz _loop_end 55 | 56 | mov edi, ebp 57 | mov ecx, 0x2d 58 | lea eax, [memcpy] 59 | call eax 60 | inc edx 61 | add ebp, 0x2d 62 | mov byte ptr [ebp], 0xc3 63 | jmp _loop_start 64 | 65 | _loop_end: 66 | -------------------------------------------------------------------------------- /tests/regress/x86_set_ip.py: -------------------------------------------------------------------------------- 1 | import regress 2 | from unicorn import * 3 | from unicorn.x86_const import * 4 | 5 | NOPSLED = b"\x90" * 5 6 | 7 | 8 | class TestSetIP(regress.RegressTest): 9 | def runTest(self): 10 | # execution history 11 | history = [] 12 | 13 | def __code_hook(uc, addr, size, ud): 14 | # track execution history 15 | history.append(addr) 16 | 17 | if len(history) == 5: 18 | uc.emu_stop() 19 | else: 20 | uc.reg_write(UC_X86_REG_RIP, 0x1800) 21 | 22 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 23 | 24 | mu.mem_map(0x1000, 0x1000) 25 | mu.mem_write(0x1000, NOPSLED) 26 | mu.mem_write(0x1800, NOPSLED) 27 | 28 | mu.hook_add(UC_HOOK_CODE, __code_hook) 29 | mu.emu_start(0x1000, 0x1800 + 1) 30 | 31 | self.assertListEqual([0x1000] + [0x1800] * 4, history) 32 | 33 | 34 | if __name__ == '__main__': 35 | regress.main() 36 | -------------------------------------------------------------------------------- /tests/regress/x86_vex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unicorn-engine/unicorn/f8c6db950420d2498700245269d0b647697c5666/tests/regress/x86_vex -------------------------------------------------------------------------------- /tests/unit/test_m68k.c: -------------------------------------------------------------------------------- 1 | #include "unicorn_test.h" 2 | 3 | const uint64_t code_start = 0x1000; 4 | const uint64_t code_len = 0x4000; 5 | 6 | static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, 7 | const char *code, uint64_t size, 8 | uc_cpu_m68k cpu_model) 9 | { 10 | OK(uc_open(arch, mode, uc)); 11 | OK(uc_ctl_set_cpu_model(*uc, cpu_model)); 12 | OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); 13 | OK(uc_mem_write(*uc, code_start, code, size)); 14 | } 15 | 16 | static void test_move_to_sr(void) 17 | { 18 | 19 | uc_engine *uc; 20 | char code[] = "\x46\xfc\x27\x00"; // move #$2700,sr 21 | int r_sr; 22 | 23 | uc_common_setup(&uc, UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, code, 24 | sizeof(code) - 1, UC_CPU_M68K_M68000); 25 | OK(uc_reg_read(uc, UC_M68K_REG_SR, &r_sr)); 26 | 27 | r_sr = r_sr | 0x2000; 28 | 29 | OK(uc_reg_write(uc, UC_M68K_REG_SR, &r_sr)); 30 | 31 | OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); 32 | 33 | OK(uc_close(uc)); 34 | } 35 | 36 | TEST_LIST = {{"test_move_to_sr", test_move_to_sr}, {NULL, NULL}}; -------------------------------------------------------------------------------- /tests/unit/test_s390x.c: -------------------------------------------------------------------------------- 1 | #include "unicorn_test.h" 2 | 3 | const uint64_t code_start = 0x1000; 4 | const uint64_t code_len = 0x4000; 5 | 6 | static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, 7 | const char *code, uint64_t size) 8 | { 9 | OK(uc_open(arch, mode, uc)); 10 | OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); 11 | OK(uc_mem_write(*uc, code_start, code, size)); 12 | } 13 | 14 | static void test_s390x_lr(void) 15 | { 16 | char code[] = "\x18\x23"; // lr %r2, %r3 17 | uint64_t r_pc, r_r2, r_r3 = 0x114514; 18 | uc_engine *uc; 19 | 20 | uc_common_setup(&uc, UC_ARCH_S390X, UC_MODE_BIG_ENDIAN, code, 21 | sizeof(code) - 1); 22 | 23 | OK(uc_reg_write(uc, UC_S390X_REG_R3, &r_r3)); 24 | 25 | OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); 26 | 27 | OK(uc_reg_read(uc, UC_S390X_REG_R2, &r_r2)); 28 | OK(uc_reg_read(uc, UC_S390X_REG_PC, &r_pc)); 29 | 30 | TEST_CHECK(r_r2 == 0x114514); 31 | TEST_CHECK(r_pc == code_start + sizeof(code) - 1); 32 | 33 | OK(uc_close(uc)); 34 | } 35 | 36 | TEST_LIST = {{"test_s390x_lr", test_s390x_lr}, {NULL, NULL}}; 37 | -------------------------------------------------------------------------------- /tests/unit/test_sparc.c: -------------------------------------------------------------------------------- 1 | #include "unicorn_test.h" 2 | 3 | const uint64_t code_start = 0x1000; 4 | const uint64_t code_len = 0x4000; 5 | 6 | TEST_LIST = {{NULL, NULL}}; -------------------------------------------------------------------------------- /tests/unit/test_tricore.c: -------------------------------------------------------------------------------- 1 | #include "unicorn_test.h" 2 | 3 | const uint64_t code_start = 0x1000; 4 | const uint64_t code_len = 0x4000; 5 | 6 | TEST_LIST = {{NULL, NULL}}; 7 | --------------------------------------------------------------------------------