From 56f3bdedb42d26bee1532cc01baf5eaf44a9aa23 Mon Sep 17 00:00:00 2001 From: mio Date: Tue, 22 Nov 2022 21:55:02 +0100 Subject: [PATCH 01/26] Update ChangeLog --- ChangeLog | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 224883de..0e7113d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ This file details the changelog of Unicorn Engine. +------------------------------- +[Version 2.0.1.post1]: Nov 22nd, 2022 + +This is a small release to complement the previous 2.0.1 release. + +Fix: + +- Fix the endianness detection in tests. +- Fix the version number in CMakeLists.txt. + ------------------------------- [Version 2.0.1]: Nov 1st, 2022 From 7b8c63dfe650b5d4d2bf684526161971925e6350 Mon Sep 17 00:00:00 2001 From: lazymio Date: Tue, 7 Feb 2023 10:44:36 +0100 Subject: [PATCH 02/26] Exclude enhancement and bug issues --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 04c46b3e..214472cf 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -14,5 +14,5 @@ jobs: days-before-stale: 60 days-before-close: 15 exempt-all-milestones: true - exempt-issue-labels: 'pinned,help wanted' + exempt-issue-labels: 'pinned,help wanted,enhancement,bug' exempt-pr-labels: 'pinned' From 545c9ed24e62d11b91839ba4b453e19d2df24ba5 Mon Sep 17 00:00:00 2001 From: Choongwoo Han Date: Tue, 28 Feb 2023 20:10:38 -0800 Subject: [PATCH 03/26] [dotnet] Add /MT flag for nuget package build --- .github/workflows/Nuget-publishing.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/Nuget-publishing.yml b/.github/workflows/Nuget-publishing.yml index 3a6f0207..e82961cd 100644 --- a/.github/workflows/Nuget-publishing.yml +++ b/.github/workflows/Nuget-publishing.yml @@ -80,6 +80,7 @@ jobs: -B . \ -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ -G "${{ matrix.config.generators }}" \ + -DCMAKE_C_FLAGS="//MT" \ -DCMAKE_INSTALL_PREFIX:PATH=instdir \ -DBUILD_SHARED_LIBS=${{ matrix.config.shared }} cmake --build . --config ${{ matrix.config.build_type }} @@ -107,6 +108,7 @@ jobs: -A "win32" \ -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ -G "${{ matrix.config.generators }}" \ + -DCMAKE_C_FLAGS="//MT" \ -DCMAKE_INSTALL_PREFIX:PATH=instdir \ -DBUILD_SHARED_LIBS=${{ matrix.config.shared }} cmake --build . --config ${{ matrix.config.build_type }} From b7b1a4d6b4eae2ae12e78ec6cd676a69e4ee9392 Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Mon, 6 Mar 2023 15:35:01 +0100 Subject: [PATCH 04/26] difference between stop_request and quit_request quit_request is for internal use. This means the IP register was updated and qemu needs to rebuild the translation blocks. stop_request is set by the user (uc_emu_stop) to indecate that unicorn sould stop emulating. --- include/uc_priv.h | 22 +++++++++++++++++++ qemu/softmmu/cpus.c | 2 +- qemu/target/arm/unicorn_aarch64.c | 2 +- qemu/target/arm/unicorn_arm.c | 2 +- qemu/target/i386/unicorn.c | 4 ++-- qemu/target/m68k/unicorn.c | 2 +- qemu/target/mips/unicorn.c | 2 +- qemu/target/ppc/unicorn.c | 2 +- qemu/target/riscv/unicorn.c | 2 +- qemu/target/s390x/unicorn.c | 2 +- qemu/target/tricore/unicorn.c | 2 +- tests/unit/test_ctl.c | 36 +++++++++++++++++++++++++++++++ uc.c | 13 +---------- 13 files changed, 70 insertions(+), 23 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index 66b6e83e..60a9b486 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -486,6 +486,28 @@ static inline void hooked_regions_check(uc_engine *uc, uint64_t start, length); } +/* + break translation loop: + This is done in two cases: + 1. the user wants to stop the emulation. + 2. the user has set it IP. This requires to restart the internal + CPU emulation and rebuild some translation blocks +*/ +static inline uc_err break_translation_loop(uc_engine *uc) +{ + if (uc->emulation_done) { + return UC_ERR_OK; + } + + // TODO: make this atomic somehow? + if (uc->cpu) { + // exit the current TB + cpu_exit(uc->cpu); + } + + return UC_ERR_OK; +} + #ifdef UNICORN_TRACER #define UC_TRACE_START(loc) trace_start(get_tracer(), loc) #define UC_TRACE_END(loc, fmt, ...) \ diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index f6b242f3..22511ac7 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -96,7 +96,7 @@ static int tcg_cpu_exec(struct uc_struct *uc) r = cpu_exec(uc, cpu); // quit current TB but continue emulating? - if (uc->quit_request) { + if (uc->quit_request && !uc->stop_request) { // reset stop_request uc->stop_request = false; diff --git a/qemu/target/arm/unicorn_aarch64.c b/qemu/target/arm/unicorn_aarch64.c index fec0db68..fa40330f 100644 --- a/qemu/target/arm/unicorn_aarch64.c +++ b/qemu/target/arm/unicorn_aarch64.c @@ -372,7 +372,7 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, if (regid == UC_ARM64_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); } } diff --git a/qemu/target/arm/unicorn_arm.c b/qemu/target/arm/unicorn_arm.c index bb39b348..e706b12b 100644 --- a/qemu/target/arm/unicorn_arm.c +++ b/qemu/target/arm/unicorn_arm.c @@ -515,7 +515,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, if (regid == UC_ARM_REG_R15) { // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); } } diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index 4541044e..3e83b0ba 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -1521,7 +1521,7 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, case UC_X86_REG_IP: // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); break; } @@ -1535,7 +1535,7 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, case UC_X86_REG_IP: // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); break; } #endif diff --git a/qemu/target/m68k/unicorn.c b/qemu/target/m68k/unicorn.c index d748ace7..d0a091fa 100644 --- a/qemu/target/m68k/unicorn.c +++ b/qemu/target/m68k/unicorn.c @@ -117,7 +117,7 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, if (regid == UC_M68K_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); } } diff --git a/qemu/target/mips/unicorn.c b/qemu/target/mips/unicorn.c index bd4d5595..792fb45e 100644 --- a/qemu/target/mips/unicorn.c +++ b/qemu/target/mips/unicorn.c @@ -170,7 +170,7 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, if (regid == UC_MIPS_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); } } diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index b157ce5a..fc8e24f1 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -361,7 +361,7 @@ int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, if (regid == UC_PPC_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); } } diff --git a/qemu/target/riscv/unicorn.c b/qemu/target/riscv/unicorn.c index a440a6bd..8970051e 100644 --- a/qemu/target/riscv/unicorn.c +++ b/qemu/target/riscv/unicorn.c @@ -560,7 +560,7 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, if (regid == UC_RISCV_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); } } diff --git a/qemu/target/s390x/unicorn.c b/qemu/target/s390x/unicorn.c index 469cda7c..6378fe4c 100644 --- a/qemu/target/s390x/unicorn.c +++ b/qemu/target/s390x/unicorn.c @@ -130,7 +130,7 @@ static int s390_reg_write(struct uc_struct *uc, unsigned int *regs, if (regid == UC_S390X_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); } } diff --git a/qemu/target/tricore/unicorn.c b/qemu/target/tricore/unicorn.c index 88e937bb..a3eac632 100644 --- a/qemu/target/tricore/unicorn.c +++ b/qemu/target/tricore/unicorn.c @@ -229,7 +229,7 @@ int tricore_reg_write(struct uc_struct *uc, unsigned int *regs, if (regid == UC_TRICORE_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; - uc_emu_stop(uc); + break_translation_loop(uc); } } diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 05f4c54e..0c1eeabc 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -304,6 +304,41 @@ static void test_uc_hook_cached_uaf(void) #endif } +static void test_uc_emu_stop_set_ip_callback(uc_engine *uc, uint64_t address, uint32_t size, void *userdata) +{ + uint64_t rip = code_start + 0xb; + + if (address == code_start + 0x7) { + printf("stoping\n"); + uc_emu_stop(uc); + uc_reg_write(uc, UC_X86_REG_RIP, &rip); + } +} + +static void test_uc_emu_stop_set_ip(void) +{ + uc_engine *uc; + uc_hook h; + uint64_t rip; + + char code[] = "\x48\x31\xc0" // 0x0 xor rax, rax : rax = 0 + "\x90" // 0x3 nop : + "\x48\xff\xc0" // 0x4 inc rax : rax++ + "\x90" // 0x7 nop : <-- going to stop here + "\x48\xff\xc0" // 0x8 inc rax : rax++ + "\x90" // 0xb nop : + "\x0f\x0b" // 0xc ud2 : <-- will raise UC_ERR_INSN_INVALID, but should not never be reached + "\x90" // 0xe nop : + "\x90"; // 0xf nop : + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1); + OK(uc_hook_add(uc, &h, UC_HOOK_CODE, test_uc_emu_stop_set_ip_callback, NULL, 1, 0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + OK(uc_reg_read(uc, UC_X86_REG_RIP, &rip)); + TEST_CHECK(rip == code_start + 0xb); + OK(uc_close(uc)); +} + TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_page_size", test_uc_ctl_page_size}, {"test_uc_ctl_arch", test_uc_ctl_arch}, @@ -315,4 +350,5 @@ TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_arm_cpu", test_uc_ctl_arm_cpu}, #endif {"test_uc_hook_cached_uaf", test_uc_hook_cached_uaf}, + {"test_uc_emu_stop_set_ip", test_uc_emu_stop_set_ip}, {NULL, NULL}}; diff --git a/uc.c b/uc.c index 829dda95..76c4eb28 100644 --- a/uc.c +++ b/uc.c @@ -907,19 +907,8 @@ UNICORN_EXPORT uc_err uc_emu_stop(uc_engine *uc) { UC_INIT(uc); - - if (uc->emulation_done) { - return UC_ERR_OK; - } - uc->stop_request = true; - // TODO: make this atomic somehow? - if (uc->cpu) { - // exit the current TB - cpu_exit(uc->cpu); - } - - return UC_ERR_OK; + return break_translation_loop(uc); } // return target index where a memory region at the address exists, or could be From b4b6caf57c9e3c01a66a8b1627859c516e4de6a7 Mon Sep 17 00:00:00 2001 From: Choongwoo Han Date: Sat, 11 Mar 2023 08:51:01 -0800 Subject: [PATCH 05/26] [dotnet] Support HookDel with native bindings call --- bindings/dotnet/UnicornEngine/Unicorn.fs | 281 +++++++++++------------ 1 file changed, 138 insertions(+), 143 deletions(-) diff --git a/bindings/dotnet/UnicornEngine/Unicorn.fs b/bindings/dotnet/UnicornEngine/Unicorn.fs index e353bf0c..56a683b0 100644 --- a/bindings/dotnet/UnicornEngine/Unicorn.fs +++ b/bindings/dotnet/UnicornEngine/Unicorn.fs @@ -22,17 +22,16 @@ and SyscallHook = delegate of Unicorn * Object -> unit and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = // hook callback list - let _codeHooks = new List<(CodeHook * Object)>() - let _blockHooks = new List<(BlockHook * Object)>() - let _interruptHooks = new List<(InterruptHook * Object)>() - let _memReadHooks = new List<(MemReadHook * Object)>() - let _memWriteHooks = new List<(MemWriteHook * Object)>() - let _memEventHooks = new Dictionary>() - let _inHooks = new List<(InHook * Object)>() - let _outHooks = new List<(OutHook * Object)>() - let _syscallHooks = new List<(SyscallHook * Object)>() + let _codeHooks = new List<(CodeHook * (UIntPtr * Object * Object))>() + let _blockHooks = new List<(BlockHook * (UIntPtr * Object * Object))>() + let _interruptHooks = new List<(InterruptHook * (UIntPtr * Object * Object))>() + let _memReadHooks = new List<(MemReadHook * (UIntPtr * Object * Object))>() + let _memWriteHooks = new List<(MemWriteHook * (UIntPtr * Object * Object))>() + let _memEventHooks = new Dictionary>() + let _inHooks = new List<(InHook * (UIntPtr * Object * Object))>() + let _outHooks = new List<(OutHook * (UIntPtr * Object * Object))>() + let _syscallHooks = new List<(SyscallHook * (UIntPtr * Object * Object))>() let _disposablePointers = new List() - let _hookInternals = new List(); let _eventMemMap = [ @@ -46,14 +45,25 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = let mutable _eng = [|UIntPtr.Zero|] - let checkResult(errCode: Int32, errMsg: String) = - if errCode <> Common.UC_ERR_OK then raise(ApplicationException(String.Format("{0}. Error: {1}", errMsg, errCode))) + let strError(errorNo: Int32) = + let errorStringPointer = binding.Strerror(errorNo) + Marshal.PtrToStringAnsi(errorStringPointer) - let hookDel(callbacks: List<'a * Object>) (callback: 'a)= - // TODO: invoke the native function in order to not call the trampoline anymore - callbacks - |> Seq.tryFind(fun item -> match item with | (c, _) -> c = callback) - |> (fun k -> if k.IsSome then callbacks.Remove(k.Value) |> ignore) + let checkResult(errorCode: Int32) = + // return the exception instead of raising it in order to have a more meaningful stack trace + if errorCode <> Common.UC_ERR_OK then + let errorMessage = strError(errorCode) + Some <| UnicornEngineException(errorCode, errorMessage) + else None + + let hookDel(callbacks: List<'a * (UIntPtr * Object * Object)>) (callback: 'a)= + match callbacks |> Seq.tryFind(fun item -> match item with | (c, _) -> c = callback) with + | Some(item) -> + let (hh, _, _) = snd item + match binding.HookDel(_eng.[0], hh) |> checkResult with + | Some e -> raise e + | None -> callbacks.Remove(item) |> ignore + | None -> () let allocate(size: Int32) = let mem = Marshal.AllocHGlobal(size) @@ -64,61 +74,55 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = // initialize event list _eventMemMap |> Seq.map(fun kv -> kv.Key) - |> Seq.iter (fun eventType -> _memEventHooks.Add(eventType, new List())) + |> Seq.iter (fun eventType -> _memEventHooks.Add(eventType, new List())) // init engine _eng <- [|new UIntPtr(allocate(IntPtr.Size))|] let err = binding.UcOpen(uint32 arch, uint32 mode, _eng) - checkResult(err, "Unable to open the Unicorn Engine") + if err <> Common.UC_ERR_OK then + raise(ApplicationException(String.Format("Unable to open the Unicorn Engine. Error: {0}", err))) new(arch, mode) = new Unicorn(arch, mode, BindingFactory.getDefault()) - member private this.CheckResult(errorCode: Int32) = - // return the exception instead of raising it in order to have a more meaningful stack trace - if errorCode <> Common.UC_ERR_OK then - let errorMessage = this.StrError(errorCode) - Some <| UnicornEngineException(errorCode, errorMessage) - else None - member this.MemMap(address: Int64, size: Int64, perm: Int32) = let size = new UIntPtr(uint64 size) - match binding.MemMap(_eng.[0], uint64 address, size, uint32 perm) |> this.CheckResult with + match binding.MemMap(_eng.[0], uint64 address, size, uint32 perm) |> checkResult with | Some e -> raise e | None -> () member this.MemMapPtr(address: Int64, size: Int64, perm: Int32, ptr: IntPtr) = let size = new UIntPtr(uint64 size) let ptr = new UIntPtr(ptr.ToPointer()) - match binding.MemMapPtr(_eng.[0], uint64 address, size, uint32 perm, ptr) |> this.CheckResult with + match binding.MemMapPtr(_eng.[0], uint64 address, size, uint32 perm, ptr) |> checkResult with | Some e -> raise e | None -> () member this.MemUnmap(address: Int64, size: Int64) = let size = new UIntPtr(uint64 size) - match binding.MemUnmap(_eng.[0], uint64 address, size) |> this.CheckResult with + match binding.MemUnmap(_eng.[0], uint64 address, size) |> checkResult with | Some e -> raise e | None -> () member this.MemProtect(address: Int64, size: Int64, ?perm: Int32) = let size = new UIntPtr(uint64 size) let perm = defaultArg perm Common.UC_PROT_ALL - match binding.MemProtect(_eng.[0], uint64 address, size, uint32 perm) |> this.CheckResult with + match binding.MemProtect(_eng.[0], uint64 address, size, uint32 perm) |> checkResult with | Some e -> raise e | None -> () member this.MemWrite(address: Int64, value: Byte array) = - match binding.MemWrite(_eng.[0], uint64 address, value, new UIntPtr(uint32 value.Length)) |> this.CheckResult with + match binding.MemWrite(_eng.[0], uint64 address, value, new UIntPtr(uint32 value.Length)) |> checkResult with | Some e -> raise e | None -> () member this.MemRead(address: Int64, memValue: Byte array) = - match binding.MemRead(_eng.[0], uint64 address, memValue, new UIntPtr(uint32 memValue.Length)) |> this.CheckResult with + match binding.MemRead(_eng.[0], uint64 address, memValue, new UIntPtr(uint32 memValue.Length)) |> checkResult with | Some e -> raise e | None -> () member this.RegWrite(regId: Int32, value: Byte array) = - match binding.RegWrite(_eng.[0], regId, value) |> this.CheckResult with + match binding.RegWrite(_eng.[0], regId, value) |> checkResult with | Some e -> raise e | None -> () member this.RegWrite(regId: Int32, value: Int64) = this.RegWrite(regId, int64ToBytes value) member this.RegRead(regId: Int32, regValue: Byte array) = - match binding.RegRead(_eng.[0], regId, regValue) |> this.CheckResult with + match binding.RegRead(_eng.[0], regId, regValue) |> checkResult with | Some e -> raise e | None -> () member this.RegRead(regId: Int32) = @@ -127,15 +131,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = bytesToInt64 buffer member this.EmuStart(beginAddr: Int64, untilAddr: Int64, timeout: Int64, count: Int64) = - match binding.EmuStart(_eng.[0], uint64 beginAddr, uint64 untilAddr, uint64 timeout, uint64 count) |> this.CheckResult with + match binding.EmuStart(_eng.[0], uint64 beginAddr, uint64 untilAddr, uint64 timeout, uint64 count) |> checkResult with | Some e -> raise e | None -> () member this.EmuStop() = - match binding.EmuStop(_eng.[0]) |> this.CheckResult with + match binding.EmuStop(_eng.[0]) |> checkResult with | Some e -> raise e | None -> () member this.Close() = - match binding.Close(_eng.[0]) |> this.CheckResult with + match binding.Close(_eng.[0]) |> checkResult with | Some e -> raise e | None -> () member this.ArchSupported(arch: Int32) = @@ -144,24 +148,18 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = member this.ErrNo() = binding.Errono(_eng.[0]) - member this.StrError(errorNo: Int32) = - let errorStringPointer = binding.Strerror(errorNo) - Marshal.PtrToStringAnsi(errorStringPointer) - member this.AddCodeHook(callback: CodeHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) = - _codeHooks - |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) + callback.Invoke(this, addr, size, userData) - if _codeHooks |> Seq.isEmpty then - let codeHookInternal = new CodeHookInternal(trampoline) - _hookInternals.Add(codeHookInternal) - let funcPointer = Marshal.GetFunctionPointerForDelegate(codeHookInternal) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with - | Some e -> raise e | None -> () + let codeHookInternal = new CodeHookInternal(trampoline) + let funcPointer = Marshal.GetFunctionPointerForDelegate(codeHookInternal) + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with + | Some e -> raise e | None -> () - _codeHooks.Add(callback, userData) + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _codeHooks.Add(callback, (hh, userData, codeHookInternal)) member this.AddCodeHook(callback: CodeHook, beginAddr: Int64, endAddr: Int64) = this.AddCodeHook(callback, null, beginAddr, endAddr) @@ -171,36 +169,32 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = member this.AddBlockHook(callback: BlockHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) = - _blockHooks - |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) + callback.Invoke(this, addr, size, userData) - if _blockHooks |> Seq.isEmpty then - let blockHookInternal = new BlockHookInternal(trampoline) - _hookInternals.Add(blockHookInternal) - let funcPointer = Marshal.GetFunctionPointerForDelegate(blockHookInternal) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with - | Some e -> raise e | None -> () + let blockHookInternal = new BlockHookInternal(trampoline) + let funcPointer = Marshal.GetFunctionPointerForDelegate(blockHookInternal) + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with + | Some e -> raise e | None -> () - _blockHooks.Add(callback, userData) + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _blockHooks.Add(callback, (hh, userData, blockHookInternal)) member this.HookDel(callback: BlockHook) = hookDel _blockHooks callback member this.AddInterruptHook(callback: InterruptHook, userData: Object, hookBegin: UInt64, hookEnd : UInt64) = let trampoline(u: IntPtr) (intNumber: Int32) (user: IntPtr) = - _interruptHooks - |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, intNumber, userData)) + callback.Invoke(this, intNumber, userData) - if _interruptHooks |> Seq.isEmpty then - let interruptHookInternal = new InterruptHookInternal(trampoline) - _hookInternals.Add(interruptHookInternal) - let funcPointer = Marshal.GetFunctionPointerForDelegate(interruptHookInternal) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, hookBegin, hookEnd) |> this.CheckResult with - | Some e -> raise e | None -> () + let interruptHookInternal = new InterruptHookInternal(trampoline) + let funcPointer = Marshal.GetFunctionPointerForDelegate(interruptHookInternal) + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, hookBegin, hookEnd) |> checkResult with + | Some e -> raise e | None -> () - _interruptHooks.Add(callback, userData) + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _interruptHooks.Add(callback, (hh, userData, interruptHookInternal)) member this.AddInterruptHook(callback: InterruptHook) = this.AddInterruptHook(callback, null, uint64 1, uint64 0) @@ -210,129 +204,130 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) = member this.AddMemReadHook(callback: MemReadHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (_eventType: Int32) (addr: Int64) (size: Int32) (user: IntPtr) = - _memReadHooks - |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) + callback.Invoke(this, addr, size, userData) - if _memReadHooks |> Seq.isEmpty then - let memReadHookInternal = new MemReadHookInternal(trampoline) - _hookInternals.Add(memReadHookInternal) - let funcPointer = Marshal.GetFunctionPointerForDelegate(memReadHookInternal) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with - | Some e -> raise e | None -> () + let memReadHookInternal = new MemReadHookInternal(trampoline) + let funcPointer = Marshal.GetFunctionPointerForDelegate(memReadHookInternal) + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with + | Some e -> raise e | None -> () - _memReadHooks.Add(callback, userData) + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _memReadHooks.Add(callback, (hh, userData, memReadHookInternal)) member this.HookDel(callback: MemReadHook) = hookDel _memReadHooks callback member this.AddMemWriteHook(callback: MemWriteHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (_eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) = - _memWriteHooks - |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, value, userData)) + callback.Invoke(this, addr, size, value, userData) - if _memWriteHooks |> Seq.isEmpty then - let memWriteHookInternal = new MemWriteHookInternal(trampoline) - _hookInternals.Add(memWriteHookInternal) - let funcPointer = Marshal.GetFunctionPointerForDelegate(memWriteHookInternal) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with - | Some e -> raise e | None -> () + let memWriteHookInternal = new MemWriteHookInternal(trampoline) + let funcPointer = Marshal.GetFunctionPointerForDelegate(memWriteHookInternal) + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with + | Some e -> raise e | None -> () - _memWriteHooks.Add(callback, userData) + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _memWriteHooks.Add(callback, (hh, userData, memWriteHookInternal)) member this.HookDel(callback: MemWriteHook) = hookDel _memWriteHooks callback - member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object) = + member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) = - _memEventHooks.Keys - |> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0) - |> Seq.map(fun eventflag -> _memEventHooks.[eventflag]) - |> Seq.concat - |> Seq.map(fun (callback, userData) -> callback.Invoke(this, eventType, addr, size, value, userData)) - |> Seq.forall id + callback.Invoke(this, eventType, addr, size, value, userData) // register the event if not already done _memEventHooks.Keys |> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0) - |> Seq.filter(fun eventFlag -> _memEventHooks.[eventFlag] |> Seq.isEmpty) |> Seq.iter(fun eventFlag -> let memEventHookInternal = new EventMemHookInternal(trampoline) - _hookInternals.Add(memEventHookInternal) let funcPointer = Marshal.GetFunctionPointerForDelegate(memEventHookInternal) let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0) |> this.CheckResult with + match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with | Some e -> raise e | None -> () + + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _memEventHooks.[eventFlag].Add((callback, (hh, userData, memEventHookInternal))) ) - // register the callbacks - _memEventHooks.Keys - |> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0) - |> Seq.iter(fun eventFlag -> _memEventHooks.[eventFlag].Add((callback, userData))) + member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object) = + this.AddEventMemHook(callback, eventType, userData, 1, 0) member this.AddEventMemHook(callback: EventMemHook, eventType: Int32) = this.AddEventMemHook(callback, eventType, null) member this.HookDel(callback: EventMemHook) = - let callbacks = (_memEventHooks.Values |> Seq.concat).ToList() - hookDel callbacks callback + _memEventHooks.Keys + |> Seq.iter(fun eventFlag -> hookDel _memEventHooks.[eventFlag] callback) + + member this.AddInHook(callback: InHook, userData: Object, beginAddr: Int64, endAddr: Int64) = + let trampoline(u: IntPtr) (port: Int32) (size: Int32) (user: IntPtr) = + callback.Invoke(this, port, size, userData) + + let inHookInternal = new InHookInternal(trampoline) + let funcPointer = Marshal.GetFunctionPointerForDelegate(inHookInternal) + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr, X86.UC_X86_INS_IN) |> checkResult with + | Some e -> raise e | None -> () + + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _inHooks.Add(callback, (hh, userData, inHookInternal)) member this.AddInHook(callback: InHook, userData: Object) = - let trampoline(u: IntPtr) (port: Int32) (size: Int32) (user: IntPtr) = - _inHooks - |> Seq.map(fun (callback, userData) -> callback.Invoke(this, port, size, userData)) - |> Seq.last - - if _inHooks |> Seq.isEmpty then - let inHookInternal = new InHookInternal(trampoline) - _hookInternals.Add(inHookInternal) - let funcPointer = Marshal.GetFunctionPointerForDelegate(inHookInternal) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_IN) |> this.CheckResult with - | Some e -> raise e | None -> () - - _inHooks.Add(callback, userData) + this.AddInHook(callback, userData, 1, 0) member this.AddInHook(callback: InHook) = this.AddInHook(callback, null) - member this.AddOutHook(callback: OutHook, userData: Object) = + member this.HookDel(callback: InHook) = + hookDel _inHooks callback + + member this.AddOutHook(callback: OutHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (port: Int32) (size: Int32) (value: Int32) (user: IntPtr) = - _outHooks - |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, port, size, value, userData)) + callback.Invoke(this, port, size, value, userData) - if _outHooks |> Seq.isEmpty then - let outHookInternal = new OutHookInternal(trampoline) - _hookInternals.Add(outHookInternal) - let funcPointer = Marshal.GetFunctionPointerForDelegate(outHookInternal) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_OUT) |> this.CheckResult with - | Some e -> raise e | None -> () + let outHookInternal = new OutHookInternal(trampoline) + let funcPointer = Marshal.GetFunctionPointerForDelegate(outHookInternal) + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr, X86.UC_X86_INS_OUT) |> checkResult with + | Some e -> raise e | None -> () - _outHooks.Add(callback, userData) + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _outHooks.Add(callback, (hh, userData, outHookInternal)) + + member this.AddOutHook(callback: OutHook, userData: Object) = + this.AddOutHook(callback, userData, 1, 0) member this.AddOutHook(callback: OutHook) = this.AddOutHook(callback, null) - member this.AddSyscallHook(callback: SyscallHook, userData: Object) = + member this.HookDel(callback: OutHook) = + hookDel _outHooks callback + + member this.AddSyscallHook(callback: SyscallHook, userData: Object, beginAddr: Int64, endAddr: Int64) = let trampoline(u: IntPtr) (user: IntPtr) = - _syscallHooks - |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, userData)) + callback.Invoke(this, userData) - if _syscallHooks |> Seq.isEmpty then - let syscallHookInternal = new SyscallHookInternal(trampoline) - _hookInternals.Add(syscallHookInternal) - let funcPointer = Marshal.GetFunctionPointerForDelegate(syscallHookInternal) - let hh = new UIntPtr(allocate(IntPtr.Size)) - match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with - | Some e -> raise e | None -> () + let syscallHookInternal = new SyscallHookInternal(trampoline) + let funcPointer = Marshal.GetFunctionPointerForDelegate(syscallHookInternal) + let hh = new UIntPtr(allocate(IntPtr.Size)) + match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr, X86.UC_X86_INS_SYSCALL) |> checkResult with + | Some e -> raise e | None -> () - _syscallHooks.Add(callback, userData) + let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh)) + _syscallHooks.Add(callback, (hh, userData, syscallHookInternal)) + + member this.AddSyscallHook(callback: SyscallHook, userData: Object) = + this.AddSyscallHook(callback, userData, 1, 0) member this.AddSyscallHook(callback: SyscallHook) = this.AddSyscallHook(callback, null) + member this.HookDel(callback: SyscallHook) = + hookDel _syscallHooks callback + member this.Version() = let (major, minor) = (new UIntPtr(), new UIntPtr()) let combined = binding.Version(major, minor) From 11fcbad9ff937c922f6666f6f8111b2240efe314 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 12 Mar 2023 20:28:01 +0100 Subject: [PATCH 06/26] Remove redundant printf --- tests/unit/test_ctl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 0c1eeabc..e1e467d3 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -309,7 +309,6 @@ static void test_uc_emu_stop_set_ip_callback(uc_engine *uc, uint64_t address, ui uint64_t rip = code_start + 0xb; if (address == code_start + 0x7) { - printf("stoping\n"); uc_emu_stop(uc); uc_reg_write(uc, UC_X86_REG_RIP, &rip); } From 8f2841ecdb4db099d5670fa396012810179d7a06 Mon Sep 17 00:00:00 2001 From: Choongwoo Han Date: Mon, 20 Mar 2023 17:07:15 -0700 Subject: [PATCH 07/26] Cache index for find_memory_region --- uc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/uc.c b/uc.c index 76c4eb28..ed9663ef 100644 --- a/uc.c +++ b/uc.c @@ -1532,8 +1532,10 @@ MemoryRegion *find_memory_region(struct uc_struct *uc, uint64_t address) if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && - address <= uc->mapped_blocks[i]->end - 1) + address < uc->mapped_blocks[i]->end) { + uc->mapped_block_cache_index = i; return uc->mapped_blocks[i]; + } // not found return NULL; From 0a38a0bf1728bfcf6e358e3574211dac4b62446b Mon Sep 17 00:00:00 2001 From: Choongwoo Han Date: Mon, 20 Mar 2023 18:41:59 -0700 Subject: [PATCH 08/26] Fix test failure --- uc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uc.c b/uc.c index ed9663ef..a1a71366 100644 --- a/uc.c +++ b/uc.c @@ -1524,7 +1524,7 @@ MemoryRegion *find_memory_region(struct uc_struct *uc, uint64_t address) if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && - address < uc->mapped_blocks[i]->end) { + address <= uc->mapped_blocks[i]->end - 1) { return uc->mapped_blocks[i]; } @@ -1532,7 +1532,7 @@ MemoryRegion *find_memory_region(struct uc_struct *uc, uint64_t address) if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && - address < uc->mapped_blocks[i]->end) { + address <= uc->mapped_blocks[i]->end - 1) { uc->mapped_block_cache_index = i; return uc->mapped_blocks[i]; } From d504e3a004a594bc96e163ba691ad8ed1e9d389b Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 22 Mar 2023 13:57:12 -0500 Subject: [PATCH 09/26] build: Fixes for Haiku * Haiku is fully posix, so can be lumped together with most unix cases --- glib_compat/grand.c | 4 ++-- tests/unit/acutest.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/glib_compat/grand.c b/glib_compat/grand.c index b6e57645..0d3f95b4 100644 --- a/glib_compat/grand.c +++ b/glib_compat/grand.c @@ -232,7 +232,7 @@ GRand *g_rand_new_with_seed_array (const guint32 *seed, guint seed_length) gint64 g_get_real_time (void) { -#if defined(unix) || defined(__unix__) || defined(__unix) || defined (__MINGW32__) || defined(__APPLE__) +#if defined(unix) || defined(__unix__) || defined(__unix) || defined (__MINGW32__) || defined(__APPLE__) || defined(__HAIKU__) struct timeval r; /* this is required on alpha, there the timeval structs are ints @@ -271,7 +271,7 @@ gint64 g_get_real_time (void) GRand *g_rand_new (void) { guint32 seed[4]; -#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) +#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) || defined(__HAIKU__) static gboolean dev_urandom_exists = TRUE; if (dev_urandom_exists) diff --git a/tests/unit/acutest.h b/tests/unit/acutest.h index 6b4d596d..fbe55bc2 100644 --- a/tests/unit/acutest.h +++ b/tests/unit/acutest.h @@ -270,7 +270,7 @@ #include #include -#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) +#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) || defined(__HAIKU__) #define ACUTEST_UNIX_ 1 #include #include From c6158b8628ff443506fe3333fafa83df2cf41678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matheus=20C=2E=20Fran=C3=A7a?= Date: Thu, 23 Mar 2023 10:09:41 -0300 Subject: [PATCH 10/26] zig consts --- bindings/Makefile | 1 + bindings/const_generator.py | 20 + bindings/zig/README.md | 10 + bindings/zig/unicorn/arm64_const.zig | 337 +++++ bindings/zig/unicorn/arm_const.zig | 196 +++ bindings/zig/unicorn/m68k_const.zig | 41 + bindings/zig/unicorn/mips_const.zig | 239 ++++ bindings/zig/unicorn/ppc_const.zig | 408 ++++++ bindings/zig/unicorn/riscv_const.zig | 289 +++++ bindings/zig/unicorn/s390x_const.zig | 126 ++ bindings/zig/unicorn/sparc_const.zig | 138 ++ bindings/zig/unicorn/tricore_const.zig | 128 ++ bindings/zig/unicorn/unicorn.zig | 13 + bindings/zig/unicorn/unicorn_const.zig | 144 +++ bindings/zig/unicorn/x86_const.zig | 1632 ++++++++++++++++++++++++ 15 files changed, 3722 insertions(+) create mode 100644 bindings/zig/README.md create mode 100644 bindings/zig/unicorn/arm64_const.zig create mode 100644 bindings/zig/unicorn/arm_const.zig create mode 100644 bindings/zig/unicorn/m68k_const.zig create mode 100644 bindings/zig/unicorn/mips_const.zig create mode 100644 bindings/zig/unicorn/ppc_const.zig create mode 100644 bindings/zig/unicorn/riscv_const.zig create mode 100644 bindings/zig/unicorn/s390x_const.zig create mode 100644 bindings/zig/unicorn/sparc_const.zig create mode 100644 bindings/zig/unicorn/tricore_const.zig create mode 100644 bindings/zig/unicorn/unicorn.zig create mode 100644 bindings/zig/unicorn/unicorn_const.zig create mode 100644 bindings/zig/unicorn/x86_const.zig diff --git a/bindings/Makefile b/bindings/Makefile index bc5fb243..8c2ee2c2 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -26,6 +26,7 @@ build: $(MAKE) -C ruby gen_const python3 const_generator.py dotnet python3 const_generator.py pascal + python3 const_generator.py zig install: build $(MAKE) -C python install diff --git a/bindings/const_generator.py b/bindings/const_generator.py index 2a74c864..4c5d1e76 100644 --- a/bindings/const_generator.py +++ b/bindings/const_generator.py @@ -129,6 +129,26 @@ template = { 'comment_open': '//', 'comment_close': '', }, + 'zig': { + 'header': "// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT\n\npub const %sConst = enum(c_int) {\n", + 'footer': "\n};\n", + 'line_format': '\t%s = %s,\n', + 'out_file': './zig/unicorn/%s_const.zig', + # prefixes for constant filenames of all archs - case sensitive + 'arm.h': 'arm', + 'arm64.h': 'arm64', + 'mips.h': 'mips', + 'x86.h': 'x86', + 'sparc.h': 'sparc', + 'm68k.h': 'm68k', + 'ppc.h': 'ppc', + 'riscv.h': 'riscv', + 's390x.h' : 's390x', + 'tricore.h' : 'tricore', + 'unicorn.h': 'unicorn', + 'comment_open': '//', + 'comment_close': '', + }, } # markup for comments to be added to autogen files diff --git a/bindings/zig/README.md b/bindings/zig/README.md new file mode 100644 index 00000000..47bdda0e --- /dev/null +++ b/bindings/zig/README.md @@ -0,0 +1,10 @@ +# Unicorn-engine-Zig + +[Zig](https://ziglang.org/) bindings for the [Unicorn](http://www.unicorn-engine.org/) emulator with utility functions. + +*Unicorn* is a lightweight multi-platform, multi-architecture CPU emulator framework +based on [QEMU](http://www.qemu.org/). + +## How to use + +Add to your project the file `unicorn/unicorn.zig` that will manage all the available architectures. \ No newline at end of file diff --git a/bindings/zig/unicorn/arm64_const.zig b/bindings/zig/unicorn/arm64_const.zig new file mode 100644 index 00000000..54aa4030 --- /dev/null +++ b/bindings/zig/unicorn/arm64_const.zig @@ -0,0 +1,337 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const arm64Const = enum(c_int) { + +// ARM64 CPU + + CPU_ARM64_A57 = 0, + CPU_ARM64_A53 = 1, + CPU_ARM64_A72 = 2, + CPU_ARM64_MAX = 3, + CPU_ARM64_ENDING = 4, + +// ARM64 registers + + ARM64_REG_INVALID = 0, + ARM64_REG_X29 = 1, + ARM64_REG_X30 = 2, + ARM64_REG_NZCV = 3, + ARM64_REG_SP = 4, + ARM64_REG_WSP = 5, + ARM64_REG_WZR = 6, + ARM64_REG_XZR = 7, + ARM64_REG_B0 = 8, + ARM64_REG_B1 = 9, + ARM64_REG_B2 = 10, + ARM64_REG_B3 = 11, + ARM64_REG_B4 = 12, + ARM64_REG_B5 = 13, + ARM64_REG_B6 = 14, + ARM64_REG_B7 = 15, + ARM64_REG_B8 = 16, + ARM64_REG_B9 = 17, + ARM64_REG_B10 = 18, + ARM64_REG_B11 = 19, + ARM64_REG_B12 = 20, + ARM64_REG_B13 = 21, + ARM64_REG_B14 = 22, + ARM64_REG_B15 = 23, + ARM64_REG_B16 = 24, + ARM64_REG_B17 = 25, + ARM64_REG_B18 = 26, + ARM64_REG_B19 = 27, + ARM64_REG_B20 = 28, + ARM64_REG_B21 = 29, + ARM64_REG_B22 = 30, + ARM64_REG_B23 = 31, + ARM64_REG_B24 = 32, + ARM64_REG_B25 = 33, + ARM64_REG_B26 = 34, + ARM64_REG_B27 = 35, + ARM64_REG_B28 = 36, + ARM64_REG_B29 = 37, + ARM64_REG_B30 = 38, + ARM64_REG_B31 = 39, + ARM64_REG_D0 = 40, + ARM64_REG_D1 = 41, + ARM64_REG_D2 = 42, + ARM64_REG_D3 = 43, + ARM64_REG_D4 = 44, + ARM64_REG_D5 = 45, + ARM64_REG_D6 = 46, + ARM64_REG_D7 = 47, + ARM64_REG_D8 = 48, + ARM64_REG_D9 = 49, + ARM64_REG_D10 = 50, + ARM64_REG_D11 = 51, + ARM64_REG_D12 = 52, + ARM64_REG_D13 = 53, + ARM64_REG_D14 = 54, + ARM64_REG_D15 = 55, + ARM64_REG_D16 = 56, + ARM64_REG_D17 = 57, + ARM64_REG_D18 = 58, + ARM64_REG_D19 = 59, + ARM64_REG_D20 = 60, + ARM64_REG_D21 = 61, + ARM64_REG_D22 = 62, + ARM64_REG_D23 = 63, + ARM64_REG_D24 = 64, + ARM64_REG_D25 = 65, + ARM64_REG_D26 = 66, + ARM64_REG_D27 = 67, + ARM64_REG_D28 = 68, + ARM64_REG_D29 = 69, + ARM64_REG_D30 = 70, + ARM64_REG_D31 = 71, + ARM64_REG_H0 = 72, + ARM64_REG_H1 = 73, + ARM64_REG_H2 = 74, + ARM64_REG_H3 = 75, + ARM64_REG_H4 = 76, + ARM64_REG_H5 = 77, + ARM64_REG_H6 = 78, + ARM64_REG_H7 = 79, + ARM64_REG_H8 = 80, + ARM64_REG_H9 = 81, + ARM64_REG_H10 = 82, + ARM64_REG_H11 = 83, + ARM64_REG_H12 = 84, + ARM64_REG_H13 = 85, + ARM64_REG_H14 = 86, + ARM64_REG_H15 = 87, + ARM64_REG_H16 = 88, + ARM64_REG_H17 = 89, + ARM64_REG_H18 = 90, + ARM64_REG_H19 = 91, + ARM64_REG_H20 = 92, + ARM64_REG_H21 = 93, + ARM64_REG_H22 = 94, + ARM64_REG_H23 = 95, + ARM64_REG_H24 = 96, + ARM64_REG_H25 = 97, + ARM64_REG_H26 = 98, + ARM64_REG_H27 = 99, + ARM64_REG_H28 = 100, + ARM64_REG_H29 = 101, + ARM64_REG_H30 = 102, + ARM64_REG_H31 = 103, + ARM64_REG_Q0 = 104, + ARM64_REG_Q1 = 105, + ARM64_REG_Q2 = 106, + ARM64_REG_Q3 = 107, + ARM64_REG_Q4 = 108, + ARM64_REG_Q5 = 109, + ARM64_REG_Q6 = 110, + ARM64_REG_Q7 = 111, + ARM64_REG_Q8 = 112, + ARM64_REG_Q9 = 113, + ARM64_REG_Q10 = 114, + ARM64_REG_Q11 = 115, + ARM64_REG_Q12 = 116, + ARM64_REG_Q13 = 117, + ARM64_REG_Q14 = 118, + ARM64_REG_Q15 = 119, + ARM64_REG_Q16 = 120, + ARM64_REG_Q17 = 121, + ARM64_REG_Q18 = 122, + ARM64_REG_Q19 = 123, + ARM64_REG_Q20 = 124, + ARM64_REG_Q21 = 125, + ARM64_REG_Q22 = 126, + ARM64_REG_Q23 = 127, + ARM64_REG_Q24 = 128, + ARM64_REG_Q25 = 129, + ARM64_REG_Q26 = 130, + ARM64_REG_Q27 = 131, + ARM64_REG_Q28 = 132, + ARM64_REG_Q29 = 133, + ARM64_REG_Q30 = 134, + ARM64_REG_Q31 = 135, + ARM64_REG_S0 = 136, + ARM64_REG_S1 = 137, + ARM64_REG_S2 = 138, + ARM64_REG_S3 = 139, + ARM64_REG_S4 = 140, + ARM64_REG_S5 = 141, + ARM64_REG_S6 = 142, + ARM64_REG_S7 = 143, + ARM64_REG_S8 = 144, + ARM64_REG_S9 = 145, + ARM64_REG_S10 = 146, + ARM64_REG_S11 = 147, + ARM64_REG_S12 = 148, + ARM64_REG_S13 = 149, + ARM64_REG_S14 = 150, + ARM64_REG_S15 = 151, + ARM64_REG_S16 = 152, + ARM64_REG_S17 = 153, + ARM64_REG_S18 = 154, + ARM64_REG_S19 = 155, + ARM64_REG_S20 = 156, + ARM64_REG_S21 = 157, + ARM64_REG_S22 = 158, + ARM64_REG_S23 = 159, + ARM64_REG_S24 = 160, + ARM64_REG_S25 = 161, + ARM64_REG_S26 = 162, + ARM64_REG_S27 = 163, + ARM64_REG_S28 = 164, + ARM64_REG_S29 = 165, + ARM64_REG_S30 = 166, + ARM64_REG_S31 = 167, + ARM64_REG_W0 = 168, + ARM64_REG_W1 = 169, + ARM64_REG_W2 = 170, + ARM64_REG_W3 = 171, + ARM64_REG_W4 = 172, + ARM64_REG_W5 = 173, + ARM64_REG_W6 = 174, + ARM64_REG_W7 = 175, + ARM64_REG_W8 = 176, + ARM64_REG_W9 = 177, + ARM64_REG_W10 = 178, + ARM64_REG_W11 = 179, + ARM64_REG_W12 = 180, + ARM64_REG_W13 = 181, + ARM64_REG_W14 = 182, + ARM64_REG_W15 = 183, + ARM64_REG_W16 = 184, + ARM64_REG_W17 = 185, + ARM64_REG_W18 = 186, + ARM64_REG_W19 = 187, + ARM64_REG_W20 = 188, + ARM64_REG_W21 = 189, + ARM64_REG_W22 = 190, + ARM64_REG_W23 = 191, + ARM64_REG_W24 = 192, + ARM64_REG_W25 = 193, + ARM64_REG_W26 = 194, + ARM64_REG_W27 = 195, + ARM64_REG_W28 = 196, + ARM64_REG_W29 = 197, + ARM64_REG_W30 = 198, + ARM64_REG_X0 = 199, + ARM64_REG_X1 = 200, + ARM64_REG_X2 = 201, + ARM64_REG_X3 = 202, + ARM64_REG_X4 = 203, + ARM64_REG_X5 = 204, + ARM64_REG_X6 = 205, + ARM64_REG_X7 = 206, + ARM64_REG_X8 = 207, + ARM64_REG_X9 = 208, + ARM64_REG_X10 = 209, + ARM64_REG_X11 = 210, + ARM64_REG_X12 = 211, + ARM64_REG_X13 = 212, + ARM64_REG_X14 = 213, + ARM64_REG_X15 = 214, + ARM64_REG_X16 = 215, + ARM64_REG_X17 = 216, + ARM64_REG_X18 = 217, + ARM64_REG_X19 = 218, + ARM64_REG_X20 = 219, + ARM64_REG_X21 = 220, + ARM64_REG_X22 = 221, + ARM64_REG_X23 = 222, + ARM64_REG_X24 = 223, + ARM64_REG_X25 = 224, + ARM64_REG_X26 = 225, + ARM64_REG_X27 = 226, + ARM64_REG_X28 = 227, + ARM64_REG_V0 = 228, + ARM64_REG_V1 = 229, + ARM64_REG_V2 = 230, + ARM64_REG_V3 = 231, + ARM64_REG_V4 = 232, + ARM64_REG_V5 = 233, + ARM64_REG_V6 = 234, + ARM64_REG_V7 = 235, + ARM64_REG_V8 = 236, + ARM64_REG_V9 = 237, + ARM64_REG_V10 = 238, + ARM64_REG_V11 = 239, + ARM64_REG_V12 = 240, + ARM64_REG_V13 = 241, + ARM64_REG_V14 = 242, + ARM64_REG_V15 = 243, + ARM64_REG_V16 = 244, + ARM64_REG_V17 = 245, + ARM64_REG_V18 = 246, + ARM64_REG_V19 = 247, + ARM64_REG_V20 = 248, + ARM64_REG_V21 = 249, + ARM64_REG_V22 = 250, + ARM64_REG_V23 = 251, + ARM64_REG_V24 = 252, + ARM64_REG_V25 = 253, + ARM64_REG_V26 = 254, + ARM64_REG_V27 = 255, + ARM64_REG_V28 = 256, + ARM64_REG_V29 = 257, + ARM64_REG_V30 = 258, + ARM64_REG_V31 = 259, + +// pseudo registers + ARM64_REG_PC = 260, + ARM64_REG_CPACR_EL1 = 261, + +// thread registers, depreciated, use UC_ARM64_REG_CP_REG instead + ARM64_REG_TPIDR_EL0 = 262, + ARM64_REG_TPIDRRO_EL0 = 263, + ARM64_REG_TPIDR_EL1 = 264, + ARM64_REG_PSTATE = 265, + +// exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead + ARM64_REG_ELR_EL0 = 266, + ARM64_REG_ELR_EL1 = 267, + ARM64_REG_ELR_EL2 = 268, + ARM64_REG_ELR_EL3 = 269, + +// stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead + ARM64_REG_SP_EL0 = 270, + ARM64_REG_SP_EL1 = 271, + ARM64_REG_SP_EL2 = 272, + ARM64_REG_SP_EL3 = 273, + +// other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead + ARM64_REG_TTBR0_EL1 = 274, + ARM64_REG_TTBR1_EL1 = 275, + ARM64_REG_ESR_EL0 = 276, + ARM64_REG_ESR_EL1 = 277, + ARM64_REG_ESR_EL2 = 278, + ARM64_REG_ESR_EL3 = 279, + ARM64_REG_FAR_EL0 = 280, + ARM64_REG_FAR_EL1 = 281, + ARM64_REG_FAR_EL2 = 282, + ARM64_REG_FAR_EL3 = 283, + ARM64_REG_PAR_EL1 = 284, + ARM64_REG_MAIR_EL1 = 285, + ARM64_REG_VBAR_EL0 = 286, + ARM64_REG_VBAR_EL1 = 287, + ARM64_REG_VBAR_EL2 = 288, + ARM64_REG_VBAR_EL3 = 289, + ARM64_REG_CP_REG = 290, + +// floating point control and status registers + ARM64_REG_FPCR = 291, + ARM64_REG_FPSR = 292, + ARM64_REG_ENDING = 293, + +// alias registers + ARM64_REG_IP0 = 215, + ARM64_REG_IP1 = 216, + ARM64_REG_FP = 1, + ARM64_REG_LR = 2, + +// ARM64 instructions + + ARM64_INS_INVALID = 0, + ARM64_INS_MRS = 1, + ARM64_INS_MSR = 2, + ARM64_INS_SYS = 3, + ARM64_INS_SYSL = 4, + ARM64_INS_ENDING = 5, + +}; diff --git a/bindings/zig/unicorn/arm_const.zig b/bindings/zig/unicorn/arm_const.zig new file mode 100644 index 00000000..2403e9a7 --- /dev/null +++ b/bindings/zig/unicorn/arm_const.zig @@ -0,0 +1,196 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const armConst = enum(c_int) { + +// ARM CPU + + CPU_ARM_926 = 0, + CPU_ARM_946 = 1, + CPU_ARM_1026 = 2, + CPU_ARM_1136_R2 = 3, + CPU_ARM_1136 = 4, + CPU_ARM_1176 = 5, + CPU_ARM_11MPCORE = 6, + CPU_ARM_CORTEX_M0 = 7, + CPU_ARM_CORTEX_M3 = 8, + CPU_ARM_CORTEX_M4 = 9, + CPU_ARM_CORTEX_M7 = 10, + CPU_ARM_CORTEX_M33 = 11, + CPU_ARM_CORTEX_R5 = 12, + CPU_ARM_CORTEX_R5F = 13, + CPU_ARM_CORTEX_A7 = 14, + CPU_ARM_CORTEX_A8 = 15, + CPU_ARM_CORTEX_A9 = 16, + CPU_ARM_CORTEX_A15 = 17, + CPU_ARM_TI925T = 18, + CPU_ARM_SA1100 = 19, + CPU_ARM_SA1110 = 20, + CPU_ARM_PXA250 = 21, + CPU_ARM_PXA255 = 22, + CPU_ARM_PXA260 = 23, + CPU_ARM_PXA261 = 24, + CPU_ARM_PXA262 = 25, + CPU_ARM_PXA270 = 26, + CPU_ARM_PXA270A0 = 27, + CPU_ARM_PXA270A1 = 28, + CPU_ARM_PXA270B0 = 29, + CPU_ARM_PXA270B1 = 30, + CPU_ARM_PXA270C0 = 31, + CPU_ARM_PXA270C5 = 32, + CPU_ARM_MAX = 33, + CPU_ARM_ENDING = 34, + +// ARM registers + + ARM_REG_INVALID = 0, + ARM_REG_APSR = 1, + ARM_REG_APSR_NZCV = 2, + ARM_REG_CPSR = 3, + ARM_REG_FPEXC = 4, + ARM_REG_FPINST = 5, + ARM_REG_FPSCR = 6, + ARM_REG_FPSCR_NZCV = 7, + ARM_REG_FPSID = 8, + ARM_REG_ITSTATE = 9, + ARM_REG_LR = 10, + ARM_REG_PC = 11, + ARM_REG_SP = 12, + ARM_REG_SPSR = 13, + ARM_REG_D0 = 14, + ARM_REG_D1 = 15, + ARM_REG_D2 = 16, + ARM_REG_D3 = 17, + ARM_REG_D4 = 18, + ARM_REG_D5 = 19, + ARM_REG_D6 = 20, + ARM_REG_D7 = 21, + ARM_REG_D8 = 22, + ARM_REG_D9 = 23, + ARM_REG_D10 = 24, + ARM_REG_D11 = 25, + ARM_REG_D12 = 26, + ARM_REG_D13 = 27, + ARM_REG_D14 = 28, + ARM_REG_D15 = 29, + ARM_REG_D16 = 30, + ARM_REG_D17 = 31, + ARM_REG_D18 = 32, + ARM_REG_D19 = 33, + ARM_REG_D20 = 34, + ARM_REG_D21 = 35, + ARM_REG_D22 = 36, + ARM_REG_D23 = 37, + ARM_REG_D24 = 38, + ARM_REG_D25 = 39, + ARM_REG_D26 = 40, + ARM_REG_D27 = 41, + ARM_REG_D28 = 42, + ARM_REG_D29 = 43, + ARM_REG_D30 = 44, + ARM_REG_D31 = 45, + ARM_REG_FPINST2 = 46, + ARM_REG_MVFR0 = 47, + ARM_REG_MVFR1 = 48, + ARM_REG_MVFR2 = 49, + ARM_REG_Q0 = 50, + ARM_REG_Q1 = 51, + ARM_REG_Q2 = 52, + ARM_REG_Q3 = 53, + ARM_REG_Q4 = 54, + ARM_REG_Q5 = 55, + ARM_REG_Q6 = 56, + ARM_REG_Q7 = 57, + ARM_REG_Q8 = 58, + ARM_REG_Q9 = 59, + ARM_REG_Q10 = 60, + ARM_REG_Q11 = 61, + ARM_REG_Q12 = 62, + ARM_REG_Q13 = 63, + ARM_REG_Q14 = 64, + ARM_REG_Q15 = 65, + ARM_REG_R0 = 66, + ARM_REG_R1 = 67, + ARM_REG_R2 = 68, + ARM_REG_R3 = 69, + ARM_REG_R4 = 70, + ARM_REG_R5 = 71, + ARM_REG_R6 = 72, + ARM_REG_R7 = 73, + ARM_REG_R8 = 74, + ARM_REG_R9 = 75, + ARM_REG_R10 = 76, + ARM_REG_R11 = 77, + ARM_REG_R12 = 78, + ARM_REG_S0 = 79, + ARM_REG_S1 = 80, + ARM_REG_S2 = 81, + ARM_REG_S3 = 82, + ARM_REG_S4 = 83, + ARM_REG_S5 = 84, + ARM_REG_S6 = 85, + ARM_REG_S7 = 86, + ARM_REG_S8 = 87, + ARM_REG_S9 = 88, + ARM_REG_S10 = 89, + ARM_REG_S11 = 90, + ARM_REG_S12 = 91, + ARM_REG_S13 = 92, + ARM_REG_S14 = 93, + ARM_REG_S15 = 94, + ARM_REG_S16 = 95, + ARM_REG_S17 = 96, + ARM_REG_S18 = 97, + ARM_REG_S19 = 98, + ARM_REG_S20 = 99, + ARM_REG_S21 = 100, + ARM_REG_S22 = 101, + ARM_REG_S23 = 102, + ARM_REG_S24 = 103, + ARM_REG_S25 = 104, + ARM_REG_S26 = 105, + ARM_REG_S27 = 106, + ARM_REG_S28 = 107, + ARM_REG_S29 = 108, + ARM_REG_S30 = 109, + ARM_REG_S31 = 110, + ARM_REG_C1_C0_2 = 111, + ARM_REG_C13_C0_2 = 112, + ARM_REG_C13_C0_3 = 113, + ARM_REG_IPSR = 114, + ARM_REG_MSP = 115, + ARM_REG_PSP = 116, + ARM_REG_CONTROL = 117, + ARM_REG_IAPSR = 118, + ARM_REG_EAPSR = 119, + ARM_REG_XPSR = 120, + ARM_REG_EPSR = 121, + ARM_REG_IEPSR = 122, + ARM_REG_PRIMASK = 123, + ARM_REG_BASEPRI = 124, + ARM_REG_BASEPRI_MAX = 125, + ARM_REG_FAULTMASK = 126, + ARM_REG_APSR_NZCVQ = 127, + ARM_REG_APSR_G = 128, + ARM_REG_APSR_NZCVQG = 129, + ARM_REG_IAPSR_NZCVQ = 130, + ARM_REG_IAPSR_G = 131, + ARM_REG_IAPSR_NZCVQG = 132, + ARM_REG_EAPSR_NZCVQ = 133, + ARM_REG_EAPSR_G = 134, + ARM_REG_EAPSR_NZCVQG = 135, + ARM_REG_XPSR_NZCVQ = 136, + ARM_REG_XPSR_G = 137, + ARM_REG_XPSR_NZCVQG = 138, + ARM_REG_CP_REG = 139, + ARM_REG_ENDING = 140, + +// alias registers + ARM_REG_R13 = 12, + ARM_REG_R14 = 10, + ARM_REG_R15 = 11, + ARM_REG_SB = 75, + ARM_REG_SL = 76, + ARM_REG_FP = 77, + ARM_REG_IP = 78, + +}; diff --git a/bindings/zig/unicorn/m68k_const.zig b/bindings/zig/unicorn/m68k_const.zig new file mode 100644 index 00000000..8514d848 --- /dev/null +++ b/bindings/zig/unicorn/m68k_const.zig @@ -0,0 +1,41 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const m68kConst = enum(c_int) { + +// M68K CPU + + CPU_M68K_M5206 = 0, + CPU_M68K_M68000 = 1, + CPU_M68K_M68020 = 2, + CPU_M68K_M68030 = 3, + CPU_M68K_M68040 = 4, + CPU_M68K_M68060 = 5, + CPU_M68K_M5208 = 6, + CPU_M68K_CFV4E = 7, + CPU_M68K_ANY = 8, + CPU_M68K_ENDING = 9, + +// M68K registers + + M68K_REG_INVALID = 0, + M68K_REG_A0 = 1, + M68K_REG_A1 = 2, + M68K_REG_A2 = 3, + M68K_REG_A3 = 4, + M68K_REG_A4 = 5, + M68K_REG_A5 = 6, + M68K_REG_A6 = 7, + M68K_REG_A7 = 8, + M68K_REG_D0 = 9, + M68K_REG_D1 = 10, + M68K_REG_D2 = 11, + M68K_REG_D3 = 12, + M68K_REG_D4 = 13, + M68K_REG_D5 = 14, + M68K_REG_D6 = 15, + M68K_REG_D7 = 16, + M68K_REG_SR = 17, + M68K_REG_PC = 18, + M68K_REG_ENDING = 19, + +}; diff --git a/bindings/zig/unicorn/mips_const.zig b/bindings/zig/unicorn/mips_const.zig new file mode 100644 index 00000000..39a8aaf9 --- /dev/null +++ b/bindings/zig/unicorn/mips_const.zig @@ -0,0 +1,239 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const mipsConst = enum(c_int) { + +// MIPS32 CPUS + + CPU_MIPS32_4KC = 0, + CPU_MIPS32_4KM = 1, + CPU_MIPS32_4KECR1 = 2, + CPU_MIPS32_4KEMR1 = 3, + CPU_MIPS32_4KEC = 4, + CPU_MIPS32_4KEM = 5, + CPU_MIPS32_24KC = 6, + CPU_MIPS32_24KEC = 7, + CPU_MIPS32_24KF = 8, + CPU_MIPS32_34KF = 9, + CPU_MIPS32_74KF = 10, + CPU_MIPS32_M14K = 11, + CPU_MIPS32_M14KC = 12, + CPU_MIPS32_P5600 = 13, + CPU_MIPS32_MIPS32R6_GENERIC = 14, + CPU_MIPS32_I7200 = 15, + CPU_MIPS32_ENDING = 16, + +// MIPS64 CPUS + + CPU_MIPS64_R4000 = 0, + CPU_MIPS64_VR5432 = 1, + CPU_MIPS64_5KC = 2, + CPU_MIPS64_5KF = 3, + CPU_MIPS64_20KC = 4, + CPU_MIPS64_MIPS64R2_GENERIC = 5, + CPU_MIPS64_5KEC = 6, + CPU_MIPS64_5KEF = 7, + CPU_MIPS64_I6400 = 8, + CPU_MIPS64_I6500 = 9, + CPU_MIPS64_LOONGSON_2E = 10, + CPU_MIPS64_LOONGSON_2F = 11, + CPU_MIPS64_MIPS64DSPR2 = 12, + CPU_MIPS64_ENDING = 13, + +// MIPS registers + + MIPS_REG_INVALID = 0, + +// General purpose registers + MIPS_REG_PC = 1, + MIPS_REG_0 = 2, + MIPS_REG_1 = 3, + MIPS_REG_2 = 4, + MIPS_REG_3 = 5, + MIPS_REG_4 = 6, + MIPS_REG_5 = 7, + MIPS_REG_6 = 8, + MIPS_REG_7 = 9, + MIPS_REG_8 = 10, + MIPS_REG_9 = 11, + MIPS_REG_10 = 12, + MIPS_REG_11 = 13, + MIPS_REG_12 = 14, + MIPS_REG_13 = 15, + MIPS_REG_14 = 16, + MIPS_REG_15 = 17, + MIPS_REG_16 = 18, + MIPS_REG_17 = 19, + MIPS_REG_18 = 20, + MIPS_REG_19 = 21, + MIPS_REG_20 = 22, + MIPS_REG_21 = 23, + MIPS_REG_22 = 24, + MIPS_REG_23 = 25, + MIPS_REG_24 = 26, + MIPS_REG_25 = 27, + MIPS_REG_26 = 28, + MIPS_REG_27 = 29, + MIPS_REG_28 = 30, + MIPS_REG_29 = 31, + MIPS_REG_30 = 32, + MIPS_REG_31 = 33, + +// DSP registers + MIPS_REG_DSPCCOND = 34, + MIPS_REG_DSPCARRY = 35, + MIPS_REG_DSPEFI = 36, + MIPS_REG_DSPOUTFLAG = 37, + MIPS_REG_DSPOUTFLAG16_19 = 38, + MIPS_REG_DSPOUTFLAG20 = 39, + MIPS_REG_DSPOUTFLAG21 = 40, + MIPS_REG_DSPOUTFLAG22 = 41, + MIPS_REG_DSPOUTFLAG23 = 42, + MIPS_REG_DSPPOS = 43, + MIPS_REG_DSPSCOUNT = 44, + +// ACC registers + MIPS_REG_AC0 = 45, + MIPS_REG_AC1 = 46, + MIPS_REG_AC2 = 47, + MIPS_REG_AC3 = 48, + +// COP registers + MIPS_REG_CC0 = 49, + MIPS_REG_CC1 = 50, + MIPS_REG_CC2 = 51, + MIPS_REG_CC3 = 52, + MIPS_REG_CC4 = 53, + MIPS_REG_CC5 = 54, + MIPS_REG_CC6 = 55, + MIPS_REG_CC7 = 56, + +// FPU registers + MIPS_REG_F0 = 57, + MIPS_REG_F1 = 58, + MIPS_REG_F2 = 59, + MIPS_REG_F3 = 60, + MIPS_REG_F4 = 61, + MIPS_REG_F5 = 62, + MIPS_REG_F6 = 63, + MIPS_REG_F7 = 64, + MIPS_REG_F8 = 65, + MIPS_REG_F9 = 66, + MIPS_REG_F10 = 67, + MIPS_REG_F11 = 68, + MIPS_REG_F12 = 69, + MIPS_REG_F13 = 70, + MIPS_REG_F14 = 71, + MIPS_REG_F15 = 72, + MIPS_REG_F16 = 73, + MIPS_REG_F17 = 74, + MIPS_REG_F18 = 75, + MIPS_REG_F19 = 76, + MIPS_REG_F20 = 77, + MIPS_REG_F21 = 78, + MIPS_REG_F22 = 79, + MIPS_REG_F23 = 80, + MIPS_REG_F24 = 81, + MIPS_REG_F25 = 82, + MIPS_REG_F26 = 83, + MIPS_REG_F27 = 84, + MIPS_REG_F28 = 85, + MIPS_REG_F29 = 86, + MIPS_REG_F30 = 87, + MIPS_REG_F31 = 88, + MIPS_REG_FCC0 = 89, + MIPS_REG_FCC1 = 90, + MIPS_REG_FCC2 = 91, + MIPS_REG_FCC3 = 92, + MIPS_REG_FCC4 = 93, + MIPS_REG_FCC5 = 94, + MIPS_REG_FCC6 = 95, + MIPS_REG_FCC7 = 96, + +// AFPR128 + MIPS_REG_W0 = 97, + MIPS_REG_W1 = 98, + MIPS_REG_W2 = 99, + MIPS_REG_W3 = 100, + MIPS_REG_W4 = 101, + MIPS_REG_W5 = 102, + MIPS_REG_W6 = 103, + MIPS_REG_W7 = 104, + MIPS_REG_W8 = 105, + MIPS_REG_W9 = 106, + MIPS_REG_W10 = 107, + MIPS_REG_W11 = 108, + MIPS_REG_W12 = 109, + MIPS_REG_W13 = 110, + MIPS_REG_W14 = 111, + MIPS_REG_W15 = 112, + MIPS_REG_W16 = 113, + MIPS_REG_W17 = 114, + MIPS_REG_W18 = 115, + MIPS_REG_W19 = 116, + MIPS_REG_W20 = 117, + MIPS_REG_W21 = 118, + MIPS_REG_W22 = 119, + MIPS_REG_W23 = 120, + MIPS_REG_W24 = 121, + MIPS_REG_W25 = 122, + MIPS_REG_W26 = 123, + MIPS_REG_W27 = 124, + MIPS_REG_W28 = 125, + MIPS_REG_W29 = 126, + MIPS_REG_W30 = 127, + MIPS_REG_W31 = 128, + MIPS_REG_HI = 129, + MIPS_REG_LO = 130, + MIPS_REG_P0 = 131, + MIPS_REG_P1 = 132, + MIPS_REG_P2 = 133, + MIPS_REG_MPL0 = 134, + MIPS_REG_MPL1 = 135, + MIPS_REG_MPL2 = 136, + MIPS_REG_CP0_CONFIG3 = 137, + MIPS_REG_CP0_USERLOCAL = 138, + MIPS_REG_CP0_STATUS = 139, + MIPS_REG_ENDING = 140, + MIPS_REG_ZERO = 2, + MIPS_REG_AT = 3, + MIPS_REG_V0 = 4, + MIPS_REG_V1 = 5, + MIPS_REG_A0 = 6, + MIPS_REG_A1 = 7, + MIPS_REG_A2 = 8, + MIPS_REG_A3 = 9, + MIPS_REG_T0 = 10, + MIPS_REG_T1 = 11, + MIPS_REG_T2 = 12, + MIPS_REG_T3 = 13, + MIPS_REG_T4 = 14, + MIPS_REG_T5 = 15, + MIPS_REG_T6 = 16, + MIPS_REG_T7 = 17, + MIPS_REG_S0 = 18, + MIPS_REG_S1 = 19, + MIPS_REG_S2 = 20, + MIPS_REG_S3 = 21, + MIPS_REG_S4 = 22, + MIPS_REG_S5 = 23, + MIPS_REG_S6 = 24, + MIPS_REG_S7 = 25, + MIPS_REG_T8 = 26, + MIPS_REG_T9 = 27, + MIPS_REG_K0 = 28, + MIPS_REG_K1 = 29, + MIPS_REG_GP = 30, + MIPS_REG_SP = 31, + MIPS_REG_FP = 32, + MIPS_REG_S8 = 32, + MIPS_REG_RA = 33, + MIPS_REG_HI0 = 45, + MIPS_REG_HI1 = 46, + MIPS_REG_HI2 = 47, + MIPS_REG_HI3 = 48, + MIPS_REG_LO0 = 45, + MIPS_REG_LO1 = 46, + MIPS_REG_LO2 = 47, + MIPS_REG_LO3 = 48, + +}; diff --git a/bindings/zig/unicorn/ppc_const.zig b/bindings/zig/unicorn/ppc_const.zig new file mode 100644 index 00000000..9a4dd61a --- /dev/null +++ b/bindings/zig/unicorn/ppc_const.zig @@ -0,0 +1,408 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const ppcConst = enum(c_int) { + +// PPC CPU + + CPU_PPC32_401 = 0, + CPU_PPC32_401A1 = 1, + CPU_PPC32_401B2 = 2, + CPU_PPC32_401C2 = 3, + CPU_PPC32_401D2 = 4, + CPU_PPC32_401E2 = 5, + CPU_PPC32_401F2 = 6, + CPU_PPC32_401G2 = 7, + CPU_PPC32_IOP480 = 8, + CPU_PPC32_COBRA = 9, + CPU_PPC32_403GA = 10, + CPU_PPC32_403GB = 11, + CPU_PPC32_403GC = 12, + CPU_PPC32_403GCX = 13, + CPU_PPC32_405D2 = 14, + CPU_PPC32_405D4 = 15, + CPU_PPC32_405CRA = 16, + CPU_PPC32_405CRB = 17, + CPU_PPC32_405CRC = 18, + CPU_PPC32_405EP = 19, + CPU_PPC32_405EZ = 20, + CPU_PPC32_405GPA = 21, + CPU_PPC32_405GPB = 22, + CPU_PPC32_405GPC = 23, + CPU_PPC32_405GPD = 24, + CPU_PPC32_405GPR = 25, + CPU_PPC32_405LP = 26, + CPU_PPC32_NPE405H = 27, + CPU_PPC32_NPE405H2 = 28, + CPU_PPC32_NPE405L = 29, + CPU_PPC32_NPE4GS3 = 30, + CPU_PPC32_STB03 = 31, + CPU_PPC32_STB04 = 32, + CPU_PPC32_STB25 = 33, + CPU_PPC32_X2VP4 = 34, + CPU_PPC32_X2VP20 = 35, + CPU_PPC32_440_XILINX = 36, + CPU_PPC32_440_XILINX_W_DFPU = 37, + CPU_PPC32_440EPA = 38, + CPU_PPC32_440EPB = 39, + CPU_PPC32_440EPX = 40, + CPU_PPC32_460EXB = 41, + CPU_PPC32_G2 = 42, + CPU_PPC32_G2H4 = 43, + CPU_PPC32_G2GP = 44, + CPU_PPC32_G2LS = 45, + CPU_PPC32_G2HIP3 = 46, + CPU_PPC32_G2HIP4 = 47, + CPU_PPC32_MPC603 = 48, + CPU_PPC32_G2LE = 49, + CPU_PPC32_G2LEGP = 50, + CPU_PPC32_G2LELS = 51, + CPU_PPC32_G2LEGP1 = 52, + CPU_PPC32_G2LEGP3 = 53, + CPU_PPC32_MPC5200_V10 = 54, + CPU_PPC32_MPC5200_V11 = 55, + CPU_PPC32_MPC5200_V12 = 56, + CPU_PPC32_MPC5200B_V20 = 57, + CPU_PPC32_MPC5200B_V21 = 58, + CPU_PPC32_E200Z5 = 59, + CPU_PPC32_E200Z6 = 60, + CPU_PPC32_E300C1 = 61, + CPU_PPC32_E300C2 = 62, + CPU_PPC32_E300C3 = 63, + CPU_PPC32_E300C4 = 64, + CPU_PPC32_MPC8343 = 65, + CPU_PPC32_MPC8343A = 66, + CPU_PPC32_MPC8343E = 67, + CPU_PPC32_MPC8343EA = 68, + CPU_PPC32_MPC8347T = 69, + CPU_PPC32_MPC8347P = 70, + CPU_PPC32_MPC8347AT = 71, + CPU_PPC32_MPC8347AP = 72, + CPU_PPC32_MPC8347ET = 73, + CPU_PPC32_MPC8347EP = 74, + CPU_PPC32_MPC8347EAT = 75, + CPU_PPC32_MPC8347EAP = 76, + CPU_PPC32_MPC8349 = 77, + CPU_PPC32_MPC8349A = 78, + CPU_PPC32_MPC8349E = 79, + CPU_PPC32_MPC8349EA = 80, + CPU_PPC32_MPC8377 = 81, + CPU_PPC32_MPC8377E = 82, + CPU_PPC32_MPC8378 = 83, + CPU_PPC32_MPC8378E = 84, + CPU_PPC32_MPC8379 = 85, + CPU_PPC32_MPC8379E = 86, + CPU_PPC32_E500_V10 = 87, + CPU_PPC32_E500_V20 = 88, + CPU_PPC32_E500V2_V10 = 89, + CPU_PPC32_E500V2_V20 = 90, + CPU_PPC32_E500V2_V21 = 91, + CPU_PPC32_E500V2_V22 = 92, + CPU_PPC32_E500V2_V30 = 93, + CPU_PPC32_E500MC = 94, + CPU_PPC32_MPC8533_V10 = 95, + CPU_PPC32_MPC8533_V11 = 96, + CPU_PPC32_MPC8533E_V10 = 97, + CPU_PPC32_MPC8533E_V11 = 98, + CPU_PPC32_MPC8540_V10 = 99, + CPU_PPC32_MPC8540_V20 = 100, + CPU_PPC32_MPC8540_V21 = 101, + CPU_PPC32_MPC8541_V10 = 102, + CPU_PPC32_MPC8541_V11 = 103, + CPU_PPC32_MPC8541E_V10 = 104, + CPU_PPC32_MPC8541E_V11 = 105, + CPU_PPC32_MPC8543_V10 = 106, + CPU_PPC32_MPC8543_V11 = 107, + CPU_PPC32_MPC8543_V20 = 108, + CPU_PPC32_MPC8543_V21 = 109, + CPU_PPC32_MPC8543E_V10 = 110, + CPU_PPC32_MPC8543E_V11 = 111, + CPU_PPC32_MPC8543E_V20 = 112, + CPU_PPC32_MPC8543E_V21 = 113, + CPU_PPC32_MPC8544_V10 = 114, + CPU_PPC32_MPC8544_V11 = 115, + CPU_PPC32_MPC8544E_V10 = 116, + CPU_PPC32_MPC8544E_V11 = 117, + CPU_PPC32_MPC8545_V20 = 118, + CPU_PPC32_MPC8545_V21 = 119, + CPU_PPC32_MPC8545E_V20 = 120, + CPU_PPC32_MPC8545E_V21 = 121, + CPU_PPC32_MPC8547E_V20 = 122, + CPU_PPC32_MPC8547E_V21 = 123, + CPU_PPC32_MPC8548_V10 = 124, + CPU_PPC32_MPC8548_V11 = 125, + CPU_PPC32_MPC8548_V20 = 126, + CPU_PPC32_MPC8548_V21 = 127, + CPU_PPC32_MPC8548E_V10 = 128, + CPU_PPC32_MPC8548E_V11 = 129, + CPU_PPC32_MPC8548E_V20 = 130, + CPU_PPC32_MPC8548E_V21 = 131, + CPU_PPC32_MPC8555_V10 = 132, + CPU_PPC32_MPC8555_V11 = 133, + CPU_PPC32_MPC8555E_V10 = 134, + CPU_PPC32_MPC8555E_V11 = 135, + CPU_PPC32_MPC8560_V10 = 136, + CPU_PPC32_MPC8560_V20 = 137, + CPU_PPC32_MPC8560_V21 = 138, + CPU_PPC32_MPC8567 = 139, + CPU_PPC32_MPC8567E = 140, + CPU_PPC32_MPC8568 = 141, + CPU_PPC32_MPC8568E = 142, + CPU_PPC32_MPC8572 = 143, + CPU_PPC32_MPC8572E = 144, + CPU_PPC32_E600 = 145, + CPU_PPC32_MPC8610 = 146, + CPU_PPC32_MPC8641 = 147, + CPU_PPC32_MPC8641D = 148, + CPU_PPC32_601_V0 = 149, + CPU_PPC32_601_V1 = 150, + CPU_PPC32_601_V2 = 151, + CPU_PPC32_602 = 152, + CPU_PPC32_603 = 153, + CPU_PPC32_603E_V1_1 = 154, + CPU_PPC32_603E_V1_2 = 155, + CPU_PPC32_603E_V1_3 = 156, + CPU_PPC32_603E_V1_4 = 157, + CPU_PPC32_603E_V2_2 = 158, + CPU_PPC32_603E_V3 = 159, + CPU_PPC32_603E_V4 = 160, + CPU_PPC32_603E_V4_1 = 161, + CPU_PPC32_603E7 = 162, + CPU_PPC32_603E7T = 163, + CPU_PPC32_603E7V = 164, + CPU_PPC32_603E7V1 = 165, + CPU_PPC32_603E7V2 = 166, + CPU_PPC32_603P = 167, + CPU_PPC32_604 = 168, + CPU_PPC32_604E_V1_0 = 169, + CPU_PPC32_604E_V2_2 = 170, + CPU_PPC32_604E_V2_4 = 171, + CPU_PPC32_604R = 172, + CPU_PPC32_740_V1_0 = 173, + CPU_PPC32_750_V1_0 = 174, + CPU_PPC32_740_V2_0 = 175, + CPU_PPC32_750_V2_0 = 176, + CPU_PPC32_740_V2_1 = 177, + CPU_PPC32_750_V2_1 = 178, + CPU_PPC32_740_V2_2 = 179, + CPU_PPC32_750_V2_2 = 180, + CPU_PPC32_740_V3_0 = 181, + CPU_PPC32_750_V3_0 = 182, + CPU_PPC32_740_V3_1 = 183, + CPU_PPC32_750_V3_1 = 184, + CPU_PPC32_740E = 185, + CPU_PPC32_750E = 186, + CPU_PPC32_740P = 187, + CPU_PPC32_750P = 188, + CPU_PPC32_750CL_V1_0 = 189, + CPU_PPC32_750CL_V2_0 = 190, + CPU_PPC32_750CX_V1_0 = 191, + CPU_PPC32_750CX_V2_0 = 192, + CPU_PPC32_750CX_V2_1 = 193, + CPU_PPC32_750CX_V2_2 = 194, + CPU_PPC32_750CXE_V2_1 = 195, + CPU_PPC32_750CXE_V2_2 = 196, + CPU_PPC32_750CXE_V2_3 = 197, + CPU_PPC32_750CXE_V2_4 = 198, + CPU_PPC32_750CXE_V2_4B = 199, + CPU_PPC32_750CXE_V3_0 = 200, + CPU_PPC32_750CXE_V3_1 = 201, + CPU_PPC32_750CXE_V3_1B = 202, + CPU_PPC32_750CXR = 203, + CPU_PPC32_750FL = 204, + CPU_PPC32_750FX_V1_0 = 205, + CPU_PPC32_750FX_V2_0 = 206, + CPU_PPC32_750FX_V2_1 = 207, + CPU_PPC32_750FX_V2_2 = 208, + CPU_PPC32_750FX_V2_3 = 209, + CPU_PPC32_750GL = 210, + CPU_PPC32_750GX_V1_0 = 211, + CPU_PPC32_750GX_V1_1 = 212, + CPU_PPC32_750GX_V1_2 = 213, + CPU_PPC32_750L_V2_0 = 214, + CPU_PPC32_750L_V2_1 = 215, + CPU_PPC32_750L_V2_2 = 216, + CPU_PPC32_750L_V3_0 = 217, + CPU_PPC32_750L_V3_2 = 218, + CPU_PPC32_745_V1_0 = 219, + CPU_PPC32_755_V1_0 = 220, + CPU_PPC32_745_V1_1 = 221, + CPU_PPC32_755_V1_1 = 222, + CPU_PPC32_745_V2_0 = 223, + CPU_PPC32_755_V2_0 = 224, + CPU_PPC32_745_V2_1 = 225, + CPU_PPC32_755_V2_1 = 226, + CPU_PPC32_745_V2_2 = 227, + CPU_PPC32_755_V2_2 = 228, + CPU_PPC32_745_V2_3 = 229, + CPU_PPC32_755_V2_3 = 230, + CPU_PPC32_745_V2_4 = 231, + CPU_PPC32_755_V2_4 = 232, + CPU_PPC32_745_V2_5 = 233, + CPU_PPC32_755_V2_5 = 234, + CPU_PPC32_745_V2_6 = 235, + CPU_PPC32_755_V2_6 = 236, + CPU_PPC32_745_V2_7 = 237, + CPU_PPC32_755_V2_7 = 238, + CPU_PPC32_745_V2_8 = 239, + CPU_PPC32_755_V2_8 = 240, + CPU_PPC32_7400_V1_0 = 241, + CPU_PPC32_7400_V1_1 = 242, + CPU_PPC32_7400_V2_0 = 243, + CPU_PPC32_7400_V2_1 = 244, + CPU_PPC32_7400_V2_2 = 245, + CPU_PPC32_7400_V2_6 = 246, + CPU_PPC32_7400_V2_7 = 247, + CPU_PPC32_7400_V2_8 = 248, + CPU_PPC32_7400_V2_9 = 249, + CPU_PPC32_7410_V1_0 = 250, + CPU_PPC32_7410_V1_1 = 251, + CPU_PPC32_7410_V1_2 = 252, + CPU_PPC32_7410_V1_3 = 253, + CPU_PPC32_7410_V1_4 = 254, + CPU_PPC32_7448_V1_0 = 255, + CPU_PPC32_7448_V1_1 = 256, + CPU_PPC32_7448_V2_0 = 257, + CPU_PPC32_7448_V2_1 = 258, + CPU_PPC32_7450_V1_0 = 259, + CPU_PPC32_7450_V1_1 = 260, + CPU_PPC32_7450_V1_2 = 261, + CPU_PPC32_7450_V2_0 = 262, + CPU_PPC32_7450_V2_1 = 263, + CPU_PPC32_7441_V2_1 = 264, + CPU_PPC32_7441_V2_3 = 265, + CPU_PPC32_7451_V2_3 = 266, + CPU_PPC32_7441_V2_10 = 267, + CPU_PPC32_7451_V2_10 = 268, + CPU_PPC32_7445_V1_0 = 269, + CPU_PPC32_7455_V1_0 = 270, + CPU_PPC32_7445_V2_1 = 271, + CPU_PPC32_7455_V2_1 = 272, + CPU_PPC32_7445_V3_2 = 273, + CPU_PPC32_7455_V3_2 = 274, + CPU_PPC32_7445_V3_3 = 275, + CPU_PPC32_7455_V3_3 = 276, + CPU_PPC32_7445_V3_4 = 277, + CPU_PPC32_7455_V3_4 = 278, + CPU_PPC32_7447_V1_0 = 279, + CPU_PPC32_7457_V1_0 = 280, + CPU_PPC32_7447_V1_1 = 281, + CPU_PPC32_7457_V1_1 = 282, + CPU_PPC32_7457_V1_2 = 283, + CPU_PPC32_7447A_V1_0 = 284, + CPU_PPC32_7457A_V1_0 = 285, + CPU_PPC32_7447A_V1_1 = 286, + CPU_PPC32_7457A_V1_1 = 287, + CPU_PPC32_7447A_V1_2 = 288, + CPU_PPC32_7457A_V1_2 = 289, + CPU_PPC32_ENDING = 290, + +// PPC64 CPU + + CPU_PPC64_E5500 = 0, + CPU_PPC64_E6500 = 1, + CPU_PPC64_970_V2_2 = 2, + CPU_PPC64_970FX_V1_0 = 3, + CPU_PPC64_970FX_V2_0 = 4, + CPU_PPC64_970FX_V2_1 = 5, + CPU_PPC64_970FX_V3_0 = 6, + CPU_PPC64_970FX_V3_1 = 7, + CPU_PPC64_970MP_V1_0 = 8, + CPU_PPC64_970MP_V1_1 = 9, + CPU_PPC64_POWER5_V2_1 = 10, + CPU_PPC64_POWER7_V2_3 = 11, + CPU_PPC64_POWER7_V2_1 = 12, + CPU_PPC64_POWER8E_V2_1 = 13, + CPU_PPC64_POWER8_V2_0 = 14, + CPU_PPC64_POWER8NVL_V1_0 = 15, + CPU_PPC64_POWER9_V1_0 = 16, + CPU_PPC64_POWER9_V2_0 = 17, + CPU_PPC64_POWER10_V1_0 = 18, + CPU_PPC64_ENDING = 19, + +// PPC registers + + PPC_REG_INVALID = 0, + +// General purpose registers + PPC_REG_PC = 1, + PPC_REG_0 = 2, + PPC_REG_1 = 3, + PPC_REG_2 = 4, + PPC_REG_3 = 5, + PPC_REG_4 = 6, + PPC_REG_5 = 7, + PPC_REG_6 = 8, + PPC_REG_7 = 9, + PPC_REG_8 = 10, + PPC_REG_9 = 11, + PPC_REG_10 = 12, + PPC_REG_11 = 13, + PPC_REG_12 = 14, + PPC_REG_13 = 15, + PPC_REG_14 = 16, + PPC_REG_15 = 17, + PPC_REG_16 = 18, + PPC_REG_17 = 19, + PPC_REG_18 = 20, + PPC_REG_19 = 21, + PPC_REG_20 = 22, + PPC_REG_21 = 23, + PPC_REG_22 = 24, + PPC_REG_23 = 25, + PPC_REG_24 = 26, + PPC_REG_25 = 27, + PPC_REG_26 = 28, + PPC_REG_27 = 29, + PPC_REG_28 = 30, + PPC_REG_29 = 31, + PPC_REG_30 = 32, + PPC_REG_31 = 33, + PPC_REG_CR0 = 34, + PPC_REG_CR1 = 35, + PPC_REG_CR2 = 36, + PPC_REG_CR3 = 37, + PPC_REG_CR4 = 38, + PPC_REG_CR5 = 39, + PPC_REG_CR6 = 40, + PPC_REG_CR7 = 41, + PPC_REG_FPR0 = 42, + PPC_REG_FPR1 = 43, + PPC_REG_FPR2 = 44, + PPC_REG_FPR3 = 45, + PPC_REG_FPR4 = 46, + PPC_REG_FPR5 = 47, + PPC_REG_FPR6 = 48, + PPC_REG_FPR7 = 49, + PPC_REG_FPR8 = 50, + PPC_REG_FPR9 = 51, + PPC_REG_FPR10 = 52, + PPC_REG_FPR11 = 53, + PPC_REG_FPR12 = 54, + PPC_REG_FPR13 = 55, + PPC_REG_FPR14 = 56, + PPC_REG_FPR15 = 57, + PPC_REG_FPR16 = 58, + PPC_REG_FPR17 = 59, + PPC_REG_FPR18 = 60, + PPC_REG_FPR19 = 61, + PPC_REG_FPR20 = 62, + PPC_REG_FPR21 = 63, + PPC_REG_FPR22 = 64, + PPC_REG_FPR23 = 65, + PPC_REG_FPR24 = 66, + PPC_REG_FPR25 = 67, + PPC_REG_FPR26 = 68, + PPC_REG_FPR27 = 69, + PPC_REG_FPR28 = 70, + PPC_REG_FPR29 = 71, + PPC_REG_FPR30 = 72, + PPC_REG_FPR31 = 73, + PPC_REG_LR = 74, + PPC_REG_XER = 75, + PPC_REG_CTR = 76, + PPC_REG_MSR = 77, + PPC_REG_FPSCR = 78, + PPC_REG_CR = 79, + PPC_REG_ENDING = 80, + +}; diff --git a/bindings/zig/unicorn/riscv_const.zig b/bindings/zig/unicorn/riscv_const.zig new file mode 100644 index 00000000..3e713449 --- /dev/null +++ b/bindings/zig/unicorn/riscv_const.zig @@ -0,0 +1,289 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const riscvConst = enum(c_int) { + +// RISCV32 CPU + + CPU_RISCV32_ANY = 0, + CPU_RISCV32_BASE32 = 1, + CPU_RISCV32_SIFIVE_E31 = 2, + CPU_RISCV32_SIFIVE_U34 = 3, + CPU_RISCV32_ENDING = 4, + +// RISCV64 CPU + + CPU_RISCV64_ANY = 0, + CPU_RISCV64_BASE64 = 1, + CPU_RISCV64_SIFIVE_E51 = 2, + CPU_RISCV64_SIFIVE_U54 = 3, + CPU_RISCV64_ENDING = 4, + +// RISCV registers + + RISCV_REG_INVALID = 0, + +// General purpose registers + RISCV_REG_X0 = 1, + RISCV_REG_X1 = 2, + RISCV_REG_X2 = 3, + RISCV_REG_X3 = 4, + RISCV_REG_X4 = 5, + RISCV_REG_X5 = 6, + RISCV_REG_X6 = 7, + RISCV_REG_X7 = 8, + RISCV_REG_X8 = 9, + RISCV_REG_X9 = 10, + RISCV_REG_X10 = 11, + RISCV_REG_X11 = 12, + RISCV_REG_X12 = 13, + RISCV_REG_X13 = 14, + RISCV_REG_X14 = 15, + RISCV_REG_X15 = 16, + RISCV_REG_X16 = 17, + RISCV_REG_X17 = 18, + RISCV_REG_X18 = 19, + RISCV_REG_X19 = 20, + RISCV_REG_X20 = 21, + RISCV_REG_X21 = 22, + RISCV_REG_X22 = 23, + RISCV_REG_X23 = 24, + RISCV_REG_X24 = 25, + RISCV_REG_X25 = 26, + RISCV_REG_X26 = 27, + RISCV_REG_X27 = 28, + RISCV_REG_X28 = 29, + RISCV_REG_X29 = 30, + RISCV_REG_X30 = 31, + RISCV_REG_X31 = 32, + +// RISCV CSR + RISCV_REG_USTATUS = 33, + RISCV_REG_UIE = 34, + RISCV_REG_UTVEC = 35, + RISCV_REG_USCRATCH = 36, + RISCV_REG_UEPC = 37, + RISCV_REG_UCAUSE = 38, + RISCV_REG_UTVAL = 39, + RISCV_REG_UIP = 40, + RISCV_REG_FFLAGS = 41, + RISCV_REG_FRM = 42, + RISCV_REG_FCSR = 43, + RISCV_REG_CYCLE = 44, + RISCV_REG_TIME = 45, + RISCV_REG_INSTRET = 46, + RISCV_REG_HPMCOUNTER3 = 47, + RISCV_REG_HPMCOUNTER4 = 48, + RISCV_REG_HPMCOUNTER5 = 49, + RISCV_REG_HPMCOUNTER6 = 50, + RISCV_REG_HPMCOUNTER7 = 51, + RISCV_REG_HPMCOUNTER8 = 52, + RISCV_REG_HPMCOUNTER9 = 53, + RISCV_REG_HPMCOUNTER10 = 54, + RISCV_REG_HPMCOUNTER11 = 55, + RISCV_REG_HPMCOUNTER12 = 56, + RISCV_REG_HPMCOUNTER13 = 57, + RISCV_REG_HPMCOUNTER14 = 58, + RISCV_REG_HPMCOUNTER15 = 59, + RISCV_REG_HPMCOUNTER16 = 60, + RISCV_REG_HPMCOUNTER17 = 61, + RISCV_REG_HPMCOUNTER18 = 62, + RISCV_REG_HPMCOUNTER19 = 63, + RISCV_REG_HPMCOUNTER20 = 64, + RISCV_REG_HPMCOUNTER21 = 65, + RISCV_REG_HPMCOUNTER22 = 66, + RISCV_REG_HPMCOUNTER23 = 67, + RISCV_REG_HPMCOUNTER24 = 68, + RISCV_REG_HPMCOUNTER25 = 69, + RISCV_REG_HPMCOUNTER26 = 70, + RISCV_REG_HPMCOUNTER27 = 71, + RISCV_REG_HPMCOUNTER28 = 72, + RISCV_REG_HPMCOUNTER29 = 73, + RISCV_REG_HPMCOUNTER30 = 74, + RISCV_REG_HPMCOUNTER31 = 75, + RISCV_REG_CYCLEH = 76, + RISCV_REG_TIMEH = 77, + RISCV_REG_INSTRETH = 78, + RISCV_REG_HPMCOUNTER3H = 79, + RISCV_REG_HPMCOUNTER4H = 80, + RISCV_REG_HPMCOUNTER5H = 81, + RISCV_REG_HPMCOUNTER6H = 82, + RISCV_REG_HPMCOUNTER7H = 83, + RISCV_REG_HPMCOUNTER8H = 84, + RISCV_REG_HPMCOUNTER9H = 85, + RISCV_REG_HPMCOUNTER10H = 86, + RISCV_REG_HPMCOUNTER11H = 87, + RISCV_REG_HPMCOUNTER12H = 88, + RISCV_REG_HPMCOUNTER13H = 89, + RISCV_REG_HPMCOUNTER14H = 90, + RISCV_REG_HPMCOUNTER15H = 91, + RISCV_REG_HPMCOUNTER16H = 92, + RISCV_REG_HPMCOUNTER17H = 93, + RISCV_REG_HPMCOUNTER18H = 94, + RISCV_REG_HPMCOUNTER19H = 95, + RISCV_REG_HPMCOUNTER20H = 96, + RISCV_REG_HPMCOUNTER21H = 97, + RISCV_REG_HPMCOUNTER22H = 98, + RISCV_REG_HPMCOUNTER23H = 99, + RISCV_REG_HPMCOUNTER24H = 100, + RISCV_REG_HPMCOUNTER25H = 101, + RISCV_REG_HPMCOUNTER26H = 102, + RISCV_REG_HPMCOUNTER27H = 103, + RISCV_REG_HPMCOUNTER28H = 104, + RISCV_REG_HPMCOUNTER29H = 105, + RISCV_REG_HPMCOUNTER30H = 106, + RISCV_REG_HPMCOUNTER31H = 107, + RISCV_REG_MCYCLE = 108, + RISCV_REG_MINSTRET = 109, + RISCV_REG_MCYCLEH = 110, + RISCV_REG_MINSTRETH = 111, + RISCV_REG_MVENDORID = 112, + RISCV_REG_MARCHID = 113, + RISCV_REG_MIMPID = 114, + RISCV_REG_MHARTID = 115, + RISCV_REG_MSTATUS = 116, + RISCV_REG_MISA = 117, + RISCV_REG_MEDELEG = 118, + RISCV_REG_MIDELEG = 119, + RISCV_REG_MIE = 120, + RISCV_REG_MTVEC = 121, + RISCV_REG_MCOUNTEREN = 122, + RISCV_REG_MSTATUSH = 123, + RISCV_REG_MUCOUNTEREN = 124, + RISCV_REG_MSCOUNTEREN = 125, + RISCV_REG_MHCOUNTEREN = 126, + RISCV_REG_MSCRATCH = 127, + RISCV_REG_MEPC = 128, + RISCV_REG_MCAUSE = 129, + RISCV_REG_MTVAL = 130, + RISCV_REG_MIP = 131, + RISCV_REG_MBADADDR = 132, + RISCV_REG_SSTATUS = 133, + RISCV_REG_SEDELEG = 134, + RISCV_REG_SIDELEG = 135, + RISCV_REG_SIE = 136, + RISCV_REG_STVEC = 137, + RISCV_REG_SCOUNTEREN = 138, + RISCV_REG_SSCRATCH = 139, + RISCV_REG_SEPC = 140, + RISCV_REG_SCAUSE = 141, + RISCV_REG_STVAL = 142, + RISCV_REG_SIP = 143, + RISCV_REG_SBADADDR = 144, + RISCV_REG_SPTBR = 145, + RISCV_REG_SATP = 146, + RISCV_REG_HSTATUS = 147, + RISCV_REG_HEDELEG = 148, + RISCV_REG_HIDELEG = 149, + RISCV_REG_HIE = 150, + RISCV_REG_HCOUNTEREN = 151, + RISCV_REG_HTVAL = 152, + RISCV_REG_HIP = 153, + RISCV_REG_HTINST = 154, + RISCV_REG_HGATP = 155, + RISCV_REG_HTIMEDELTA = 156, + RISCV_REG_HTIMEDELTAH = 157, + +// Floating-point registers + RISCV_REG_F0 = 158, + RISCV_REG_F1 = 159, + RISCV_REG_F2 = 160, + RISCV_REG_F3 = 161, + RISCV_REG_F4 = 162, + RISCV_REG_F5 = 163, + RISCV_REG_F6 = 164, + RISCV_REG_F7 = 165, + RISCV_REG_F8 = 166, + RISCV_REG_F9 = 167, + RISCV_REG_F10 = 168, + RISCV_REG_F11 = 169, + RISCV_REG_F12 = 170, + RISCV_REG_F13 = 171, + RISCV_REG_F14 = 172, + RISCV_REG_F15 = 173, + RISCV_REG_F16 = 174, + RISCV_REG_F17 = 175, + RISCV_REG_F18 = 176, + RISCV_REG_F19 = 177, + RISCV_REG_F20 = 178, + RISCV_REG_F21 = 179, + RISCV_REG_F22 = 180, + RISCV_REG_F23 = 181, + RISCV_REG_F24 = 182, + RISCV_REG_F25 = 183, + RISCV_REG_F26 = 184, + RISCV_REG_F27 = 185, + RISCV_REG_F28 = 186, + RISCV_REG_F29 = 187, + RISCV_REG_F30 = 188, + RISCV_REG_F31 = 189, + RISCV_REG_PC = 190, + RISCV_REG_ENDING = 191, + +// Alias registers + RISCV_REG_ZERO = 1, + RISCV_REG_RA = 2, + RISCV_REG_SP = 3, + RISCV_REG_GP = 4, + RISCV_REG_TP = 5, + RISCV_REG_T0 = 6, + RISCV_REG_T1 = 7, + RISCV_REG_T2 = 8, + RISCV_REG_S0 = 9, + RISCV_REG_FP = 9, + RISCV_REG_S1 = 10, + RISCV_REG_A0 = 11, + RISCV_REG_A1 = 12, + RISCV_REG_A2 = 13, + RISCV_REG_A3 = 14, + RISCV_REG_A4 = 15, + RISCV_REG_A5 = 16, + RISCV_REG_A6 = 17, + RISCV_REG_A7 = 18, + RISCV_REG_S2 = 19, + RISCV_REG_S3 = 20, + RISCV_REG_S4 = 21, + RISCV_REG_S5 = 22, + RISCV_REG_S6 = 23, + RISCV_REG_S7 = 24, + RISCV_REG_S8 = 25, + RISCV_REG_S9 = 26, + RISCV_REG_S10 = 27, + RISCV_REG_S11 = 28, + RISCV_REG_T3 = 29, + RISCV_REG_T4 = 30, + RISCV_REG_T5 = 31, + RISCV_REG_T6 = 32, + RISCV_REG_FT0 = 158, + RISCV_REG_FT1 = 159, + RISCV_REG_FT2 = 160, + RISCV_REG_FT3 = 161, + RISCV_REG_FT4 = 162, + RISCV_REG_FT5 = 163, + RISCV_REG_FT6 = 164, + RISCV_REG_FT7 = 165, + RISCV_REG_FS0 = 166, + RISCV_REG_FS1 = 167, + RISCV_REG_FA0 = 168, + RISCV_REG_FA1 = 169, + RISCV_REG_FA2 = 170, + RISCV_REG_FA3 = 171, + RISCV_REG_FA4 = 172, + RISCV_REG_FA5 = 173, + RISCV_REG_FA6 = 174, + RISCV_REG_FA7 = 175, + RISCV_REG_FS2 = 176, + RISCV_REG_FS3 = 177, + RISCV_REG_FS4 = 178, + RISCV_REG_FS5 = 179, + RISCV_REG_FS6 = 180, + RISCV_REG_FS7 = 181, + RISCV_REG_FS8 = 182, + RISCV_REG_FS9 = 183, + RISCV_REG_FS10 = 184, + RISCV_REG_FS11 = 185, + RISCV_REG_FT8 = 186, + RISCV_REG_FT9 = 187, + RISCV_REG_FT10 = 188, + RISCV_REG_FT11 = 189, + +}; diff --git a/bindings/zig/unicorn/s390x_const.zig b/bindings/zig/unicorn/s390x_const.zig new file mode 100644 index 00000000..9b1908b1 --- /dev/null +++ b/bindings/zig/unicorn/s390x_const.zig @@ -0,0 +1,126 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const s390xConst = enum(c_int) { + +// S390X CPU + + CPU_S390X_Z900 = 0, + CPU_S390X_Z900_2 = 1, + CPU_S390X_Z900_3 = 2, + CPU_S390X_Z800 = 3, + CPU_S390X_Z990 = 4, + CPU_S390X_Z990_2 = 5, + CPU_S390X_Z990_3 = 6, + CPU_S390X_Z890 = 7, + CPU_S390X_Z990_4 = 8, + CPU_S390X_Z890_2 = 9, + CPU_S390X_Z990_5 = 10, + CPU_S390X_Z890_3 = 11, + CPU_S390X_Z9EC = 12, + CPU_S390X_Z9EC_2 = 13, + CPU_S390X_Z9BC = 14, + CPU_S390X_Z9EC_3 = 15, + CPU_S390X_Z9BC_2 = 16, + CPU_S390X_Z10EC = 17, + CPU_S390X_Z10EC_2 = 18, + CPU_S390X_Z10BC = 19, + CPU_S390X_Z10EC_3 = 20, + CPU_S390X_Z10BC_2 = 21, + CPU_S390X_Z196 = 22, + CPU_S390X_Z196_2 = 23, + CPU_S390X_Z114 = 24, + CPU_S390X_ZEC12 = 25, + CPU_S390X_ZEC12_2 = 26, + CPU_S390X_ZBC12 = 27, + CPU_S390X_Z13 = 28, + CPU_S390X_Z13_2 = 29, + CPU_S390X_Z13S = 30, + CPU_S390X_Z14 = 31, + CPU_S390X_Z14_2 = 32, + CPU_S390X_Z14ZR1 = 33, + CPU_S390X_GEN15A = 34, + CPU_S390X_GEN15B = 35, + CPU_S390X_QEMU = 36, + CPU_S390X_MAX = 37, + CPU_S390X_ENDING = 38, + +// S390X registers + + S390X_REG_INVALID = 0, + +// General purpose registers + S390X_REG_R0 = 1, + S390X_REG_R1 = 2, + S390X_REG_R2 = 3, + S390X_REG_R3 = 4, + S390X_REG_R4 = 5, + S390X_REG_R5 = 6, + S390X_REG_R6 = 7, + S390X_REG_R7 = 8, + S390X_REG_R8 = 9, + S390X_REG_R9 = 10, + S390X_REG_R10 = 11, + S390X_REG_R11 = 12, + S390X_REG_R12 = 13, + S390X_REG_R13 = 14, + S390X_REG_R14 = 15, + S390X_REG_R15 = 16, + +// Floating point registers + S390X_REG_F0 = 17, + S390X_REG_F1 = 18, + S390X_REG_F2 = 19, + S390X_REG_F3 = 20, + S390X_REG_F4 = 21, + S390X_REG_F5 = 22, + S390X_REG_F6 = 23, + S390X_REG_F7 = 24, + S390X_REG_F8 = 25, + S390X_REG_F9 = 26, + S390X_REG_F10 = 27, + S390X_REG_F11 = 28, + S390X_REG_F12 = 29, + S390X_REG_F13 = 30, + S390X_REG_F14 = 31, + S390X_REG_F15 = 32, + S390X_REG_F16 = 33, + S390X_REG_F17 = 34, + S390X_REG_F18 = 35, + S390X_REG_F19 = 36, + S390X_REG_F20 = 37, + S390X_REG_F21 = 38, + S390X_REG_F22 = 39, + S390X_REG_F23 = 40, + S390X_REG_F24 = 41, + S390X_REG_F25 = 42, + S390X_REG_F26 = 43, + S390X_REG_F27 = 44, + S390X_REG_F28 = 45, + S390X_REG_F29 = 46, + S390X_REG_F30 = 47, + S390X_REG_F31 = 48, + +// Access registers + S390X_REG_A0 = 49, + S390X_REG_A1 = 50, + S390X_REG_A2 = 51, + S390X_REG_A3 = 52, + S390X_REG_A4 = 53, + S390X_REG_A5 = 54, + S390X_REG_A6 = 55, + S390X_REG_A7 = 56, + S390X_REG_A8 = 57, + S390X_REG_A9 = 58, + S390X_REG_A10 = 59, + S390X_REG_A11 = 60, + S390X_REG_A12 = 61, + S390X_REG_A13 = 62, + S390X_REG_A14 = 63, + S390X_REG_A15 = 64, + S390X_REG_PC = 65, + S390X_REG_PSWM = 66, + S390X_REG_ENDING = 67, + +// Alias registers + +}; diff --git a/bindings/zig/unicorn/sparc_const.zig b/bindings/zig/unicorn/sparc_const.zig new file mode 100644 index 00000000..f745e84f --- /dev/null +++ b/bindings/zig/unicorn/sparc_const.zig @@ -0,0 +1,138 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const sparcConst = enum(c_int) { + +// SPARC32 CPU + + CPU_SPARC32_FUJITSU_MB86904 = 0, + CPU_SPARC32_FUJITSU_MB86907 = 1, + CPU_SPARC32_TI_MICROSPARC_I = 2, + CPU_SPARC32_TI_MICROSPARC_II = 3, + CPU_SPARC32_TI_MICROSPARC_IIEP = 4, + CPU_SPARC32_TI_SUPERSPARC_40 = 5, + CPU_SPARC32_TI_SUPERSPARC_50 = 6, + CPU_SPARC32_TI_SUPERSPARC_51 = 7, + CPU_SPARC32_TI_SUPERSPARC_60 = 8, + CPU_SPARC32_TI_SUPERSPARC_61 = 9, + CPU_SPARC32_TI_SUPERSPARC_II = 10, + CPU_SPARC32_LEON2 = 11, + CPU_SPARC32_LEON3 = 12, + CPU_SPARC32_ENDING = 13, + +// SPARC64 CPU + + CPU_SPARC64_FUJITSU = 0, + CPU_SPARC64_FUJITSU_III = 1, + CPU_SPARC64_FUJITSU_IV = 2, + CPU_SPARC64_FUJITSU_V = 3, + CPU_SPARC64_TI_ULTRASPARC_I = 4, + CPU_SPARC64_TI_ULTRASPARC_II = 5, + CPU_SPARC64_TI_ULTRASPARC_III = 6, + CPU_SPARC64_TI_ULTRASPARC_IIE = 7, + CPU_SPARC64_SUN_ULTRASPARC_III = 8, + CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9, + CPU_SPARC64_SUN_ULTRASPARC_IIII = 10, + CPU_SPARC64_SUN_ULTRASPARC_IV = 11, + CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12, + CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13, + CPU_SPARC64_SUN_ULTRASPARC_T1 = 14, + CPU_SPARC64_SUN_ULTRASPARC_T2 = 15, + CPU_SPARC64_NEC_ULTRASPARC_I = 16, + CPU_SPARC64_ENDING = 17, + +// SPARC registers + + SPARC_REG_INVALID = 0, + SPARC_REG_F0 = 1, + SPARC_REG_F1 = 2, + SPARC_REG_F2 = 3, + SPARC_REG_F3 = 4, + SPARC_REG_F4 = 5, + SPARC_REG_F5 = 6, + SPARC_REG_F6 = 7, + SPARC_REG_F7 = 8, + SPARC_REG_F8 = 9, + SPARC_REG_F9 = 10, + SPARC_REG_F10 = 11, + SPARC_REG_F11 = 12, + SPARC_REG_F12 = 13, + SPARC_REG_F13 = 14, + SPARC_REG_F14 = 15, + SPARC_REG_F15 = 16, + SPARC_REG_F16 = 17, + SPARC_REG_F17 = 18, + SPARC_REG_F18 = 19, + SPARC_REG_F19 = 20, + SPARC_REG_F20 = 21, + SPARC_REG_F21 = 22, + SPARC_REG_F22 = 23, + SPARC_REG_F23 = 24, + SPARC_REG_F24 = 25, + SPARC_REG_F25 = 26, + SPARC_REG_F26 = 27, + SPARC_REG_F27 = 28, + SPARC_REG_F28 = 29, + SPARC_REG_F29 = 30, + SPARC_REG_F30 = 31, + SPARC_REG_F31 = 32, + SPARC_REG_F32 = 33, + SPARC_REG_F34 = 34, + SPARC_REG_F36 = 35, + SPARC_REG_F38 = 36, + SPARC_REG_F40 = 37, + SPARC_REG_F42 = 38, + SPARC_REG_F44 = 39, + SPARC_REG_F46 = 40, + SPARC_REG_F48 = 41, + SPARC_REG_F50 = 42, + SPARC_REG_F52 = 43, + SPARC_REG_F54 = 44, + SPARC_REG_F56 = 45, + SPARC_REG_F58 = 46, + SPARC_REG_F60 = 47, + SPARC_REG_F62 = 48, + SPARC_REG_FCC0 = 49, + SPARC_REG_FCC1 = 50, + SPARC_REG_FCC2 = 51, + SPARC_REG_FCC3 = 52, + SPARC_REG_G0 = 53, + SPARC_REG_G1 = 54, + SPARC_REG_G2 = 55, + SPARC_REG_G3 = 56, + SPARC_REG_G4 = 57, + SPARC_REG_G5 = 58, + SPARC_REG_G6 = 59, + SPARC_REG_G7 = 60, + SPARC_REG_I0 = 61, + SPARC_REG_I1 = 62, + SPARC_REG_I2 = 63, + SPARC_REG_I3 = 64, + SPARC_REG_I4 = 65, + SPARC_REG_I5 = 66, + SPARC_REG_FP = 67, + SPARC_REG_I7 = 68, + SPARC_REG_ICC = 69, + SPARC_REG_L0 = 70, + SPARC_REG_L1 = 71, + SPARC_REG_L2 = 72, + SPARC_REG_L3 = 73, + SPARC_REG_L4 = 74, + SPARC_REG_L5 = 75, + SPARC_REG_L6 = 76, + SPARC_REG_L7 = 77, + SPARC_REG_O0 = 78, + SPARC_REG_O1 = 79, + SPARC_REG_O2 = 80, + SPARC_REG_O3 = 81, + SPARC_REG_O4 = 82, + SPARC_REG_O5 = 83, + SPARC_REG_SP = 84, + SPARC_REG_O7 = 85, + SPARC_REG_Y = 86, + SPARC_REG_XCC = 87, + SPARC_REG_PC = 88, + SPARC_REG_ENDING = 89, + SPARC_REG_O6 = 84, + SPARC_REG_I6 = 67, + +}; diff --git a/bindings/zig/unicorn/tricore_const.zig b/bindings/zig/unicorn/tricore_const.zig new file mode 100644 index 00000000..9b51aea2 --- /dev/null +++ b/bindings/zig/unicorn/tricore_const.zig @@ -0,0 +1,128 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const tricoreConst = enum(c_int) { + +// TRICORE CPU + + CPU_TRICORE_TC1796 = 0, + CPU_TRICORE_TC1797 = 1, + CPU_TRICORE_TC27X = 2, + CPU_TRICORE_ENDING = 3, + +// TRICORE registers + + TRICORE_REG_INVALID = 0, + TRICORE_REG_A0 = 1, + TRICORE_REG_A1 = 2, + TRICORE_REG_A2 = 3, + TRICORE_REG_A3 = 4, + TRICORE_REG_A4 = 5, + TRICORE_REG_A5 = 6, + TRICORE_REG_A6 = 7, + TRICORE_REG_A7 = 8, + TRICORE_REG_A8 = 9, + TRICORE_REG_A9 = 10, + TRICORE_REG_A10 = 11, + TRICORE_REG_A11 = 12, + TRICORE_REG_A12 = 13, + TRICORE_REG_A13 = 14, + TRICORE_REG_A14 = 15, + TRICORE_REG_A15 = 16, + TRICORE_REG_D0 = 17, + TRICORE_REG_D1 = 18, + TRICORE_REG_D2 = 19, + TRICORE_REG_D3 = 20, + TRICORE_REG_D4 = 21, + TRICORE_REG_D5 = 22, + TRICORE_REG_D6 = 23, + TRICORE_REG_D7 = 24, + TRICORE_REG_D8 = 25, + TRICORE_REG_D9 = 26, + TRICORE_REG_D10 = 27, + TRICORE_REG_D11 = 28, + TRICORE_REG_D12 = 29, + TRICORE_REG_D13 = 30, + TRICORE_REG_D14 = 31, + TRICORE_REG_D15 = 32, + TRICORE_REG_PCXI = 33, + TRICORE_REG_PSW = 34, + TRICORE_REG_PSW_USB_C = 35, + TRICORE_REG_PSW_USB_V = 36, + TRICORE_REG_PSW_USB_SV = 37, + TRICORE_REG_PSW_USB_AV = 38, + TRICORE_REG_PSW_USB_SAV = 39, + TRICORE_REG_PC = 40, + TRICORE_REG_SYSCON = 41, + TRICORE_REG_CPU_ID = 42, + TRICORE_REG_BIV = 43, + TRICORE_REG_BTV = 44, + TRICORE_REG_ISP = 45, + TRICORE_REG_ICR = 46, + TRICORE_REG_FCX = 47, + TRICORE_REG_LCX = 48, + TRICORE_REG_COMPAT = 49, + TRICORE_REG_DPR0_U = 50, + TRICORE_REG_DPR1_U = 51, + TRICORE_REG_DPR2_U = 52, + TRICORE_REG_DPR3_U = 53, + TRICORE_REG_DPR0_L = 54, + TRICORE_REG_DPR1_L = 55, + TRICORE_REG_DPR2_L = 56, + TRICORE_REG_DPR3_L = 57, + TRICORE_REG_CPR0_U = 58, + TRICORE_REG_CPR1_U = 59, + TRICORE_REG_CPR2_U = 60, + TRICORE_REG_CPR3_U = 61, + TRICORE_REG_CPR0_L = 62, + TRICORE_REG_CPR1_L = 63, + TRICORE_REG_CPR2_L = 64, + TRICORE_REG_CPR3_L = 65, + TRICORE_REG_DPM0 = 66, + TRICORE_REG_DPM1 = 67, + TRICORE_REG_DPM2 = 68, + TRICORE_REG_DPM3 = 69, + TRICORE_REG_CPM0 = 70, + TRICORE_REG_CPM1 = 71, + TRICORE_REG_CPM2 = 72, + TRICORE_REG_CPM3 = 73, + TRICORE_REG_MMU_CON = 74, + TRICORE_REG_MMU_ASI = 75, + TRICORE_REG_MMU_TVA = 76, + TRICORE_REG_MMU_TPA = 77, + TRICORE_REG_MMU_TPX = 78, + TRICORE_REG_MMU_TFA = 79, + TRICORE_REG_BMACON = 80, + TRICORE_REG_SMACON = 81, + TRICORE_REG_DIEAR = 82, + TRICORE_REG_DIETR = 83, + TRICORE_REG_CCDIER = 84, + TRICORE_REG_MIECON = 85, + TRICORE_REG_PIEAR = 86, + TRICORE_REG_PIETR = 87, + TRICORE_REG_CCPIER = 88, + TRICORE_REG_DBGSR = 89, + TRICORE_REG_EXEVT = 90, + TRICORE_REG_CREVT = 91, + TRICORE_REG_SWEVT = 92, + TRICORE_REG_TR0EVT = 93, + TRICORE_REG_TR1EVT = 94, + TRICORE_REG_DMS = 95, + TRICORE_REG_DCX = 96, + TRICORE_REG_DBGTCR = 97, + TRICORE_REG_CCTRL = 98, + TRICORE_REG_CCNT = 99, + TRICORE_REG_ICNT = 100, + TRICORE_REG_M1CNT = 101, + TRICORE_REG_M2CNT = 102, + TRICORE_REG_M3CNT = 103, + TRICORE_REG_ENDING = 104, + TRICORE_REG_GA0 = 1, + TRICORE_REG_GA1 = 2, + TRICORE_REG_GA8 = 9, + TRICORE_REG_GA9 = 10, + TRICORE_REG_SP = 11, + TRICORE_REG_LR = 12, + TRICORE_REG_IA = 16, + TRICORE_REG_ID = 32, + +}; diff --git a/bindings/zig/unicorn/unicorn.zig b/bindings/zig/unicorn/unicorn.zig new file mode 100644 index 00000000..43d19738 --- /dev/null +++ b/bindings/zig/unicorn/unicorn.zig @@ -0,0 +1,13 @@ +// Architectures +pub const arm = @import("arm_const.zig"); +pub const arm64 = @import("arm64_const.zig"); +pub const m68k = @import("m68k_const.zig"); +pub const mips = @import("mips_const.zig"); +pub const ppc = @import("ppc_const.zig"); +pub const riscv = @import("riscv_const.zig"); +pub const tricore = @import("tricore_const.zig"); +pub const sparc = @import("sparc_const.zig"); +pub const s390x = @import("s390x_const.zig"); +pub const x86 = @import("x86_const.zig"); +// Unicorn +pub const unicorn = @import("unicorn_const.zig"); diff --git a/bindings/zig/unicorn/unicorn_const.zig b/bindings/zig/unicorn/unicorn_const.zig new file mode 100644 index 00000000..b7ccad62 --- /dev/null +++ b/bindings/zig/unicorn/unicorn_const.zig @@ -0,0 +1,144 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const unicornConst = enum(c_int) { + API_MAJOR = 2, + + API_MINOR = 0, + API_PATCH = 1, + API_EXTRA = 255, + VERSION_MAJOR = 2, + + VERSION_MINOR = 0, + VERSION_PATCH = 1, + VERSION_EXTRA = 255, + SECOND_SCALE = 1000000, + MILISECOND_SCALE = 1000, + ARCH_ARM = 1, + ARCH_ARM64 = 2, + ARCH_MIPS = 3, + ARCH_X86 = 4, + ARCH_PPC = 5, + ARCH_SPARC = 6, + ARCH_M68K = 7, + ARCH_RISCV = 8, + ARCH_S390X = 9, + ARCH_TRICORE = 10, + ARCH_MAX = 11, + + MODE_LITTLE_ENDIAN = 0, + MODE_BIG_ENDIAN = 1073741824, + + MODE_ARM = 0, + MODE_THUMB = 16, + MODE_MCLASS = 32, + MODE_V8 = 64, + MODE_ARMBE8 = 1024, + MODE_ARM926 = 128, + MODE_ARM946 = 256, + MODE_ARM1176 = 512, + MODE_MICRO = 16, + MODE_MIPS3 = 32, + MODE_MIPS32R6 = 64, + MODE_MIPS32 = 4, + MODE_MIPS64 = 8, + MODE_16 = 2, + MODE_32 = 4, + MODE_64 = 8, + MODE_PPC32 = 4, + MODE_PPC64 = 8, + MODE_QPX = 16, + MODE_SPARC32 = 4, + MODE_SPARC64 = 8, + MODE_V9 = 16, + MODE_RISCV32 = 4, + MODE_RISCV64 = 8, + + ERR_OK = 0, + ERR_NOMEM = 1, + ERR_ARCH = 2, + ERR_HANDLE = 3, + ERR_MODE = 4, + ERR_VERSION = 5, + ERR_READ_UNMAPPED = 6, + ERR_WRITE_UNMAPPED = 7, + ERR_FETCH_UNMAPPED = 8, + ERR_HOOK = 9, + ERR_INSN_INVALID = 10, + ERR_MAP = 11, + ERR_WRITE_PROT = 12, + ERR_READ_PROT = 13, + ERR_FETCH_PROT = 14, + ERR_ARG = 15, + ERR_READ_UNALIGNED = 16, + ERR_WRITE_UNALIGNED = 17, + ERR_FETCH_UNALIGNED = 18, + ERR_HOOK_EXIST = 19, + ERR_RESOURCE = 20, + ERR_EXCEPTION = 21, + MEM_READ = 16, + MEM_WRITE = 17, + MEM_FETCH = 18, + MEM_READ_UNMAPPED = 19, + MEM_WRITE_UNMAPPED = 20, + MEM_FETCH_UNMAPPED = 21, + MEM_WRITE_PROT = 22, + MEM_READ_PROT = 23, + MEM_FETCH_PROT = 24, + MEM_READ_AFTER = 25, + + TCG_OP_SUB = 0, + TCG_OP_FLAG_CMP = 1, + TCG_OP_FLAG_DIRECT = 2, + HOOK_INTR = 1, + HOOK_INSN = 2, + HOOK_CODE = 4, + HOOK_BLOCK = 8, + HOOK_MEM_READ_UNMAPPED = 16, + HOOK_MEM_WRITE_UNMAPPED = 32, + HOOK_MEM_FETCH_UNMAPPED = 64, + HOOK_MEM_READ_PROT = 128, + HOOK_MEM_WRITE_PROT = 256, + HOOK_MEM_FETCH_PROT = 512, + HOOK_MEM_READ = 1024, + HOOK_MEM_WRITE = 2048, + HOOK_MEM_FETCH = 4096, + HOOK_MEM_READ_AFTER = 8192, + HOOK_INSN_INVALID = 16384, + HOOK_EDGE_GENERATED = 32768, + HOOK_TCG_OPCODE = 65536, + HOOK_MEM_UNMAPPED = 112, + HOOK_MEM_PROT = 896, + HOOK_MEM_READ_INVALID = 144, + HOOK_MEM_WRITE_INVALID = 288, + HOOK_MEM_FETCH_INVALID = 576, + HOOK_MEM_INVALID = 1008, + HOOK_MEM_VALID = 7168, + QUERY_MODE = 1, + QUERY_PAGE_SIZE = 2, + QUERY_ARCH = 3, + QUERY_TIMEOUT = 4, + + CTL_IO_NONE = 0, + CTL_IO_WRITE = 1, + CTL_IO_READ = 2, + CTL_IO_READ_WRITE = 3, + + CTL_UC_MODE = 0, + CTL_UC_PAGE_SIZE = 1, + CTL_UC_ARCH = 2, + CTL_UC_TIMEOUT = 3, + CTL_UC_USE_EXITS = 4, + CTL_UC_EXITS_CNT = 5, + CTL_UC_EXITS = 6, + CTL_CPU_MODEL = 7, + CTL_TB_REQUEST_CACHE = 8, + CTL_TB_REMOVE_CACHE = 9, + CTL_TB_FLUSH = 10, + + PROT_NONE = 0, + PROT_READ = 1, + PROT_WRITE = 2, + PROT_EXEC = 4, + PROT_ALL = 7, + +}; diff --git a/bindings/zig/unicorn/x86_const.zig b/bindings/zig/unicorn/x86_const.zig new file mode 100644 index 00000000..b94f53a1 --- /dev/null +++ b/bindings/zig/unicorn/x86_const.zig @@ -0,0 +1,1632 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +pub const x86Const = enum(c_int) { + +// X86 CPU + + CPU_X86_QEMU64 = 0, + CPU_X86_PHENOM = 1, + CPU_X86_CORE2DUO = 2, + CPU_X86_KVM64 = 3, + CPU_X86_QEMU32 = 4, + CPU_X86_KVM32 = 5, + CPU_X86_COREDUO = 6, + CPU_X86_486 = 7, + CPU_X86_PENTIUM = 8, + CPU_X86_PENTIUM2 = 9, + CPU_X86_PENTIUM3 = 10, + CPU_X86_ATHLON = 11, + CPU_X86_N270 = 12, + CPU_X86_CONROE = 13, + CPU_X86_PENRYN = 14, + CPU_X86_NEHALEM = 15, + CPU_X86_WESTMERE = 16, + CPU_X86_SANDYBRIDGE = 17, + CPU_X86_IVYBRIDGE = 18, + CPU_X86_HASWELL = 19, + CPU_X86_BROADWELL = 20, + CPU_X86_SKYLAKE_CLIENT = 21, + CPU_X86_SKYLAKE_SERVER = 22, + CPU_X86_CASCADELAKE_SERVER = 23, + CPU_X86_COOPERLAKE = 24, + CPU_X86_ICELAKE_CLIENT = 25, + CPU_X86_ICELAKE_SERVER = 26, + CPU_X86_DENVERTON = 27, + CPU_X86_SNOWRIDGE = 28, + CPU_X86_KNIGHTSMILL = 29, + CPU_X86_OPTERON_G1 = 30, + CPU_X86_OPTERON_G2 = 31, + CPU_X86_OPTERON_G3 = 32, + CPU_X86_OPTERON_G4 = 33, + CPU_X86_OPTERON_G5 = 34, + CPU_X86_EPYC = 35, + CPU_X86_DHYANA = 36, + CPU_X86_EPYC_ROME = 37, + CPU_X86_ENDING = 38, + +// X86 registers + + X86_REG_INVALID = 0, + X86_REG_AH = 1, + X86_REG_AL = 2, + X86_REG_AX = 3, + X86_REG_BH = 4, + X86_REG_BL = 5, + X86_REG_BP = 6, + X86_REG_BPL = 7, + X86_REG_BX = 8, + X86_REG_CH = 9, + X86_REG_CL = 10, + X86_REG_CS = 11, + X86_REG_CX = 12, + X86_REG_DH = 13, + X86_REG_DI = 14, + X86_REG_DIL = 15, + X86_REG_DL = 16, + X86_REG_DS = 17, + X86_REG_DX = 18, + X86_REG_EAX = 19, + X86_REG_EBP = 20, + X86_REG_EBX = 21, + X86_REG_ECX = 22, + X86_REG_EDI = 23, + X86_REG_EDX = 24, + X86_REG_EFLAGS = 25, + X86_REG_EIP = 26, + X86_REG_ES = 28, + X86_REG_ESI = 29, + X86_REG_ESP = 30, + X86_REG_FPSW = 31, + X86_REG_FS = 32, + X86_REG_GS = 33, + X86_REG_IP = 34, + X86_REG_RAX = 35, + X86_REG_RBP = 36, + X86_REG_RBX = 37, + X86_REG_RCX = 38, + X86_REG_RDI = 39, + X86_REG_RDX = 40, + X86_REG_RIP = 41, + X86_REG_RSI = 43, + X86_REG_RSP = 44, + X86_REG_SI = 45, + X86_REG_SIL = 46, + X86_REG_SP = 47, + X86_REG_SPL = 48, + X86_REG_SS = 49, + X86_REG_CR0 = 50, + X86_REG_CR1 = 51, + X86_REG_CR2 = 52, + X86_REG_CR3 = 53, + X86_REG_CR4 = 54, + X86_REG_CR8 = 58, + X86_REG_DR0 = 66, + X86_REG_DR1 = 67, + X86_REG_DR2 = 68, + X86_REG_DR3 = 69, + X86_REG_DR4 = 70, + X86_REG_DR5 = 71, + X86_REG_DR6 = 72, + X86_REG_DR7 = 73, + X86_REG_FP0 = 82, + X86_REG_FP1 = 83, + X86_REG_FP2 = 84, + X86_REG_FP3 = 85, + X86_REG_FP4 = 86, + X86_REG_FP5 = 87, + X86_REG_FP6 = 88, + X86_REG_FP7 = 89, + X86_REG_K0 = 90, + X86_REG_K1 = 91, + X86_REG_K2 = 92, + X86_REG_K3 = 93, + X86_REG_K4 = 94, + X86_REG_K5 = 95, + X86_REG_K6 = 96, + X86_REG_K7 = 97, + X86_REG_MM0 = 98, + X86_REG_MM1 = 99, + X86_REG_MM2 = 100, + X86_REG_MM3 = 101, + X86_REG_MM4 = 102, + X86_REG_MM5 = 103, + X86_REG_MM6 = 104, + X86_REG_MM7 = 105, + X86_REG_R8 = 106, + X86_REG_R9 = 107, + X86_REG_R10 = 108, + X86_REG_R11 = 109, + X86_REG_R12 = 110, + X86_REG_R13 = 111, + X86_REG_R14 = 112, + X86_REG_R15 = 113, + X86_REG_ST0 = 114, + X86_REG_ST1 = 115, + X86_REG_ST2 = 116, + X86_REG_ST3 = 117, + X86_REG_ST4 = 118, + X86_REG_ST5 = 119, + X86_REG_ST6 = 120, + X86_REG_ST7 = 121, + X86_REG_XMM0 = 122, + X86_REG_XMM1 = 123, + X86_REG_XMM2 = 124, + X86_REG_XMM3 = 125, + X86_REG_XMM4 = 126, + X86_REG_XMM5 = 127, + X86_REG_XMM6 = 128, + X86_REG_XMM7 = 129, + X86_REG_XMM8 = 130, + X86_REG_XMM9 = 131, + X86_REG_XMM10 = 132, + X86_REG_XMM11 = 133, + X86_REG_XMM12 = 134, + X86_REG_XMM13 = 135, + X86_REG_XMM14 = 136, + X86_REG_XMM15 = 137, + X86_REG_XMM16 = 138, + X86_REG_XMM17 = 139, + X86_REG_XMM18 = 140, + X86_REG_XMM19 = 141, + X86_REG_XMM20 = 142, + X86_REG_XMM21 = 143, + X86_REG_XMM22 = 144, + X86_REG_XMM23 = 145, + X86_REG_XMM24 = 146, + X86_REG_XMM25 = 147, + X86_REG_XMM26 = 148, + X86_REG_XMM27 = 149, + X86_REG_XMM28 = 150, + X86_REG_XMM29 = 151, + X86_REG_XMM30 = 152, + X86_REG_XMM31 = 153, + X86_REG_YMM0 = 154, + X86_REG_YMM1 = 155, + X86_REG_YMM2 = 156, + X86_REG_YMM3 = 157, + X86_REG_YMM4 = 158, + X86_REG_YMM5 = 159, + X86_REG_YMM6 = 160, + X86_REG_YMM7 = 161, + X86_REG_YMM8 = 162, + X86_REG_YMM9 = 163, + X86_REG_YMM10 = 164, + X86_REG_YMM11 = 165, + X86_REG_YMM12 = 166, + X86_REG_YMM13 = 167, + X86_REG_YMM14 = 168, + X86_REG_YMM15 = 169, + X86_REG_YMM16 = 170, + X86_REG_YMM17 = 171, + X86_REG_YMM18 = 172, + X86_REG_YMM19 = 173, + X86_REG_YMM20 = 174, + X86_REG_YMM21 = 175, + X86_REG_YMM22 = 176, + X86_REG_YMM23 = 177, + X86_REG_YMM24 = 178, + X86_REG_YMM25 = 179, + X86_REG_YMM26 = 180, + X86_REG_YMM27 = 181, + X86_REG_YMM28 = 182, + X86_REG_YMM29 = 183, + X86_REG_YMM30 = 184, + X86_REG_YMM31 = 185, + X86_REG_ZMM0 = 186, + X86_REG_ZMM1 = 187, + X86_REG_ZMM2 = 188, + X86_REG_ZMM3 = 189, + X86_REG_ZMM4 = 190, + X86_REG_ZMM5 = 191, + X86_REG_ZMM6 = 192, + X86_REG_ZMM7 = 193, + X86_REG_ZMM8 = 194, + X86_REG_ZMM9 = 195, + X86_REG_ZMM10 = 196, + X86_REG_ZMM11 = 197, + X86_REG_ZMM12 = 198, + X86_REG_ZMM13 = 199, + X86_REG_ZMM14 = 200, + X86_REG_ZMM15 = 201, + X86_REG_ZMM16 = 202, + X86_REG_ZMM17 = 203, + X86_REG_ZMM18 = 204, + X86_REG_ZMM19 = 205, + X86_REG_ZMM20 = 206, + X86_REG_ZMM21 = 207, + X86_REG_ZMM22 = 208, + X86_REG_ZMM23 = 209, + X86_REG_ZMM24 = 210, + X86_REG_ZMM25 = 211, + X86_REG_ZMM26 = 212, + X86_REG_ZMM27 = 213, + X86_REG_ZMM28 = 214, + X86_REG_ZMM29 = 215, + X86_REG_ZMM30 = 216, + X86_REG_ZMM31 = 217, + X86_REG_R8B = 218, + X86_REG_R9B = 219, + X86_REG_R10B = 220, + X86_REG_R11B = 221, + X86_REG_R12B = 222, + X86_REG_R13B = 223, + X86_REG_R14B = 224, + X86_REG_R15B = 225, + X86_REG_R8D = 226, + X86_REG_R9D = 227, + X86_REG_R10D = 228, + X86_REG_R11D = 229, + X86_REG_R12D = 230, + X86_REG_R13D = 231, + X86_REG_R14D = 232, + X86_REG_R15D = 233, + X86_REG_R8W = 234, + X86_REG_R9W = 235, + X86_REG_R10W = 236, + X86_REG_R11W = 237, + X86_REG_R12W = 238, + X86_REG_R13W = 239, + X86_REG_R14W = 240, + X86_REG_R15W = 241, + X86_REG_IDTR = 242, + X86_REG_GDTR = 243, + X86_REG_LDTR = 244, + X86_REG_TR = 245, + X86_REG_FPCW = 246, + X86_REG_FPTAG = 247, + X86_REG_MSR = 248, + X86_REG_MXCSR = 249, + X86_REG_FS_BASE = 250, + X86_REG_GS_BASE = 251, + X86_REG_FLAGS = 252, + X86_REG_RFLAGS = 253, + X86_REG_FIP = 254, + X86_REG_FCS = 255, + X86_REG_FDP = 256, + X86_REG_FDS = 257, + X86_REG_FOP = 258, + X86_REG_ENDING = 259, + +// X86 instructions + + X86_INS_INVALID = 0, + X86_INS_AAA = 1, + X86_INS_AAD = 2, + X86_INS_AAM = 3, + X86_INS_AAS = 4, + X86_INS_FABS = 5, + X86_INS_ADC = 6, + X86_INS_ADCX = 7, + X86_INS_ADD = 8, + X86_INS_ADDPD = 9, + X86_INS_ADDPS = 10, + X86_INS_ADDSD = 11, + X86_INS_ADDSS = 12, + X86_INS_ADDSUBPD = 13, + X86_INS_ADDSUBPS = 14, + X86_INS_FADD = 15, + X86_INS_FIADD = 16, + X86_INS_FADDP = 17, + X86_INS_ADOX = 18, + X86_INS_AESDECLAST = 19, + X86_INS_AESDEC = 20, + X86_INS_AESENCLAST = 21, + X86_INS_AESENC = 22, + X86_INS_AESIMC = 23, + X86_INS_AESKEYGENASSIST = 24, + X86_INS_AND = 25, + X86_INS_ANDN = 26, + X86_INS_ANDNPD = 27, + X86_INS_ANDNPS = 28, + X86_INS_ANDPD = 29, + X86_INS_ANDPS = 30, + X86_INS_ARPL = 31, + X86_INS_BEXTR = 32, + X86_INS_BLCFILL = 33, + X86_INS_BLCI = 34, + X86_INS_BLCIC = 35, + X86_INS_BLCMSK = 36, + X86_INS_BLCS = 37, + X86_INS_BLENDPD = 38, + X86_INS_BLENDPS = 39, + X86_INS_BLENDVPD = 40, + X86_INS_BLENDVPS = 41, + X86_INS_BLSFILL = 42, + X86_INS_BLSI = 43, + X86_INS_BLSIC = 44, + X86_INS_BLSMSK = 45, + X86_INS_BLSR = 46, + X86_INS_BOUND = 47, + X86_INS_BSF = 48, + X86_INS_BSR = 49, + X86_INS_BSWAP = 50, + X86_INS_BT = 51, + X86_INS_BTC = 52, + X86_INS_BTR = 53, + X86_INS_BTS = 54, + X86_INS_BZHI = 55, + X86_INS_CALL = 56, + X86_INS_CBW = 57, + X86_INS_CDQ = 58, + X86_INS_CDQE = 59, + X86_INS_FCHS = 60, + X86_INS_CLAC = 61, + X86_INS_CLC = 62, + X86_INS_CLD = 63, + X86_INS_CLFLUSH = 64, + X86_INS_CLFLUSHOPT = 65, + X86_INS_CLGI = 66, + X86_INS_CLI = 67, + X86_INS_CLTS = 68, + X86_INS_CLWB = 69, + X86_INS_CMC = 70, + X86_INS_CMOVA = 71, + X86_INS_CMOVAE = 72, + X86_INS_CMOVB = 73, + X86_INS_CMOVBE = 74, + X86_INS_FCMOVBE = 75, + X86_INS_FCMOVB = 76, + X86_INS_CMOVE = 77, + X86_INS_FCMOVE = 78, + X86_INS_CMOVG = 79, + X86_INS_CMOVGE = 80, + X86_INS_CMOVL = 81, + X86_INS_CMOVLE = 82, + X86_INS_FCMOVNBE = 83, + X86_INS_FCMOVNB = 84, + X86_INS_CMOVNE = 85, + X86_INS_FCMOVNE = 86, + X86_INS_CMOVNO = 87, + X86_INS_CMOVNP = 88, + X86_INS_FCMOVNU = 89, + X86_INS_CMOVNS = 90, + X86_INS_CMOVO = 91, + X86_INS_CMOVP = 92, + X86_INS_FCMOVU = 93, + X86_INS_CMOVS = 94, + X86_INS_CMP = 95, + X86_INS_CMPPD = 96, + X86_INS_CMPPS = 97, + X86_INS_CMPSB = 98, + X86_INS_CMPSD = 99, + X86_INS_CMPSQ = 100, + X86_INS_CMPSS = 101, + X86_INS_CMPSW = 102, + X86_INS_CMPXCHG16B = 103, + X86_INS_CMPXCHG = 104, + X86_INS_CMPXCHG8B = 105, + X86_INS_COMISD = 106, + X86_INS_COMISS = 107, + X86_INS_FCOMP = 108, + X86_INS_FCOMPI = 109, + X86_INS_FCOMI = 110, + X86_INS_FCOM = 111, + X86_INS_FCOS = 112, + X86_INS_CPUID = 113, + X86_INS_CQO = 114, + X86_INS_CRC32 = 115, + X86_INS_CVTDQ2PD = 116, + X86_INS_CVTDQ2PS = 117, + X86_INS_CVTPD2DQ = 118, + X86_INS_CVTPD2PS = 119, + X86_INS_CVTPS2DQ = 120, + X86_INS_CVTPS2PD = 121, + X86_INS_CVTSD2SI = 122, + X86_INS_CVTSD2SS = 123, + X86_INS_CVTSI2SD = 124, + X86_INS_CVTSI2SS = 125, + X86_INS_CVTSS2SD = 126, + X86_INS_CVTSS2SI = 127, + X86_INS_CVTTPD2DQ = 128, + X86_INS_CVTTPS2DQ = 129, + X86_INS_CVTTSD2SI = 130, + X86_INS_CVTTSS2SI = 131, + X86_INS_CWD = 132, + X86_INS_CWDE = 133, + X86_INS_DAA = 134, + X86_INS_DAS = 135, + X86_INS_DATA16 = 136, + X86_INS_DEC = 137, + X86_INS_DIV = 138, + X86_INS_DIVPD = 139, + X86_INS_DIVPS = 140, + X86_INS_FDIVR = 141, + X86_INS_FIDIVR = 142, + X86_INS_FDIVRP = 143, + X86_INS_DIVSD = 144, + X86_INS_DIVSS = 145, + X86_INS_FDIV = 146, + X86_INS_FIDIV = 147, + X86_INS_FDIVP = 148, + X86_INS_DPPD = 149, + X86_INS_DPPS = 150, + X86_INS_RET = 151, + X86_INS_ENCLS = 152, + X86_INS_ENCLU = 153, + X86_INS_ENTER = 154, + X86_INS_EXTRACTPS = 155, + X86_INS_EXTRQ = 156, + X86_INS_F2XM1 = 157, + X86_INS_LCALL = 158, + X86_INS_LJMP = 159, + X86_INS_FBLD = 160, + X86_INS_FBSTP = 161, + X86_INS_FCOMPP = 162, + X86_INS_FDECSTP = 163, + X86_INS_FEMMS = 164, + X86_INS_FFREE = 165, + X86_INS_FICOM = 166, + X86_INS_FICOMP = 167, + X86_INS_FINCSTP = 168, + X86_INS_FLDCW = 169, + X86_INS_FLDENV = 170, + X86_INS_FLDL2E = 171, + X86_INS_FLDL2T = 172, + X86_INS_FLDLG2 = 173, + X86_INS_FLDLN2 = 174, + X86_INS_FLDPI = 175, + X86_INS_FNCLEX = 176, + X86_INS_FNINIT = 177, + X86_INS_FNOP = 178, + X86_INS_FNSTCW = 179, + X86_INS_FNSTSW = 180, + X86_INS_FPATAN = 181, + X86_INS_FPREM = 182, + X86_INS_FPREM1 = 183, + X86_INS_FPTAN = 184, + X86_INS_FFREEP = 185, + X86_INS_FRNDINT = 186, + X86_INS_FRSTOR = 187, + X86_INS_FNSAVE = 188, + X86_INS_FSCALE = 189, + X86_INS_FSETPM = 190, + X86_INS_FSINCOS = 191, + X86_INS_FNSTENV = 192, + X86_INS_FXAM = 193, + X86_INS_FXRSTOR = 194, + X86_INS_FXRSTOR64 = 195, + X86_INS_FXSAVE = 196, + X86_INS_FXSAVE64 = 197, + X86_INS_FXTRACT = 198, + X86_INS_FYL2X = 199, + X86_INS_FYL2XP1 = 200, + X86_INS_MOVAPD = 201, + X86_INS_MOVAPS = 202, + X86_INS_ORPD = 203, + X86_INS_ORPS = 204, + X86_INS_VMOVAPD = 205, + X86_INS_VMOVAPS = 206, + X86_INS_XORPD = 207, + X86_INS_XORPS = 208, + X86_INS_GETSEC = 209, + X86_INS_HADDPD = 210, + X86_INS_HADDPS = 211, + X86_INS_HLT = 212, + X86_INS_HSUBPD = 213, + X86_INS_HSUBPS = 214, + X86_INS_IDIV = 215, + X86_INS_FILD = 216, + X86_INS_IMUL = 217, + X86_INS_IN = 218, + X86_INS_INC = 219, + X86_INS_INSB = 220, + X86_INS_INSERTPS = 221, + X86_INS_INSERTQ = 222, + X86_INS_INSD = 223, + X86_INS_INSW = 224, + X86_INS_INT = 225, + X86_INS_INT1 = 226, + X86_INS_INT3 = 227, + X86_INS_INTO = 228, + X86_INS_INVD = 229, + X86_INS_INVEPT = 230, + X86_INS_INVLPG = 231, + X86_INS_INVLPGA = 232, + X86_INS_INVPCID = 233, + X86_INS_INVVPID = 234, + X86_INS_IRET = 235, + X86_INS_IRETD = 236, + X86_INS_IRETQ = 237, + X86_INS_FISTTP = 238, + X86_INS_FIST = 239, + X86_INS_FISTP = 240, + X86_INS_UCOMISD = 241, + X86_INS_UCOMISS = 242, + X86_INS_VCOMISD = 243, + X86_INS_VCOMISS = 244, + X86_INS_VCVTSD2SS = 245, + X86_INS_VCVTSI2SD = 246, + X86_INS_VCVTSI2SS = 247, + X86_INS_VCVTSS2SD = 248, + X86_INS_VCVTTSD2SI = 249, + X86_INS_VCVTTSD2USI = 250, + X86_INS_VCVTTSS2SI = 251, + X86_INS_VCVTTSS2USI = 252, + X86_INS_VCVTUSI2SD = 253, + X86_INS_VCVTUSI2SS = 254, + X86_INS_VUCOMISD = 255, + X86_INS_VUCOMISS = 256, + X86_INS_JAE = 257, + X86_INS_JA = 258, + X86_INS_JBE = 259, + X86_INS_JB = 260, + X86_INS_JCXZ = 261, + X86_INS_JECXZ = 262, + X86_INS_JE = 263, + X86_INS_JGE = 264, + X86_INS_JG = 265, + X86_INS_JLE = 266, + X86_INS_JL = 267, + X86_INS_JMP = 268, + X86_INS_JNE = 269, + X86_INS_JNO = 270, + X86_INS_JNP = 271, + X86_INS_JNS = 272, + X86_INS_JO = 273, + X86_INS_JP = 274, + X86_INS_JRCXZ = 275, + X86_INS_JS = 276, + X86_INS_KANDB = 277, + X86_INS_KANDD = 278, + X86_INS_KANDNB = 279, + X86_INS_KANDND = 280, + X86_INS_KANDNQ = 281, + X86_INS_KANDNW = 282, + X86_INS_KANDQ = 283, + X86_INS_KANDW = 284, + X86_INS_KMOVB = 285, + X86_INS_KMOVD = 286, + X86_INS_KMOVQ = 287, + X86_INS_KMOVW = 288, + X86_INS_KNOTB = 289, + X86_INS_KNOTD = 290, + X86_INS_KNOTQ = 291, + X86_INS_KNOTW = 292, + X86_INS_KORB = 293, + X86_INS_KORD = 294, + X86_INS_KORQ = 295, + X86_INS_KORTESTB = 296, + X86_INS_KORTESTD = 297, + X86_INS_KORTESTQ = 298, + X86_INS_KORTESTW = 299, + X86_INS_KORW = 300, + X86_INS_KSHIFTLB = 301, + X86_INS_KSHIFTLD = 302, + X86_INS_KSHIFTLQ = 303, + X86_INS_KSHIFTLW = 304, + X86_INS_KSHIFTRB = 305, + X86_INS_KSHIFTRD = 306, + X86_INS_KSHIFTRQ = 307, + X86_INS_KSHIFTRW = 308, + X86_INS_KUNPCKBW = 309, + X86_INS_KXNORB = 310, + X86_INS_KXNORD = 311, + X86_INS_KXNORQ = 312, + X86_INS_KXNORW = 313, + X86_INS_KXORB = 314, + X86_INS_KXORD = 315, + X86_INS_KXORQ = 316, + X86_INS_KXORW = 317, + X86_INS_LAHF = 318, + X86_INS_LAR = 319, + X86_INS_LDDQU = 320, + X86_INS_LDMXCSR = 321, + X86_INS_LDS = 322, + X86_INS_FLDZ = 323, + X86_INS_FLD1 = 324, + X86_INS_FLD = 325, + X86_INS_LEA = 326, + X86_INS_LEAVE = 327, + X86_INS_LES = 328, + X86_INS_LFENCE = 329, + X86_INS_LFS = 330, + X86_INS_LGDT = 331, + X86_INS_LGS = 332, + X86_INS_LIDT = 333, + X86_INS_LLDT = 334, + X86_INS_LMSW = 335, + X86_INS_OR = 336, + X86_INS_SUB = 337, + X86_INS_XOR = 338, + X86_INS_LODSB = 339, + X86_INS_LODSD = 340, + X86_INS_LODSQ = 341, + X86_INS_LODSW = 342, + X86_INS_LOOP = 343, + X86_INS_LOOPE = 344, + X86_INS_LOOPNE = 345, + X86_INS_RETF = 346, + X86_INS_RETFQ = 347, + X86_INS_LSL = 348, + X86_INS_LSS = 349, + X86_INS_LTR = 350, + X86_INS_XADD = 351, + X86_INS_LZCNT = 352, + X86_INS_MASKMOVDQU = 353, + X86_INS_MAXPD = 354, + X86_INS_MAXPS = 355, + X86_INS_MAXSD = 356, + X86_INS_MAXSS = 357, + X86_INS_MFENCE = 358, + X86_INS_MINPD = 359, + X86_INS_MINPS = 360, + X86_INS_MINSD = 361, + X86_INS_MINSS = 362, + X86_INS_CVTPD2PI = 363, + X86_INS_CVTPI2PD = 364, + X86_INS_CVTPI2PS = 365, + X86_INS_CVTPS2PI = 366, + X86_INS_CVTTPD2PI = 367, + X86_INS_CVTTPS2PI = 368, + X86_INS_EMMS = 369, + X86_INS_MASKMOVQ = 370, + X86_INS_MOVD = 371, + X86_INS_MOVDQ2Q = 372, + X86_INS_MOVNTQ = 373, + X86_INS_MOVQ2DQ = 374, + X86_INS_MOVQ = 375, + X86_INS_PABSB = 376, + X86_INS_PABSD = 377, + X86_INS_PABSW = 378, + X86_INS_PACKSSDW = 379, + X86_INS_PACKSSWB = 380, + X86_INS_PACKUSWB = 381, + X86_INS_PADDB = 382, + X86_INS_PADDD = 383, + X86_INS_PADDQ = 384, + X86_INS_PADDSB = 385, + X86_INS_PADDSW = 386, + X86_INS_PADDUSB = 387, + X86_INS_PADDUSW = 388, + X86_INS_PADDW = 389, + X86_INS_PALIGNR = 390, + X86_INS_PANDN = 391, + X86_INS_PAND = 392, + X86_INS_PAVGB = 393, + X86_INS_PAVGW = 394, + X86_INS_PCMPEQB = 395, + X86_INS_PCMPEQD = 396, + X86_INS_PCMPEQW = 397, + X86_INS_PCMPGTB = 398, + X86_INS_PCMPGTD = 399, + X86_INS_PCMPGTW = 400, + X86_INS_PEXTRW = 401, + X86_INS_PHADDSW = 402, + X86_INS_PHADDW = 403, + X86_INS_PHADDD = 404, + X86_INS_PHSUBD = 405, + X86_INS_PHSUBSW = 406, + X86_INS_PHSUBW = 407, + X86_INS_PINSRW = 408, + X86_INS_PMADDUBSW = 409, + X86_INS_PMADDWD = 410, + X86_INS_PMAXSW = 411, + X86_INS_PMAXUB = 412, + X86_INS_PMINSW = 413, + X86_INS_PMINUB = 414, + X86_INS_PMOVMSKB = 415, + X86_INS_PMULHRSW = 416, + X86_INS_PMULHUW = 417, + X86_INS_PMULHW = 418, + X86_INS_PMULLW = 419, + X86_INS_PMULUDQ = 420, + X86_INS_POR = 421, + X86_INS_PSADBW = 422, + X86_INS_PSHUFB = 423, + X86_INS_PSHUFW = 424, + X86_INS_PSIGNB = 425, + X86_INS_PSIGND = 426, + X86_INS_PSIGNW = 427, + X86_INS_PSLLD = 428, + X86_INS_PSLLQ = 429, + X86_INS_PSLLW = 430, + X86_INS_PSRAD = 431, + X86_INS_PSRAW = 432, + X86_INS_PSRLD = 433, + X86_INS_PSRLQ = 434, + X86_INS_PSRLW = 435, + X86_INS_PSUBB = 436, + X86_INS_PSUBD = 437, + X86_INS_PSUBQ = 438, + X86_INS_PSUBSB = 439, + X86_INS_PSUBSW = 440, + X86_INS_PSUBUSB = 441, + X86_INS_PSUBUSW = 442, + X86_INS_PSUBW = 443, + X86_INS_PUNPCKHBW = 444, + X86_INS_PUNPCKHDQ = 445, + X86_INS_PUNPCKHWD = 446, + X86_INS_PUNPCKLBW = 447, + X86_INS_PUNPCKLDQ = 448, + X86_INS_PUNPCKLWD = 449, + X86_INS_PXOR = 450, + X86_INS_MONITOR = 451, + X86_INS_MONTMUL = 452, + X86_INS_MOV = 453, + X86_INS_MOVABS = 454, + X86_INS_MOVBE = 455, + X86_INS_MOVDDUP = 456, + X86_INS_MOVDQA = 457, + X86_INS_MOVDQU = 458, + X86_INS_MOVHLPS = 459, + X86_INS_MOVHPD = 460, + X86_INS_MOVHPS = 461, + X86_INS_MOVLHPS = 462, + X86_INS_MOVLPD = 463, + X86_INS_MOVLPS = 464, + X86_INS_MOVMSKPD = 465, + X86_INS_MOVMSKPS = 466, + X86_INS_MOVNTDQA = 467, + X86_INS_MOVNTDQ = 468, + X86_INS_MOVNTI = 469, + X86_INS_MOVNTPD = 470, + X86_INS_MOVNTPS = 471, + X86_INS_MOVNTSD = 472, + X86_INS_MOVNTSS = 473, + X86_INS_MOVSB = 474, + X86_INS_MOVSD = 475, + X86_INS_MOVSHDUP = 476, + X86_INS_MOVSLDUP = 477, + X86_INS_MOVSQ = 478, + X86_INS_MOVSS = 479, + X86_INS_MOVSW = 480, + X86_INS_MOVSX = 481, + X86_INS_MOVSXD = 482, + X86_INS_MOVUPD = 483, + X86_INS_MOVUPS = 484, + X86_INS_MOVZX = 485, + X86_INS_MPSADBW = 486, + X86_INS_MUL = 487, + X86_INS_MULPD = 488, + X86_INS_MULPS = 489, + X86_INS_MULSD = 490, + X86_INS_MULSS = 491, + X86_INS_MULX = 492, + X86_INS_FMUL = 493, + X86_INS_FIMUL = 494, + X86_INS_FMULP = 495, + X86_INS_MWAIT = 496, + X86_INS_NEG = 497, + X86_INS_NOP = 498, + X86_INS_NOT = 499, + X86_INS_OUT = 500, + X86_INS_OUTSB = 501, + X86_INS_OUTSD = 502, + X86_INS_OUTSW = 503, + X86_INS_PACKUSDW = 504, + X86_INS_PAUSE = 505, + X86_INS_PAVGUSB = 506, + X86_INS_PBLENDVB = 507, + X86_INS_PBLENDW = 508, + X86_INS_PCLMULQDQ = 509, + X86_INS_PCMPEQQ = 510, + X86_INS_PCMPESTRI = 511, + X86_INS_PCMPESTRM = 512, + X86_INS_PCMPGTQ = 513, + X86_INS_PCMPISTRI = 514, + X86_INS_PCMPISTRM = 515, + X86_INS_PCOMMIT = 516, + X86_INS_PDEP = 517, + X86_INS_PEXT = 518, + X86_INS_PEXTRB = 519, + X86_INS_PEXTRD = 520, + X86_INS_PEXTRQ = 521, + X86_INS_PF2ID = 522, + X86_INS_PF2IW = 523, + X86_INS_PFACC = 524, + X86_INS_PFADD = 525, + X86_INS_PFCMPEQ = 526, + X86_INS_PFCMPGE = 527, + X86_INS_PFCMPGT = 528, + X86_INS_PFMAX = 529, + X86_INS_PFMIN = 530, + X86_INS_PFMUL = 531, + X86_INS_PFNACC = 532, + X86_INS_PFPNACC = 533, + X86_INS_PFRCPIT1 = 534, + X86_INS_PFRCPIT2 = 535, + X86_INS_PFRCP = 536, + X86_INS_PFRSQIT1 = 537, + X86_INS_PFRSQRT = 538, + X86_INS_PFSUBR = 539, + X86_INS_PFSUB = 540, + X86_INS_PHMINPOSUW = 541, + X86_INS_PI2FD = 542, + X86_INS_PI2FW = 543, + X86_INS_PINSRB = 544, + X86_INS_PINSRD = 545, + X86_INS_PINSRQ = 546, + X86_INS_PMAXSB = 547, + X86_INS_PMAXSD = 548, + X86_INS_PMAXUD = 549, + X86_INS_PMAXUW = 550, + X86_INS_PMINSB = 551, + X86_INS_PMINSD = 552, + X86_INS_PMINUD = 553, + X86_INS_PMINUW = 554, + X86_INS_PMOVSXBD = 555, + X86_INS_PMOVSXBQ = 556, + X86_INS_PMOVSXBW = 557, + X86_INS_PMOVSXDQ = 558, + X86_INS_PMOVSXWD = 559, + X86_INS_PMOVSXWQ = 560, + X86_INS_PMOVZXBD = 561, + X86_INS_PMOVZXBQ = 562, + X86_INS_PMOVZXBW = 563, + X86_INS_PMOVZXDQ = 564, + X86_INS_PMOVZXWD = 565, + X86_INS_PMOVZXWQ = 566, + X86_INS_PMULDQ = 567, + X86_INS_PMULHRW = 568, + X86_INS_PMULLD = 569, + X86_INS_POP = 570, + X86_INS_POPAW = 571, + X86_INS_POPAL = 572, + X86_INS_POPCNT = 573, + X86_INS_POPF = 574, + X86_INS_POPFD = 575, + X86_INS_POPFQ = 576, + X86_INS_PREFETCH = 577, + X86_INS_PREFETCHNTA = 578, + X86_INS_PREFETCHT0 = 579, + X86_INS_PREFETCHT1 = 580, + X86_INS_PREFETCHT2 = 581, + X86_INS_PREFETCHW = 582, + X86_INS_PSHUFD = 583, + X86_INS_PSHUFHW = 584, + X86_INS_PSHUFLW = 585, + X86_INS_PSLLDQ = 586, + X86_INS_PSRLDQ = 587, + X86_INS_PSWAPD = 588, + X86_INS_PTEST = 589, + X86_INS_PUNPCKHQDQ = 590, + X86_INS_PUNPCKLQDQ = 591, + X86_INS_PUSH = 592, + X86_INS_PUSHAW = 593, + X86_INS_PUSHAL = 594, + X86_INS_PUSHF = 595, + X86_INS_PUSHFD = 596, + X86_INS_PUSHFQ = 597, + X86_INS_RCL = 598, + X86_INS_RCPPS = 599, + X86_INS_RCPSS = 600, + X86_INS_RCR = 601, + X86_INS_RDFSBASE = 602, + X86_INS_RDGSBASE = 603, + X86_INS_RDMSR = 604, + X86_INS_RDPMC = 605, + X86_INS_RDRAND = 606, + X86_INS_RDSEED = 607, + X86_INS_RDTSC = 608, + X86_INS_RDTSCP = 609, + X86_INS_ROL = 610, + X86_INS_ROR = 611, + X86_INS_RORX = 612, + X86_INS_ROUNDPD = 613, + X86_INS_ROUNDPS = 614, + X86_INS_ROUNDSD = 615, + X86_INS_ROUNDSS = 616, + X86_INS_RSM = 617, + X86_INS_RSQRTPS = 618, + X86_INS_RSQRTSS = 619, + X86_INS_SAHF = 620, + X86_INS_SAL = 621, + X86_INS_SALC = 622, + X86_INS_SAR = 623, + X86_INS_SARX = 624, + X86_INS_SBB = 625, + X86_INS_SCASB = 626, + X86_INS_SCASD = 627, + X86_INS_SCASQ = 628, + X86_INS_SCASW = 629, + X86_INS_SETAE = 630, + X86_INS_SETA = 631, + X86_INS_SETBE = 632, + X86_INS_SETB = 633, + X86_INS_SETE = 634, + X86_INS_SETGE = 635, + X86_INS_SETG = 636, + X86_INS_SETLE = 637, + X86_INS_SETL = 638, + X86_INS_SETNE = 639, + X86_INS_SETNO = 640, + X86_INS_SETNP = 641, + X86_INS_SETNS = 642, + X86_INS_SETO = 643, + X86_INS_SETP = 644, + X86_INS_SETS = 645, + X86_INS_SFENCE = 646, + X86_INS_SGDT = 647, + X86_INS_SHA1MSG1 = 648, + X86_INS_SHA1MSG2 = 649, + X86_INS_SHA1NEXTE = 650, + X86_INS_SHA1RNDS4 = 651, + X86_INS_SHA256MSG1 = 652, + X86_INS_SHA256MSG2 = 653, + X86_INS_SHA256RNDS2 = 654, + X86_INS_SHL = 655, + X86_INS_SHLD = 656, + X86_INS_SHLX = 657, + X86_INS_SHR = 658, + X86_INS_SHRD = 659, + X86_INS_SHRX = 660, + X86_INS_SHUFPD = 661, + X86_INS_SHUFPS = 662, + X86_INS_SIDT = 663, + X86_INS_FSIN = 664, + X86_INS_SKINIT = 665, + X86_INS_SLDT = 666, + X86_INS_SMSW = 667, + X86_INS_SQRTPD = 668, + X86_INS_SQRTPS = 669, + X86_INS_SQRTSD = 670, + X86_INS_SQRTSS = 671, + X86_INS_FSQRT = 672, + X86_INS_STAC = 673, + X86_INS_STC = 674, + X86_INS_STD = 675, + X86_INS_STGI = 676, + X86_INS_STI = 677, + X86_INS_STMXCSR = 678, + X86_INS_STOSB = 679, + X86_INS_STOSD = 680, + X86_INS_STOSQ = 681, + X86_INS_STOSW = 682, + X86_INS_STR = 683, + X86_INS_FST = 684, + X86_INS_FSTP = 685, + X86_INS_FSTPNCE = 686, + X86_INS_FXCH = 687, + X86_INS_SUBPD = 688, + X86_INS_SUBPS = 689, + X86_INS_FSUBR = 690, + X86_INS_FISUBR = 691, + X86_INS_FSUBRP = 692, + X86_INS_SUBSD = 693, + X86_INS_SUBSS = 694, + X86_INS_FSUB = 695, + X86_INS_FISUB = 696, + X86_INS_FSUBP = 697, + X86_INS_SWAPGS = 698, + X86_INS_SYSCALL = 699, + X86_INS_SYSENTER = 700, + X86_INS_SYSEXIT = 701, + X86_INS_SYSRET = 702, + X86_INS_T1MSKC = 703, + X86_INS_TEST = 704, + X86_INS_UD2 = 705, + X86_INS_FTST = 706, + X86_INS_TZCNT = 707, + X86_INS_TZMSK = 708, + X86_INS_FUCOMPI = 709, + X86_INS_FUCOMI = 710, + X86_INS_FUCOMPP = 711, + X86_INS_FUCOMP = 712, + X86_INS_FUCOM = 713, + X86_INS_UD2B = 714, + X86_INS_UNPCKHPD = 715, + X86_INS_UNPCKHPS = 716, + X86_INS_UNPCKLPD = 717, + X86_INS_UNPCKLPS = 718, + X86_INS_VADDPD = 719, + X86_INS_VADDPS = 720, + X86_INS_VADDSD = 721, + X86_INS_VADDSS = 722, + X86_INS_VADDSUBPD = 723, + X86_INS_VADDSUBPS = 724, + X86_INS_VAESDECLAST = 725, + X86_INS_VAESDEC = 726, + X86_INS_VAESENCLAST = 727, + X86_INS_VAESENC = 728, + X86_INS_VAESIMC = 729, + X86_INS_VAESKEYGENASSIST = 730, + X86_INS_VALIGND = 731, + X86_INS_VALIGNQ = 732, + X86_INS_VANDNPD = 733, + X86_INS_VANDNPS = 734, + X86_INS_VANDPD = 735, + X86_INS_VANDPS = 736, + X86_INS_VBLENDMPD = 737, + X86_INS_VBLENDMPS = 738, + X86_INS_VBLENDPD = 739, + X86_INS_VBLENDPS = 740, + X86_INS_VBLENDVPD = 741, + X86_INS_VBLENDVPS = 742, + X86_INS_VBROADCASTF128 = 743, + X86_INS_VBROADCASTI32X4 = 744, + X86_INS_VBROADCASTI64X4 = 745, + X86_INS_VBROADCASTSD = 746, + X86_INS_VBROADCASTSS = 747, + X86_INS_VCMPPD = 748, + X86_INS_VCMPPS = 749, + X86_INS_VCMPSD = 750, + X86_INS_VCMPSS = 751, + X86_INS_VCOMPRESSPD = 752, + X86_INS_VCOMPRESSPS = 753, + X86_INS_VCVTDQ2PD = 754, + X86_INS_VCVTDQ2PS = 755, + X86_INS_VCVTPD2DQX = 756, + X86_INS_VCVTPD2DQ = 757, + X86_INS_VCVTPD2PSX = 758, + X86_INS_VCVTPD2PS = 759, + X86_INS_VCVTPD2UDQ = 760, + X86_INS_VCVTPH2PS = 761, + X86_INS_VCVTPS2DQ = 762, + X86_INS_VCVTPS2PD = 763, + X86_INS_VCVTPS2PH = 764, + X86_INS_VCVTPS2UDQ = 765, + X86_INS_VCVTSD2SI = 766, + X86_INS_VCVTSD2USI = 767, + X86_INS_VCVTSS2SI = 768, + X86_INS_VCVTSS2USI = 769, + X86_INS_VCVTTPD2DQX = 770, + X86_INS_VCVTTPD2DQ = 771, + X86_INS_VCVTTPD2UDQ = 772, + X86_INS_VCVTTPS2DQ = 773, + X86_INS_VCVTTPS2UDQ = 774, + X86_INS_VCVTUDQ2PD = 775, + X86_INS_VCVTUDQ2PS = 776, + X86_INS_VDIVPD = 777, + X86_INS_VDIVPS = 778, + X86_INS_VDIVSD = 779, + X86_INS_VDIVSS = 780, + X86_INS_VDPPD = 781, + X86_INS_VDPPS = 782, + X86_INS_VERR = 783, + X86_INS_VERW = 784, + X86_INS_VEXP2PD = 785, + X86_INS_VEXP2PS = 786, + X86_INS_VEXPANDPD = 787, + X86_INS_VEXPANDPS = 788, + X86_INS_VEXTRACTF128 = 789, + X86_INS_VEXTRACTF32X4 = 790, + X86_INS_VEXTRACTF64X4 = 791, + X86_INS_VEXTRACTI128 = 792, + X86_INS_VEXTRACTI32X4 = 793, + X86_INS_VEXTRACTI64X4 = 794, + X86_INS_VEXTRACTPS = 795, + X86_INS_VFMADD132PD = 796, + X86_INS_VFMADD132PS = 797, + X86_INS_VFMADDPD = 798, + X86_INS_VFMADD213PD = 799, + X86_INS_VFMADD231PD = 800, + X86_INS_VFMADDPS = 801, + X86_INS_VFMADD213PS = 802, + X86_INS_VFMADD231PS = 803, + X86_INS_VFMADDSD = 804, + X86_INS_VFMADD213SD = 805, + X86_INS_VFMADD132SD = 806, + X86_INS_VFMADD231SD = 807, + X86_INS_VFMADDSS = 808, + X86_INS_VFMADD213SS = 809, + X86_INS_VFMADD132SS = 810, + X86_INS_VFMADD231SS = 811, + X86_INS_VFMADDSUB132PD = 812, + X86_INS_VFMADDSUB132PS = 813, + X86_INS_VFMADDSUBPD = 814, + X86_INS_VFMADDSUB213PD = 815, + X86_INS_VFMADDSUB231PD = 816, + X86_INS_VFMADDSUBPS = 817, + X86_INS_VFMADDSUB213PS = 818, + X86_INS_VFMADDSUB231PS = 819, + X86_INS_VFMSUB132PD = 820, + X86_INS_VFMSUB132PS = 821, + X86_INS_VFMSUBADD132PD = 822, + X86_INS_VFMSUBADD132PS = 823, + X86_INS_VFMSUBADDPD = 824, + X86_INS_VFMSUBADD213PD = 825, + X86_INS_VFMSUBADD231PD = 826, + X86_INS_VFMSUBADDPS = 827, + X86_INS_VFMSUBADD213PS = 828, + X86_INS_VFMSUBADD231PS = 829, + X86_INS_VFMSUBPD = 830, + X86_INS_VFMSUB213PD = 831, + X86_INS_VFMSUB231PD = 832, + X86_INS_VFMSUBPS = 833, + X86_INS_VFMSUB213PS = 834, + X86_INS_VFMSUB231PS = 835, + X86_INS_VFMSUBSD = 836, + X86_INS_VFMSUB213SD = 837, + X86_INS_VFMSUB132SD = 838, + X86_INS_VFMSUB231SD = 839, + X86_INS_VFMSUBSS = 840, + X86_INS_VFMSUB213SS = 841, + X86_INS_VFMSUB132SS = 842, + X86_INS_VFMSUB231SS = 843, + X86_INS_VFNMADD132PD = 844, + X86_INS_VFNMADD132PS = 845, + X86_INS_VFNMADDPD = 846, + X86_INS_VFNMADD213PD = 847, + X86_INS_VFNMADD231PD = 848, + X86_INS_VFNMADDPS = 849, + X86_INS_VFNMADD213PS = 850, + X86_INS_VFNMADD231PS = 851, + X86_INS_VFNMADDSD = 852, + X86_INS_VFNMADD213SD = 853, + X86_INS_VFNMADD132SD = 854, + X86_INS_VFNMADD231SD = 855, + X86_INS_VFNMADDSS = 856, + X86_INS_VFNMADD213SS = 857, + X86_INS_VFNMADD132SS = 858, + X86_INS_VFNMADD231SS = 859, + X86_INS_VFNMSUB132PD = 860, + X86_INS_VFNMSUB132PS = 861, + X86_INS_VFNMSUBPD = 862, + X86_INS_VFNMSUB213PD = 863, + X86_INS_VFNMSUB231PD = 864, + X86_INS_VFNMSUBPS = 865, + X86_INS_VFNMSUB213PS = 866, + X86_INS_VFNMSUB231PS = 867, + X86_INS_VFNMSUBSD = 868, + X86_INS_VFNMSUB213SD = 869, + X86_INS_VFNMSUB132SD = 870, + X86_INS_VFNMSUB231SD = 871, + X86_INS_VFNMSUBSS = 872, + X86_INS_VFNMSUB213SS = 873, + X86_INS_VFNMSUB132SS = 874, + X86_INS_VFNMSUB231SS = 875, + X86_INS_VFRCZPD = 876, + X86_INS_VFRCZPS = 877, + X86_INS_VFRCZSD = 878, + X86_INS_VFRCZSS = 879, + X86_INS_VORPD = 880, + X86_INS_VORPS = 881, + X86_INS_VXORPD = 882, + X86_INS_VXORPS = 883, + X86_INS_VGATHERDPD = 884, + X86_INS_VGATHERDPS = 885, + X86_INS_VGATHERPF0DPD = 886, + X86_INS_VGATHERPF0DPS = 887, + X86_INS_VGATHERPF0QPD = 888, + X86_INS_VGATHERPF0QPS = 889, + X86_INS_VGATHERPF1DPD = 890, + X86_INS_VGATHERPF1DPS = 891, + X86_INS_VGATHERPF1QPD = 892, + X86_INS_VGATHERPF1QPS = 893, + X86_INS_VGATHERQPD = 894, + X86_INS_VGATHERQPS = 895, + X86_INS_VHADDPD = 896, + X86_INS_VHADDPS = 897, + X86_INS_VHSUBPD = 898, + X86_INS_VHSUBPS = 899, + X86_INS_VINSERTF128 = 900, + X86_INS_VINSERTF32X4 = 901, + X86_INS_VINSERTF32X8 = 902, + X86_INS_VINSERTF64X2 = 903, + X86_INS_VINSERTF64X4 = 904, + X86_INS_VINSERTI128 = 905, + X86_INS_VINSERTI32X4 = 906, + X86_INS_VINSERTI32X8 = 907, + X86_INS_VINSERTI64X2 = 908, + X86_INS_VINSERTI64X4 = 909, + X86_INS_VINSERTPS = 910, + X86_INS_VLDDQU = 911, + X86_INS_VLDMXCSR = 912, + X86_INS_VMASKMOVDQU = 913, + X86_INS_VMASKMOVPD = 914, + X86_INS_VMASKMOVPS = 915, + X86_INS_VMAXPD = 916, + X86_INS_VMAXPS = 917, + X86_INS_VMAXSD = 918, + X86_INS_VMAXSS = 919, + X86_INS_VMCALL = 920, + X86_INS_VMCLEAR = 921, + X86_INS_VMFUNC = 922, + X86_INS_VMINPD = 923, + X86_INS_VMINPS = 924, + X86_INS_VMINSD = 925, + X86_INS_VMINSS = 926, + X86_INS_VMLAUNCH = 927, + X86_INS_VMLOAD = 928, + X86_INS_VMMCALL = 929, + X86_INS_VMOVQ = 930, + X86_INS_VMOVDDUP = 931, + X86_INS_VMOVD = 932, + X86_INS_VMOVDQA32 = 933, + X86_INS_VMOVDQA64 = 934, + X86_INS_VMOVDQA = 935, + X86_INS_VMOVDQU16 = 936, + X86_INS_VMOVDQU32 = 937, + X86_INS_VMOVDQU64 = 938, + X86_INS_VMOVDQU8 = 939, + X86_INS_VMOVDQU = 940, + X86_INS_VMOVHLPS = 941, + X86_INS_VMOVHPD = 942, + X86_INS_VMOVHPS = 943, + X86_INS_VMOVLHPS = 944, + X86_INS_VMOVLPD = 945, + X86_INS_VMOVLPS = 946, + X86_INS_VMOVMSKPD = 947, + X86_INS_VMOVMSKPS = 948, + X86_INS_VMOVNTDQA = 949, + X86_INS_VMOVNTDQ = 950, + X86_INS_VMOVNTPD = 951, + X86_INS_VMOVNTPS = 952, + X86_INS_VMOVSD = 953, + X86_INS_VMOVSHDUP = 954, + X86_INS_VMOVSLDUP = 955, + X86_INS_VMOVSS = 956, + X86_INS_VMOVUPD = 957, + X86_INS_VMOVUPS = 958, + X86_INS_VMPSADBW = 959, + X86_INS_VMPTRLD = 960, + X86_INS_VMPTRST = 961, + X86_INS_VMREAD = 962, + X86_INS_VMRESUME = 963, + X86_INS_VMRUN = 964, + X86_INS_VMSAVE = 965, + X86_INS_VMULPD = 966, + X86_INS_VMULPS = 967, + X86_INS_VMULSD = 968, + X86_INS_VMULSS = 969, + X86_INS_VMWRITE = 970, + X86_INS_VMXOFF = 971, + X86_INS_VMXON = 972, + X86_INS_VPABSB = 973, + X86_INS_VPABSD = 974, + X86_INS_VPABSQ = 975, + X86_INS_VPABSW = 976, + X86_INS_VPACKSSDW = 977, + X86_INS_VPACKSSWB = 978, + X86_INS_VPACKUSDW = 979, + X86_INS_VPACKUSWB = 980, + X86_INS_VPADDB = 981, + X86_INS_VPADDD = 982, + X86_INS_VPADDQ = 983, + X86_INS_VPADDSB = 984, + X86_INS_VPADDSW = 985, + X86_INS_VPADDUSB = 986, + X86_INS_VPADDUSW = 987, + X86_INS_VPADDW = 988, + X86_INS_VPALIGNR = 989, + X86_INS_VPANDD = 990, + X86_INS_VPANDND = 991, + X86_INS_VPANDNQ = 992, + X86_INS_VPANDN = 993, + X86_INS_VPANDQ = 994, + X86_INS_VPAND = 995, + X86_INS_VPAVGB = 996, + X86_INS_VPAVGW = 997, + X86_INS_VPBLENDD = 998, + X86_INS_VPBLENDMB = 999, + X86_INS_VPBLENDMD = 1000, + X86_INS_VPBLENDMQ = 1001, + X86_INS_VPBLENDMW = 1002, + X86_INS_VPBLENDVB = 1003, + X86_INS_VPBLENDW = 1004, + X86_INS_VPBROADCASTB = 1005, + X86_INS_VPBROADCASTD = 1006, + X86_INS_VPBROADCASTMB2Q = 1007, + X86_INS_VPBROADCASTMW2D = 1008, + X86_INS_VPBROADCASTQ = 1009, + X86_INS_VPBROADCASTW = 1010, + X86_INS_VPCLMULQDQ = 1011, + X86_INS_VPCMOV = 1012, + X86_INS_VPCMPB = 1013, + X86_INS_VPCMPD = 1014, + X86_INS_VPCMPEQB = 1015, + X86_INS_VPCMPEQD = 1016, + X86_INS_VPCMPEQQ = 1017, + X86_INS_VPCMPEQW = 1018, + X86_INS_VPCMPESTRI = 1019, + X86_INS_VPCMPESTRM = 1020, + X86_INS_VPCMPGTB = 1021, + X86_INS_VPCMPGTD = 1022, + X86_INS_VPCMPGTQ = 1023, + X86_INS_VPCMPGTW = 1024, + X86_INS_VPCMPISTRI = 1025, + X86_INS_VPCMPISTRM = 1026, + X86_INS_VPCMPQ = 1027, + X86_INS_VPCMPUB = 1028, + X86_INS_VPCMPUD = 1029, + X86_INS_VPCMPUQ = 1030, + X86_INS_VPCMPUW = 1031, + X86_INS_VPCMPW = 1032, + X86_INS_VPCOMB = 1033, + X86_INS_VPCOMD = 1034, + X86_INS_VPCOMPRESSD = 1035, + X86_INS_VPCOMPRESSQ = 1036, + X86_INS_VPCOMQ = 1037, + X86_INS_VPCOMUB = 1038, + X86_INS_VPCOMUD = 1039, + X86_INS_VPCOMUQ = 1040, + X86_INS_VPCOMUW = 1041, + X86_INS_VPCOMW = 1042, + X86_INS_VPCONFLICTD = 1043, + X86_INS_VPCONFLICTQ = 1044, + X86_INS_VPERM2F128 = 1045, + X86_INS_VPERM2I128 = 1046, + X86_INS_VPERMD = 1047, + X86_INS_VPERMI2D = 1048, + X86_INS_VPERMI2PD = 1049, + X86_INS_VPERMI2PS = 1050, + X86_INS_VPERMI2Q = 1051, + X86_INS_VPERMIL2PD = 1052, + X86_INS_VPERMIL2PS = 1053, + X86_INS_VPERMILPD = 1054, + X86_INS_VPERMILPS = 1055, + X86_INS_VPERMPD = 1056, + X86_INS_VPERMPS = 1057, + X86_INS_VPERMQ = 1058, + X86_INS_VPERMT2D = 1059, + X86_INS_VPERMT2PD = 1060, + X86_INS_VPERMT2PS = 1061, + X86_INS_VPERMT2Q = 1062, + X86_INS_VPEXPANDD = 1063, + X86_INS_VPEXPANDQ = 1064, + X86_INS_VPEXTRB = 1065, + X86_INS_VPEXTRD = 1066, + X86_INS_VPEXTRQ = 1067, + X86_INS_VPEXTRW = 1068, + X86_INS_VPGATHERDD = 1069, + X86_INS_VPGATHERDQ = 1070, + X86_INS_VPGATHERQD = 1071, + X86_INS_VPGATHERQQ = 1072, + X86_INS_VPHADDBD = 1073, + X86_INS_VPHADDBQ = 1074, + X86_INS_VPHADDBW = 1075, + X86_INS_VPHADDDQ = 1076, + X86_INS_VPHADDD = 1077, + X86_INS_VPHADDSW = 1078, + X86_INS_VPHADDUBD = 1079, + X86_INS_VPHADDUBQ = 1080, + X86_INS_VPHADDUBW = 1081, + X86_INS_VPHADDUDQ = 1082, + X86_INS_VPHADDUWD = 1083, + X86_INS_VPHADDUWQ = 1084, + X86_INS_VPHADDWD = 1085, + X86_INS_VPHADDWQ = 1086, + X86_INS_VPHADDW = 1087, + X86_INS_VPHMINPOSUW = 1088, + X86_INS_VPHSUBBW = 1089, + X86_INS_VPHSUBDQ = 1090, + X86_INS_VPHSUBD = 1091, + X86_INS_VPHSUBSW = 1092, + X86_INS_VPHSUBWD = 1093, + X86_INS_VPHSUBW = 1094, + X86_INS_VPINSRB = 1095, + X86_INS_VPINSRD = 1096, + X86_INS_VPINSRQ = 1097, + X86_INS_VPINSRW = 1098, + X86_INS_VPLZCNTD = 1099, + X86_INS_VPLZCNTQ = 1100, + X86_INS_VPMACSDD = 1101, + X86_INS_VPMACSDQH = 1102, + X86_INS_VPMACSDQL = 1103, + X86_INS_VPMACSSDD = 1104, + X86_INS_VPMACSSDQH = 1105, + X86_INS_VPMACSSDQL = 1106, + X86_INS_VPMACSSWD = 1107, + X86_INS_VPMACSSWW = 1108, + X86_INS_VPMACSWD = 1109, + X86_INS_VPMACSWW = 1110, + X86_INS_VPMADCSSWD = 1111, + X86_INS_VPMADCSWD = 1112, + X86_INS_VPMADDUBSW = 1113, + X86_INS_VPMADDWD = 1114, + X86_INS_VPMASKMOVD = 1115, + X86_INS_VPMASKMOVQ = 1116, + X86_INS_VPMAXSB = 1117, + X86_INS_VPMAXSD = 1118, + X86_INS_VPMAXSQ = 1119, + X86_INS_VPMAXSW = 1120, + X86_INS_VPMAXUB = 1121, + X86_INS_VPMAXUD = 1122, + X86_INS_VPMAXUQ = 1123, + X86_INS_VPMAXUW = 1124, + X86_INS_VPMINSB = 1125, + X86_INS_VPMINSD = 1126, + X86_INS_VPMINSQ = 1127, + X86_INS_VPMINSW = 1128, + X86_INS_VPMINUB = 1129, + X86_INS_VPMINUD = 1130, + X86_INS_VPMINUQ = 1131, + X86_INS_VPMINUW = 1132, + X86_INS_VPMOVDB = 1133, + X86_INS_VPMOVDW = 1134, + X86_INS_VPMOVM2B = 1135, + X86_INS_VPMOVM2D = 1136, + X86_INS_VPMOVM2Q = 1137, + X86_INS_VPMOVM2W = 1138, + X86_INS_VPMOVMSKB = 1139, + X86_INS_VPMOVQB = 1140, + X86_INS_VPMOVQD = 1141, + X86_INS_VPMOVQW = 1142, + X86_INS_VPMOVSDB = 1143, + X86_INS_VPMOVSDW = 1144, + X86_INS_VPMOVSQB = 1145, + X86_INS_VPMOVSQD = 1146, + X86_INS_VPMOVSQW = 1147, + X86_INS_VPMOVSXBD = 1148, + X86_INS_VPMOVSXBQ = 1149, + X86_INS_VPMOVSXBW = 1150, + X86_INS_VPMOVSXDQ = 1151, + X86_INS_VPMOVSXWD = 1152, + X86_INS_VPMOVSXWQ = 1153, + X86_INS_VPMOVUSDB = 1154, + X86_INS_VPMOVUSDW = 1155, + X86_INS_VPMOVUSQB = 1156, + X86_INS_VPMOVUSQD = 1157, + X86_INS_VPMOVUSQW = 1158, + X86_INS_VPMOVZXBD = 1159, + X86_INS_VPMOVZXBQ = 1160, + X86_INS_VPMOVZXBW = 1161, + X86_INS_VPMOVZXDQ = 1162, + X86_INS_VPMOVZXWD = 1163, + X86_INS_VPMOVZXWQ = 1164, + X86_INS_VPMULDQ = 1165, + X86_INS_VPMULHRSW = 1166, + X86_INS_VPMULHUW = 1167, + X86_INS_VPMULHW = 1168, + X86_INS_VPMULLD = 1169, + X86_INS_VPMULLQ = 1170, + X86_INS_VPMULLW = 1171, + X86_INS_VPMULUDQ = 1172, + X86_INS_VPORD = 1173, + X86_INS_VPORQ = 1174, + X86_INS_VPOR = 1175, + X86_INS_VPPERM = 1176, + X86_INS_VPROTB = 1177, + X86_INS_VPROTD = 1178, + X86_INS_VPROTQ = 1179, + X86_INS_VPROTW = 1180, + X86_INS_VPSADBW = 1181, + X86_INS_VPSCATTERDD = 1182, + X86_INS_VPSCATTERDQ = 1183, + X86_INS_VPSCATTERQD = 1184, + X86_INS_VPSCATTERQQ = 1185, + X86_INS_VPSHAB = 1186, + X86_INS_VPSHAD = 1187, + X86_INS_VPSHAQ = 1188, + X86_INS_VPSHAW = 1189, + X86_INS_VPSHLB = 1190, + X86_INS_VPSHLD = 1191, + X86_INS_VPSHLQ = 1192, + X86_INS_VPSHLW = 1193, + X86_INS_VPSHUFB = 1194, + X86_INS_VPSHUFD = 1195, + X86_INS_VPSHUFHW = 1196, + X86_INS_VPSHUFLW = 1197, + X86_INS_VPSIGNB = 1198, + X86_INS_VPSIGND = 1199, + X86_INS_VPSIGNW = 1200, + X86_INS_VPSLLDQ = 1201, + X86_INS_VPSLLD = 1202, + X86_INS_VPSLLQ = 1203, + X86_INS_VPSLLVD = 1204, + X86_INS_VPSLLVQ = 1205, + X86_INS_VPSLLW = 1206, + X86_INS_VPSRAD = 1207, + X86_INS_VPSRAQ = 1208, + X86_INS_VPSRAVD = 1209, + X86_INS_VPSRAVQ = 1210, + X86_INS_VPSRAW = 1211, + X86_INS_VPSRLDQ = 1212, + X86_INS_VPSRLD = 1213, + X86_INS_VPSRLQ = 1214, + X86_INS_VPSRLVD = 1215, + X86_INS_VPSRLVQ = 1216, + X86_INS_VPSRLW = 1217, + X86_INS_VPSUBB = 1218, + X86_INS_VPSUBD = 1219, + X86_INS_VPSUBQ = 1220, + X86_INS_VPSUBSB = 1221, + X86_INS_VPSUBSW = 1222, + X86_INS_VPSUBUSB = 1223, + X86_INS_VPSUBUSW = 1224, + X86_INS_VPSUBW = 1225, + X86_INS_VPTESTMD = 1226, + X86_INS_VPTESTMQ = 1227, + X86_INS_VPTESTNMD = 1228, + X86_INS_VPTESTNMQ = 1229, + X86_INS_VPTEST = 1230, + X86_INS_VPUNPCKHBW = 1231, + X86_INS_VPUNPCKHDQ = 1232, + X86_INS_VPUNPCKHQDQ = 1233, + X86_INS_VPUNPCKHWD = 1234, + X86_INS_VPUNPCKLBW = 1235, + X86_INS_VPUNPCKLDQ = 1236, + X86_INS_VPUNPCKLQDQ = 1237, + X86_INS_VPUNPCKLWD = 1238, + X86_INS_VPXORD = 1239, + X86_INS_VPXORQ = 1240, + X86_INS_VPXOR = 1241, + X86_INS_VRCP14PD = 1242, + X86_INS_VRCP14PS = 1243, + X86_INS_VRCP14SD = 1244, + X86_INS_VRCP14SS = 1245, + X86_INS_VRCP28PD = 1246, + X86_INS_VRCP28PS = 1247, + X86_INS_VRCP28SD = 1248, + X86_INS_VRCP28SS = 1249, + X86_INS_VRCPPS = 1250, + X86_INS_VRCPSS = 1251, + X86_INS_VRNDSCALEPD = 1252, + X86_INS_VRNDSCALEPS = 1253, + X86_INS_VRNDSCALESD = 1254, + X86_INS_VRNDSCALESS = 1255, + X86_INS_VROUNDPD = 1256, + X86_INS_VROUNDPS = 1257, + X86_INS_VROUNDSD = 1258, + X86_INS_VROUNDSS = 1259, + X86_INS_VRSQRT14PD = 1260, + X86_INS_VRSQRT14PS = 1261, + X86_INS_VRSQRT14SD = 1262, + X86_INS_VRSQRT14SS = 1263, + X86_INS_VRSQRT28PD = 1264, + X86_INS_VRSQRT28PS = 1265, + X86_INS_VRSQRT28SD = 1266, + X86_INS_VRSQRT28SS = 1267, + X86_INS_VRSQRTPS = 1268, + X86_INS_VRSQRTSS = 1269, + X86_INS_VSCATTERDPD = 1270, + X86_INS_VSCATTERDPS = 1271, + X86_INS_VSCATTERPF0DPD = 1272, + X86_INS_VSCATTERPF0DPS = 1273, + X86_INS_VSCATTERPF0QPD = 1274, + X86_INS_VSCATTERPF0QPS = 1275, + X86_INS_VSCATTERPF1DPD = 1276, + X86_INS_VSCATTERPF1DPS = 1277, + X86_INS_VSCATTERPF1QPD = 1278, + X86_INS_VSCATTERPF1QPS = 1279, + X86_INS_VSCATTERQPD = 1280, + X86_INS_VSCATTERQPS = 1281, + X86_INS_VSHUFPD = 1282, + X86_INS_VSHUFPS = 1283, + X86_INS_VSQRTPD = 1284, + X86_INS_VSQRTPS = 1285, + X86_INS_VSQRTSD = 1286, + X86_INS_VSQRTSS = 1287, + X86_INS_VSTMXCSR = 1288, + X86_INS_VSUBPD = 1289, + X86_INS_VSUBPS = 1290, + X86_INS_VSUBSD = 1291, + X86_INS_VSUBSS = 1292, + X86_INS_VTESTPD = 1293, + X86_INS_VTESTPS = 1294, + X86_INS_VUNPCKHPD = 1295, + X86_INS_VUNPCKHPS = 1296, + X86_INS_VUNPCKLPD = 1297, + X86_INS_VUNPCKLPS = 1298, + X86_INS_VZEROALL = 1299, + X86_INS_VZEROUPPER = 1300, + X86_INS_WAIT = 1301, + X86_INS_WBINVD = 1302, + X86_INS_WRFSBASE = 1303, + X86_INS_WRGSBASE = 1304, + X86_INS_WRMSR = 1305, + X86_INS_XABORT = 1306, + X86_INS_XACQUIRE = 1307, + X86_INS_XBEGIN = 1308, + X86_INS_XCHG = 1309, + X86_INS_XCRYPTCBC = 1310, + X86_INS_XCRYPTCFB = 1311, + X86_INS_XCRYPTCTR = 1312, + X86_INS_XCRYPTECB = 1313, + X86_INS_XCRYPTOFB = 1314, + X86_INS_XEND = 1315, + X86_INS_XGETBV = 1316, + X86_INS_XLATB = 1317, + X86_INS_XRELEASE = 1318, + X86_INS_XRSTOR = 1319, + X86_INS_XRSTOR64 = 1320, + X86_INS_XRSTORS = 1321, + X86_INS_XRSTORS64 = 1322, + X86_INS_XSAVE = 1323, + X86_INS_XSAVE64 = 1324, + X86_INS_XSAVEC = 1325, + X86_INS_XSAVEC64 = 1326, + X86_INS_XSAVEOPT = 1327, + X86_INS_XSAVEOPT64 = 1328, + X86_INS_XSAVES = 1329, + X86_INS_XSAVES64 = 1330, + X86_INS_XSETBV = 1331, + X86_INS_XSHA1 = 1332, + X86_INS_XSHA256 = 1333, + X86_INS_XSTORE = 1334, + X86_INS_XTEST = 1335, + X86_INS_FDISI8087_NOP = 1336, + X86_INS_FENI8087_NOP = 1337, + X86_INS_ENDING = 1338, + +}; From 48ce4164b3cf5a5311b7bef97c6967eef895b424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matheus=20C=2E=20Fran=C3=A7a?= Date: Thu, 23 Mar 2023 16:15:33 -0300 Subject: [PATCH 11/26] new binding --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c817cfda..87d8a159 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Unicorn offers some unparalleled features: - Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, PowerPC, RISCV, SPARC, S390X, TriCore and X86 (16, 32, 64-bit) - Clean/simple/lightweight/intuitive architecture-neutral API -- Implemented in pure C language, with bindings for Crystal, Clojure, Visual Basic, Perl, Rust, Ruby, Python, Java, .NET, Go, Delphi/Free Pascal, Haskell, Pharo, and Lua. +- Implemented in pure C language, with bindings for Crystal, Clojure, Visual Basic, Perl, Rust, Ruby, Python, Java, .NET, Go, Delphi/Free Pascal, Haskell, Pharo, Lua and Zig. - Native support for Windows & *nix (with Mac OSX, Linux, Android, *BSD & Solaris confirmed) - High performance via Just-In-Time compilation - Support for fine-grained instrumentation at various levels From 81a85368419febf01e47bc7b7f66dc391ed28555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matheus=20C=2E=20Fran=C3=A7a?= Date: Thu, 23 Mar 2023 16:16:18 -0300 Subject: [PATCH 12/26] Update Cargo.toml exclude new binding on rust build --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3d6d388d..86ff6dc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ exclude = [ "/bindings/python", "/bindings/ruby", "/bindings/vb6", + "/bindings/zig", "/samples", "/tests", ] @@ -40,4 +41,4 @@ pkg-config = { version = "0.3" } [features] default = [] -dynamic_linkage = [] \ No newline at end of file +dynamic_linkage = [] From f2a236126f6a6b2e098639738d58608ef2229449 Mon Sep 17 00:00:00 2001 From: Xeonacid Date: Mon, 27 Mar 2023 01:15:56 +0800 Subject: [PATCH 13/26] Add missing import const in python binding (#1807) --- bindings/python/unicorn/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/unicorn/__init__.py b/bindings/python/unicorn/__init__.py index 219de992..fe47b081 100644 --- a/bindings/python/unicorn/__init__.py +++ b/bindings/python/unicorn/__init__.py @@ -1,4 +1,4 @@ # Unicorn Python bindings, by Nguyen Anh Quynnh -from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const, riscv_const +from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const, riscv_const, s390x_const, tricore_const from .unicorn_const import * from .unicorn import Uc, uc_version, uc_arch_supported, version_bind, debug, UcError, __version__ From 4b327baaf7feab99b95cea853b4e1da01452a816 Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Wed, 28 Sep 2022 18:10:49 +0200 Subject: [PATCH 14/26] make unicorn use the physical addresses This allows to emulate code witch fully uses the MMU. This is necesary to allow full system emulation. --- qemu/accel/tcg/cputlb.c | 499 +++++++++++++++++++---------------- qemu/include/exec/cpu-defs.h | 5 +- 2 files changed, 280 insertions(+), 224 deletions(-) diff --git a/qemu/accel/tcg/cputlb.c b/qemu/accel/tcg/cputlb.c index d591e9d1..659faf3f 100644 --- a/qemu/accel/tcg/cputlb.c +++ b/qemu/accel/tcg/cputlb.c @@ -893,6 +893,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, /* Now calculate the new entry */ tn.addend = addend - vaddr_page; + tn.paddr = paddr_page; if (prot & PAGE_READ) { tn.addr_read = address; if (wp_flags & BP_MEM_READ) { @@ -1423,6 +1424,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t index = tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); target_ulong tlb_addr = code_read ? entry->addr_code : entry->addr_read; + target_ulong paddr; const size_t tlb_off = code_read ? offsetof(CPUTLBEntry, addr_code) : offsetof(CPUTLBEntry, addr_read); const MMUAccessType access_type = @@ -1436,146 +1438,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, bool handled; HOOK_FOREACH_VAR_DECLARE; struct uc_struct *uc = env->uc; - MemoryRegion *mr = find_memory_region(uc, addr); - - // memory might be still unmapped while reading or fetching - if (mr == NULL) { - handled = false; - // if there is already an unhandled eror, skip callbacks. - if (uc->invalid_error == UC_ERR_OK) { - if (code_read) { - // code fetching - error_code = UC_ERR_FETCH_UNMAPPED; - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_UNMAPPED) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, addr)) - continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, size, 0, hook->user_data))) - break; - - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; - } - } else { - // data reading - error_code = UC_ERR_READ_UNMAPPED; - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_UNMAPPED) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, addr)) - continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, size, 0, hook->user_data))) - break; - - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; - } - } - } else { - error_code = uc->invalid_error; - } - - if (handled) { - uc->invalid_error = UC_ERR_OK; - mr = find_memory_region(uc, addr); - if (mr == NULL) { - uc->invalid_error = UC_ERR_MAP; - cpu_exit(uc->cpu); - // XXX(@lazymio): We have to exit early so that the target register won't be overwritten - // because qemu might generate tcg code like: - // qemu_ld_i64 x0,x1,leq,8 sync: 0 dead: 0 1 - // where we don't have a change to recover x0 value - cpu_loop_exit(uc->cpu); - return 0; - } - } else { - uc->invalid_addr = addr; - uc->invalid_error = error_code; - // printf("***** Invalid fetch (unmapped memory) at " TARGET_FMT_lx "\n", addr); - cpu_exit(uc->cpu); - // See comments above - cpu_loop_exit(uc->cpu); - return 0; - } - } - - // now it is read on mapped memory - if (!code_read) { - // this is date reading - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, addr)) - continue; - ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, size, 0, hook->user_data); - - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; - } - - // callback on non-readable memory - if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable - handled = false; - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_PROT) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, addr)) - continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, size, 0, hook->user_data))) - break; - - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; - } - - if (handled) { - uc->invalid_error = UC_ERR_OK; - } else { - uc->invalid_addr = addr; - uc->invalid_error = UC_ERR_READ_PROT; - // printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr); - cpu_exit(uc->cpu); - // See comments above - cpu_loop_exit(uc->cpu); - return 0; - } - } - } else { - // code fetching - // Unicorn: callback on fetch from NX - if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable - handled = false; - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_PROT) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, addr)) - continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, size, 0, hook->user_data))) - break; - - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; - } - - if (handled) { - uc->invalid_error = UC_ERR_OK; - } else { - uc->invalid_addr = addr; - uc->invalid_error = UC_ERR_FETCH_PROT; - // printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr); - cpu_exit(uc->cpu); - // See comments above - cpu_loop_exit(uc->cpu); - return 0; - } - } - } + MemoryRegion *mr; /* Handle CPU specific unaligned behaviour */ if (addr & ((1 << a_bits) - 1)) { @@ -1596,6 +1459,173 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, tlb_addr &= ~TLB_INVALID_MASK; } + paddr = entry->paddr | (addr & ~TARGET_PAGE_MASK); + mr = find_memory_region(uc, paddr); + + // memory might be still unmapped while reading or fetching + if (mr == NULL) { + handled = false; + // if there is already an unhandled eror, skip callbacks. + if (uc->invalid_error == UC_ERR_OK) { + if (code_read) { + // code fetching + error_code = UC_ERR_FETCH_UNMAPPED; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_UNMAPPED) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, paddr, size, 0, hook->user_data))) + break; + + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } + } else { + // data reading + error_code = UC_ERR_READ_UNMAPPED; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_UNMAPPED) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, paddr, size, 0, hook->user_data))) + break; + + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } + } + } else { + error_code = uc->invalid_error; + } + + if (handled) { + uc->invalid_error = UC_ERR_OK; + /* If the TLB entry is for a different page, reload and try again. */ + if (!tlb_hit(env->uc, tlb_addr, addr)) { + if (!victim_tlb_hit(env, mmu_idx, index, tlb_off, + addr & TARGET_PAGE_MASK)) { + tlb_fill(env_cpu(env), addr, size, + access_type, mmu_idx, retaddr); + index = tlb_index(env, mmu_idx, addr); + entry = tlb_entry(env, mmu_idx, addr); + } + tlb_addr = code_read ? entry->addr_code : entry->addr_read; + tlb_addr &= ~TLB_INVALID_MASK; + } + paddr = entry->paddr | (addr & ~TARGET_PAGE_MASK); + mr = find_memory_region(uc, paddr); + if (mr == NULL) { + uc->invalid_error = UC_ERR_MAP; + cpu_exit(uc->cpu); + // XXX(@lazymio): We have to exit early so that the target register won't be overwritten + // because qemu might generate tcg code like: + // qemu_ld_i64 x0,x1,leq,8 sync: 0 dead: 0 1 + // where we don't have a change to recover x0 value + cpu_loop_exit(uc->cpu); + return 0; + } + } else { + uc->invalid_addr = paddr; + uc->invalid_error = error_code; + // printf("***** Invalid fetch (unmapped memory) at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); + return 0; + } + } + + // now it is read on mapped memory + if (!code_read) { + // this is date reading + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, paddr, size, 0, hook->user_data); + + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } + + // callback on non-readable memory + if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_PROT) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, paddr, size, 0, hook->user_data))) + break; + + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } + + if (handled) { + uc->invalid_error = UC_ERR_OK; + /* If the TLB entry is for a different page, reload and try again. */ + if (!tlb_hit(env->uc, tlb_addr, addr)) { + if (!victim_tlb_hit(env, mmu_idx, index, tlb_off, + addr & TARGET_PAGE_MASK)) { + tlb_fill(env_cpu(env), addr, size, + access_type, mmu_idx, retaddr); + index = tlb_index(env, mmu_idx, addr); + entry = tlb_entry(env, mmu_idx, addr); + } + tlb_addr = code_read ? entry->addr_code : entry->addr_read; + tlb_addr &= ~TLB_INVALID_MASK; + } + } else { + uc->invalid_addr = paddr; + uc->invalid_error = UC_ERR_READ_PROT; + // printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); + return 0; + } + } + } else { + // code fetching + // Unicorn: callback on fetch from NX + if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_PROT) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, paddr, size, 0, hook->user_data))) + break; + + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } + + if (handled) { + uc->invalid_error = UC_ERR_OK; + } else { + uc->invalid_addr = paddr; + uc->invalid_error = UC_ERR_FETCH_PROT; + // printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); + return 0; + } + } + } + /* Handle anything that isn't just a straight memory access. */ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { CPUIOTLBEntry *iotlbentry; @@ -1678,9 +1708,9 @@ _out: HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_AFTER) { if (hook->to_delete) continue; - if (!HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, paddr)) continue; - ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, addr, size, res, hook->user_data); + ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, paddr, size, res, hook->user_data); // the last callback may already asked to stop emulation if (uc->stop_request) @@ -1986,6 +2016,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, uintptr_t index = tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); target_ulong tlb_addr = tlb_addr_write(entry); + target_ulong paddr; const size_t tlb_off = offsetof(CPUTLBEntry, addr_write); unsigned a_bits = get_alignment_bits(get_memop(oi)); void *haddr; @@ -1994,86 +2025,6 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, bool handled; MemoryRegion *mr; - if (!uc->size_recur_mem) { // disabling write callback if in recursive call - // Unicorn: callback on memory write - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, addr)) - continue; - ((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, size, val, hook->user_data); - - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; - } - } - - // Load the latest memory mapping. - mr = find_memory_region(uc, addr); - - // Unicorn: callback on invalid memory - if (mr == NULL) { - handled = false; - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_UNMAPPED) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, addr)) - continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_UNMAPPED, addr, size, val, hook->user_data))) - break; - - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; - } - - if (!handled) { - // save error & quit - uc->invalid_addr = addr; - uc->invalid_error = UC_ERR_WRITE_UNMAPPED; - // printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr); - cpu_exit(uc->cpu); - return; - } else { - uc->invalid_error = UC_ERR_OK; - mr = find_memory_region(uc, addr); - if (mr == NULL) { - uc->invalid_error = UC_ERR_MAP; - cpu_exit(uc->cpu); - return; - } - } - } - - // Unicorn: callback on non-writable memory - if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable - // printf("not writable memory???\n"); - handled = false; - HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_PROT) { - if (hook->to_delete) - continue; - if (!HOOK_BOUND_CHECK(hook, addr)) - continue; - if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_PROT, addr, size, val, hook->user_data))) - break; - - // the last callback may already asked to stop emulation - if (uc->stop_request) - break; - } - - if (handled) { - uc->invalid_error = UC_ERR_OK; - } else { - uc->invalid_addr = addr; - uc->invalid_error = UC_ERR_WRITE_PROT; - // printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr); - cpu_exit(uc->cpu); - return; - } - } - /* Handle CPU specific unaligned behaviour */ if (addr & ((1 << a_bits) - 1)) { cpu_unaligned_access(env_cpu(env), addr, MMU_DATA_STORE, @@ -2092,6 +2043,110 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK; } + // Load the latest memory mapping. + paddr = entry->paddr | (addr & ~TARGET_PAGE_MASK); + mr = find_memory_region(uc, paddr); + + if (!uc->size_recur_mem) { // disabling write callback if in recursive call + // Unicorn: callback on memory write + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + ((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, paddr, size, val, hook->user_data); + + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } + } + + // Unicorn: callback on invalid memory + if (mr == NULL) { + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_UNMAPPED) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_UNMAPPED, paddr, size, val, hook->user_data))) + break; + + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } + + if (!handled) { + // save error & quit + uc->invalid_addr = paddr; + uc->invalid_error = UC_ERR_WRITE_UNMAPPED; + // printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->cpu); + return; + } else { + uc->invalid_error = UC_ERR_OK; + /* If the TLB entry is for a different page, reload and try again. */ + if (!tlb_hit(env->uc, tlb_addr, addr)) { + if (!victim_tlb_hit(env, mmu_idx, index, tlb_off, + addr & TARGET_PAGE_MASK)) { + tlb_fill(env_cpu(env), addr, size, MMU_DATA_STORE, + mmu_idx, retaddr); + index = tlb_index(env, mmu_idx, addr); + entry = tlb_entry(env, mmu_idx, addr); + } + tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK; + } + paddr = entry->paddr | (addr & ~TARGET_PAGE_MASK); + mr = find_memory_region(uc, paddr); + if (mr == NULL) { + uc->invalid_error = UC_ERR_MAP; + cpu_exit(uc->cpu); + return; + } + } + } + + // Unicorn: callback on non-writable memory + if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable + // printf("not writable memory???\n"); + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_PROT) { + if (hook->to_delete) + continue; + if (!HOOK_BOUND_CHECK(hook, paddr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_PROT, addr, size, val, hook->user_data))) + break; + + // the last callback may already asked to stop emulation + if (uc->stop_request) + break; + } + + if (handled) { + /* If the TLB entry is for a different page, reload and try again. */ + if (!tlb_hit(env->uc, tlb_addr, addr)) { + if (!victim_tlb_hit(env, mmu_idx, index, tlb_off, + addr & TARGET_PAGE_MASK)) { + tlb_fill(env_cpu(env), addr, size, MMU_DATA_STORE, + mmu_idx, retaddr); + index = tlb_index(env, mmu_idx, addr); + entry = tlb_entry(env, mmu_idx, addr); + } + tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK; + } + uc->invalid_error = UC_ERR_OK; + } else { + uc->invalid_addr = addr; + uc->invalid_error = UC_ERR_WRITE_PROT; + // printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->cpu); + return; + } + } + /* Handle anything that isn't just a straight memory access. */ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { CPUIOTLBEntry *iotlbentry; diff --git a/qemu/include/exec/cpu-defs.h b/qemu/include/exec/cpu-defs.h index eceaf157..8c42b4fa 100644 --- a/qemu/include/exec/cpu-defs.h +++ b/qemu/include/exec/cpu-defs.h @@ -77,9 +77,9 @@ typedef uint64_t target_ulong; #define CPU_VTLB_SIZE 8 #if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32 -#define CPU_TLB_ENTRY_BITS 4 -#else #define CPU_TLB_ENTRY_BITS 5 +#else +#define CPU_TLB_ENTRY_BITS 6 #endif #define CPU_TLB_DYN_MIN_BITS 6 @@ -112,6 +112,7 @@ typedef struct CPUTLBEntry { target_ulong addr_read; target_ulong addr_write; target_ulong addr_code; + target_ulong paddr; /* Addend to virtual address to get host address. IO accesses use the corresponding iotlb value. */ uintptr_t addend; From f2eb1f4711da8393f6b9ca5b3cd91dc5c254687e Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Thu, 29 Sep 2022 11:05:25 +0200 Subject: [PATCH 15/26] i386 mmu hack: Allow emulate usermode without mmu This basicaly mappes virtual addresses to physical addresses 1:1 when the mmu is disabled in the cpu. So you can use the full 64 bit addressspace without required to configure the mmu. --- qemu/target/i386/excp_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qemu/target/i386/excp_helper.c b/qemu/target/i386/excp_helper.c index f658c819..9a773bbb 100644 --- a/qemu/target/i386/excp_helper.c +++ b/qemu/target/i386/excp_helper.c @@ -635,7 +635,12 @@ do_check_protect_pse36: /* align to page_size */ pte &= PG_ADDRESS_MASK & ~(page_size - 1); page_offset = addr & (page_size - 1); - paddr = get_hphys(cs, pte + page_offset, is_write1, &prot); + /* HACK allow full 64 bit mapping in u64 without paging */ + if (env->cr[0] & CR0_PG_MASK) { + paddr = get_hphys(cs, pte + page_offset, is_write1, &prot); + } else { + paddr = addr; + } /* Even if 4MB pages, we map only one 4KB page in the cache to avoid filling it too fast */ @@ -643,11 +648,6 @@ do_check_protect_pse36: paddr &= TARGET_PAGE_MASK; assert(prot & (1 << is_write1)); - // Unicorn: indentity map guest virtual address to host virtual address - vaddr = addr & TARGET_PAGE_MASK; - paddr = vaddr; - //printf(">>> map address %"PRIx64" to %"PRIx64"\n", vaddr, paddr); - tlb_set_page_with_attrs(cs, vaddr, paddr, cpu_get_mem_attrs(env), prot, mmu_idx, page_size); return 0; From 7f1eb4532dc4570d34ad51294a1fb91e452e24b9 Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Thu, 6 Oct 2022 15:53:25 +0200 Subject: [PATCH 16/26] add basic mmu tests Some simple tests for diffrent mmu. Basicly add some tlb entries, enable the mmu try to read from virtual address The aarm64 test was provided by imre-kis-arm in #1718 --- tests/unit/test_arm64.c | 101 ++++++++++++++++++++++++++++++++ tests/unit/test_riscv.c | 71 ++++++++++++++++++++++ tests/unit/test_x86.c | 126 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 298 insertions(+) diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index e82869fd..8fcc9f04 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -372,6 +372,106 @@ static void test_arm64_block_invalid_mem_read_write_sync(void) OK(uc_close(uc)); } +static void test_arm64_mmu(void) +{ + uc_engine *uc; + char *data; + char tlbe[8]; + uint64_t x0, x1, x2; + /* + * Not exact the binary, but aarch64-linux-gnu-as generate this code and reference sometimes data after ttb0_base. + * // Read data from physical address + * ldr X0, =0x40000000 + * ldr X1, [X0] + + * // Initialize translation table control registers + * ldr X0, =0x180803F20 + * msr TCR_EL1, X0 + * ldr X0, =0xFFFFFFFF + * msr MAIR_EL1, X0 + + * // Set translation table + * adr X0, ttb0_base + * msr TTBR0_EL1, X0 + + * // Enable caches and the MMU + * mrs X0, SCTLR_EL1 + * orr X0, X0, #(0x1 << 2) // The C bit (data cache). + * orr X0, X0, #(0x1 << 12) // The I bit (instruction cache) + * orr X0, X0, #0x1 // The M bit (MMU). + * msr SCTLR_EL1, X0 + * dsb SY + * isb + + * // Read the same memory area through virtual address + * ldr X0, =0x80000000 + * ldr X2, [X0] + * + * // Stop + * b . + */ + char code[] = "\x00\x81\x00\x58\x01\x00\x40\xf9\x00\x81\x00\x58\x40\x20\x18\xd5\x00\x81\x00\x58\x00\xa2\x18\xd5\x40\x7f\x00\x10\x00\x20\x18\xd5\x00\x10\x38\xd5\x00\x00\x7e\xb2\x00\x00\x74\xb2\x00\x00\x40\xb2\x00\x10\x18\xd5\x9f\x3f\x03\xd5\xdf\x3f\x03\xd5\xe0\x7f\x00\x58\x02\x00\x40\xf9\x00\x00\x00\x14\x1f\x20\x03\xd5\x1f\x20\x03\xd5\x1F\x20\x03\xD5\x1F\x20\x03\xD5"; + + data = malloc(0x1000); + TEST_CHECK(data != NULL); + + OK(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc)); + OK(uc_mem_map(uc, 0, 0x2000, UC_PROT_ALL)); + OK(uc_mem_write(uc, 0, code, sizeof(code) - 1)); + + // generate tlb entries + tlbe[0] = 0x41; + tlbe[1] = 0x07; + tlbe[2] = 0; + tlbe[3] = 0; + tlbe[4] = 0; + tlbe[5] = 0; + tlbe[6] = 0; + tlbe[7] = 0; + OK(uc_mem_write(uc, 0x1000, tlbe, sizeof(tlbe))); + tlbe[3] = 0x40; + OK(uc_mem_write(uc, 0x1008, tlbe, sizeof(tlbe))); + OK(uc_mem_write(uc, 0x1010, tlbe, sizeof(tlbe))); + OK(uc_mem_write(uc, 0x1018, tlbe, sizeof(tlbe))); + + //mentioned data referenced by the asm generated my aarch64-linux-gnu-as + tlbe[0] = 0; + tlbe[1] = 0; + OK(uc_mem_write(uc, 0x1020, tlbe, sizeof(tlbe))); + tlbe[0] = 0x20; + tlbe[1] = 0x3f; + tlbe[2] = 0x80; + tlbe[3] = 0x80; + tlbe[4] = 0x1; + OK(uc_mem_write(uc, 0x1028, tlbe, sizeof(tlbe))); + tlbe[0] = 0xff; + tlbe[1] = 0xff; + tlbe[2] = 0xff; + tlbe[3] = 0xff; + tlbe[4] = 0x00; + OK(uc_mem_write(uc, 0x1030, tlbe, sizeof(tlbe))); + tlbe[0] = 0x00; + tlbe[1] = 0x00; + tlbe[2] = 0x00; + tlbe[3] = 0x80; + OK(uc_mem_write(uc, 0x1038, tlbe, sizeof(tlbe))); + + for (size_t i = 0; i < 0x1000; i++) { + data[i] = 0x44; + } + OK(uc_mem_map_ptr(uc, 0x40000000, 0x1000, UC_PROT_READ, data)); + + OK(uc_emu_start(uc, 0, 0x44, 0, 0)); + OK(uc_reg_read(uc, UC_ARM64_REG_X0, &x0)); + OK(uc_reg_read(uc, UC_ARM64_REG_X1, &x1)); + OK(uc_reg_read(uc, UC_ARM64_REG_X2, &x2)); + + TEST_CHECK(x0 == 0x80000000); + TEST_CHECK(x1 == 0x4444444444444444); + TEST_CHECK(x2 == 0x4444444444444444); + free(data); +} + TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"test_arm64_code_patching", test_arm64_code_patching}, {"test_arm64_code_patching_count", test_arm64_code_patching_count}, @@ -385,4 +485,5 @@ TEST_LIST = {{"test_arm64_until", test_arm64_until}, {"test_arm64_block_sync_pc", test_arm64_block_sync_pc}, {"test_arm64_block_invalid_mem_read_write_sync", test_arm64_block_invalid_mem_read_write_sync}, + {"test_arm64_mmu", test_arm64_mmu}, {NULL, NULL}}; diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 26e92b9c..00dbc08d 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -634,6 +634,76 @@ static void test_riscv_correct_address_in_long_jump_hook(void) OK(uc_close(uc)); } +static void test_riscv_mmu_prepare_tlb(uc_engine *uc, uint32_t data_address, uint32_t code_address) +{ + uint64_t tlbe; + uint32_t sptbr = 0x2000; + + OK(uc_mem_map(uc, sptbr, 0x3000, UC_PROT_ALL)); //tlb base + + tlbe = ((sptbr + 0x1000) >> 2) | 1; + OK(uc_mem_write(uc, sptbr, &tlbe, sizeof(tlbe))); + tlbe = ((sptbr + 0x2000) >> 2) | 1; + OK(uc_mem_write(uc, sptbr + 0x1000, &tlbe, sizeof(tlbe))); + + tlbe = (code_address >> 2) | (7 << 1) | 1; + OK(uc_mem_write(uc, sptbr + 0x2000 + 0x15*8, &tlbe, sizeof(tlbe))); + + tlbe = (data_address >> 2) | (7 << 1) | 1; + OK(uc_mem_write(uc, sptbr + 0x2000 + 0x16*8, &tlbe, sizeof(tlbe))); +} + +static void test_riscv_mmu_hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *userdata) +{ + if (address == 0x15010) { + OK(uc_emu_stop(uc)); + } +} + +static void test_riscv_mmu(void) +{ + uc_engine *uc; + uc_hook h; + uint32_t code_address = 0x5000; + uint32_t data_address = 0x6000; + uint32_t data_value = 0x41414141; + uint32_t data_result = 0; + + /* + li t3, (8 << 60) | 2 + csrw sptbr, t3 + li t0, (1 << 11) | (1 << 5) + csrw mstatus, t0 + la t1, 0x15000 + csrw mepc, t1 + mret + */ + char code_m[] = "\x1b\x0e\xf0\xff" "\x13\x1e\xfe\x03" "\x13\x0e\x2e\x00" "\x73\x10\x0e\x18" "\xb7\x12\x00\x00" "\x9b\x82\x02\x82" "\x73\x90\x02\x30" "\x37\x53\x01\x00" "\x73\x10\x13\x34" "\x73\x00\x20\x30"; + + /* + li t0, 0x41414141 + li t1, 0x16000 + sw t0, 0(t1) + nop + */ + char code_s[] = "\xb7\x42\x41\x41" "\x9b\x82\x12\x14" "\x37\x63\x01\x00" "\x23\x20\x53\x00" "\x13\x00\x00\x00"; + + OK(uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc)); + OK(uc_hook_add(uc, &h, UC_HOOK_CODE, test_riscv_mmu_hook_code, NULL, 1, 0)); + OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL)); + OK(uc_mem_map(uc, code_address, 0x1000, UC_PROT_ALL)); + OK(uc_mem_map(uc, data_address, 0x1000, UC_PROT_ALL)); + OK(uc_mem_write(uc, code_address, &code_s, sizeof(code_s))); + OK(uc_mem_write(uc, 0x1000, &code_m, sizeof(code_m))); + + test_riscv_mmu_prepare_tlb(uc, data_address, code_address); + + OK(uc_emu_start(uc, 0x1000, sizeof(code_m) - 1, 0, 0)); + OK(uc_mem_read(uc, data_address, &data_result, sizeof(data_result))); + + TEST_CHECK(data_value == data_result); +} + TEST_LIST = { {"test_riscv32_nop", test_riscv32_nop}, {"test_riscv64_nop", test_riscv64_nop}, @@ -657,4 +727,5 @@ TEST_LIST = { test_riscv_correct_address_in_small_jump_hook}, {"test_riscv_correct_address_in_long_jump_hook", test_riscv_correct_address_in_long_jump_hook}, + {"test_riscv_mmu", test_riscv_mmu}, {NULL, NULL}}; diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 110e4b41..9bcb7d81 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1259,6 +1259,131 @@ static void test_x86_16_incorrect_ip(void) OK(uc_close(uc)); } +static void test_x86_mmu_prepare_tlb(uc_engine *uc, uint64_t vaddr, uint64_t tlb_base) +{ + uint64_t cr0; + uint64_t cr4; + uc_x86_msr msr = {.rid = 0x0c0000080, .value = 0}; + uint64_t pml4o = ((vaddr & 0x00ff8000000000) >> 39)*8; + uint64_t pdpo = ((vaddr & 0x00007fc0000000) >> 30)*8; + uint64_t pdo = ((vaddr & 0x0000003fe00000) >> 21)*8; + uint64_t pml4e = (tlb_base + 0x1000) | 1 | (1 << 2); + uint64_t pdpe = (tlb_base + 0x2000) | 1 | (1 << 2); + uint64_t pde = (tlb_base + 0x3000) | 1 | (1 << 2); + OK(uc_mem_write(uc, tlb_base + pml4o, &pml4e, sizeof(pml4o))); + OK(uc_mem_write(uc, tlb_base + 0x1000 + pdpo, &pdpe, sizeof(pdpe))); + OK(uc_mem_write(uc, tlb_base + 0x2000 + pdo, &pde, sizeof(pde))); + OK(uc_reg_write(uc, UC_X86_REG_CR3, &tlb_base)); + OK(uc_reg_read(uc, UC_X86_REG_CR0, &cr0)); + OK(uc_reg_read(uc, UC_X86_REG_CR4, &cr4)); + OK(uc_reg_read(uc, UC_X86_REG_MSR, &msr)); + cr0 |= 1; + cr0 |= 1l << 31; + cr4 |= 1l << 5; + msr.value |= 1l << 8; + OK(uc_reg_write(uc, UC_X86_REG_CR0, &cr0)); + OK(uc_reg_write(uc, UC_X86_REG_CR4, &cr4)); + OK(uc_reg_write(uc, UC_X86_REG_MSR, &msr)); +} + +static void test_x86_mmu_pt_set(uc_engine *uc, uint64_t vaddr, uint64_t paddr, uint64_t tlb_base) +{ + uint64_t pto = ((vaddr & 0x000000001ff000) >> 12)*8; + uint32_t pte = (paddr) | 1 | (1 << 2); + uc_mem_write(uc, tlb_base + 0x3000 + pto, &pte, sizeof(pte)); +} + +static void test_x86_mmu_callback(uc_engine *uc, void *userdata) +{ + bool *parrent_done = userdata; + uint64_t rax; + OK(uc_reg_read(uc, UC_X86_REG_RAX, &rax)); + switch (rax) { + case 57: + /* fork */ + break; + case 60: + /* exit */ + uc_emu_stop(uc); + return; + default: + TEST_CHECK(false); + } + + if (!(*parrent_done)) { + *parrent_done = true; + rax = 27; + OK(uc_reg_write(uc, UC_X86_REG_RAX, &rax)); + uc_emu_stop(uc); + } +} + +static void test_x86_mmu(void) +{ + bool parrent_done = false; + uint64_t tlb_base = 0x3000; + uint64_t parrent, child; + uint64_t rax, rip; + uc_context *context; + uc_engine *uc; + uc_hook h1; + + /* + * mov rax, 57 + * syscall + * test rax, rax + * jz child + * xor rax, rax + * mov rax, 60 + * mov [0x4000], rax + * syscall + * + * child: + * xor rcx, rcx + * mov rcx, 42 + * mov [0x4000], rcx + * mov rax, 60 + * syscall + */ + char code[] = "\xB8\x39\x00\x00\x00\x0F\x05\x48\x85\xC0\x74\x0F\xB8\x3C\x00\x00\x00\x48\x89\x04\x25\x00\x40\x00\x00\x0F\x05\xB9\x2A\x00\x00\x00\x48\x89\x0C\x25\x00\x40\x00\x00\xB8\x3C\x00\x00\x00\x0F\x05"; + + OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + OK(uc_hook_add(uc, &h1, UC_HOOK_INSN, &test_x86_mmu_callback, &parrent_done, 1, 0, UC_X86_INS_SYSCALL)); + OK(uc_context_alloc(uc, &context)); + + OK(uc_mem_map(uc, 0x0, 0x1000, UC_PROT_ALL)); //Code + OK(uc_mem_write(uc, 0x0, code, sizeof(code) - 1)); + OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL)); //Parrent + OK(uc_mem_map(uc, 0x2000, 0x1000, UC_PROT_ALL)); //Child + OK(uc_mem_map(uc, tlb_base, 0x4000, UC_PROT_ALL)); //TLB + + test_x86_mmu_prepare_tlb(uc, 0x0, tlb_base); + test_x86_mmu_pt_set(uc, 0x2000, 0x0, tlb_base); + test_x86_mmu_pt_set(uc, 0x4000, 0x1000, tlb_base); + + OK(uc_ctl_flush_tlb(uc)); + OK(uc_emu_start(uc, 0x2000, 0x0, 0, 0)); + + OK(uc_context_save(uc, context)); + OK(uc_reg_read(uc, UC_X86_REG_RIP, &rip)); + + OK(uc_emu_start(uc, rip, 0x0, 0, 0)); + + /* restore for child */ + OK(uc_context_restore(uc, context)); + test_x86_mmu_prepare_tlb(uc, 0x0, tlb_base); + test_x86_mmu_pt_set(uc, 0x4000, 0x2000, tlb_base); + rax = 0; + OK(uc_reg_write(uc, UC_X86_REG_RAX, &rax)); + OK(uc_ctl_flush_tlb(uc)); + + OK(uc_emu_start(uc, rip, 0x0, 0, 0)); + OK(uc_mem_read(uc, 0x1000, &parrent, sizeof(parrent))); + OK(uc_mem_read(uc, 0x2000, &child, sizeof(child))); + TEST_CHECK(parrent == 60); + TEST_CHECK(child == 42); +} + TEST_LIST = { {"test_x86_in", test_x86_in}, {"test_x86_out", test_x86_out}, @@ -1302,4 +1427,5 @@ TEST_LIST = { #endif {"test_x86_lazy_mapping", test_x86_lazy_mapping}, {"test_x86_16_incorrect_ip", test_x86_16_incorrect_ip}, + {"test_x86_mmu", test_x86_mmu}, {NULL, NULL}}; From 901034577a42592901895fdeaef37d80a4fe6a2f Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Mon, 17 Oct 2022 14:33:10 +0200 Subject: [PATCH 17/26] i386 call internal helper on special porpese register write Some registers writes have side effects. i.e. write to cr3 flush the tlb, if the PG bit is set. --- qemu/target/i386/unicorn.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index 3e83b0ba..a7a93628 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -977,10 +977,16 @@ static int reg_write(CPUX86State *env, unsigned int regid, const void *value, default: break; case UC_X86_REG_CR0: + cpu_x86_update_cr0(env, *(uint32_t *)value); + goto write_cr; case UC_X86_REG_CR1: case UC_X86_REG_CR2: case UC_X86_REG_CR3: + cpu_x86_update_cr3(env, *(uint32_t *)value); + goto write_cr; case UC_X86_REG_CR4: + cpu_x86_update_cr4(env, *(uint32_t *)value); +write_cr: env->cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; break; case UC_X86_REG_DR0: @@ -1163,10 +1169,16 @@ static int reg_write(CPUX86State *env, unsigned int regid, const void *value, default: break; case UC_X86_REG_CR0: + cpu_x86_update_cr0(env, *(uint32_t *) value); + goto write_cr64; case UC_X86_REG_CR1: case UC_X86_REG_CR2: case UC_X86_REG_CR3: + cpu_x86_update_cr3(env, *(uint32_t *) value); + goto write_cr64; case UC_X86_REG_CR4: + cpu_x86_update_cr4(env, *(uint32_t *) value); +write_cr64: env->cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; break; case UC_X86_REG_DR0: From 759d694e24f207a384d3a6e12647d3acb7acd7b6 Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Tue, 29 Nov 2022 17:00:51 +0100 Subject: [PATCH 18/26] sample to use the softmmu --- CMakeLists.txt | 2 +- samples/Makefile | 1 + samples/sample_all.sh | 5 + samples/sample_mmu.c | 275 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 samples/sample_mmu.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d94bd464..4b7e4ff0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1188,7 +1188,7 @@ set(UNICORN_LINK_LIBRARIES ${UNICORN_LINK_LIBRARIES} unicorn-common) if(UNICORN_HAS_X86) set(UNICORN_COMPILE_OPTIONS ${UNICORN_COMPILE_OPTIONS} -DUNICORN_HAS_X86) set(UNICORN_LINK_LIBRARIES ${UNICORN_LINK_LIBRARIES} x86_64-softmmu) - set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_x86 sample_x86_32_gdt_and_seg_regs sample_batch_reg mem_apis shellcode) + set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_x86 sample_x86_32_gdt_and_seg_regs sample_batch_reg mem_apis shellcode sample_mmu) target_link_libraries(x86_64-softmmu PRIVATE unicorn-common) set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_x86) endif() diff --git a/samples/Makefile b/samples/Makefile index 007e43ba..cbb3d91f 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -85,6 +85,7 @@ SOURCES += shellcode.c SOURCES += mem_apis.c SOURCES += sample_x86_32_gdt_and_seg_regs.c SOURCES += sample_batch_reg.c +SOURCES += sample_mmu.c endif ifneq (,$(findstring m68k,$(UNICORN_ARCHS))) SOURCES += sample_m68k.c diff --git a/samples/sample_all.sh b/samples/sample_all.sh index 026e0107..bee64f68 100755 --- a/samples/sample_all.sh +++ b/samples/sample_all.sh @@ -57,3 +57,8 @@ if test -e $DIR/sample_x86_32_gdt_and_seg_regs; then echo "==========================" $DIR/sample_x86_32_gdt_and_seg_regs fi + +if test -e $DIR/sample_mmu; then + echo "==========================" + $DIR/sample_mmu +fi diff --git a/samples/sample_mmu.c b/samples/sample_mmu.c new file mode 100644 index 00000000..ea39b87c --- /dev/null +++ b/samples/sample_mmu.c @@ -0,0 +1,275 @@ +#include +#include + +static void mmu_write_callback(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) +{ + printf("write at 0x%lx: 0x%lx\n", address, value); +} + +static void x86_mmu_prepare_tlb(uc_engine *uc, uint64_t vaddr, uint64_t tlb_base) +{ + uc_err err; + uint64_t cr0; + uint64_t cr4; + uc_x86_msr msr = {.rid = 0xC0000080, .value = 0}; + uint64_t pml4o = ((vaddr & 0x00ff8000000000) >> 39)*8; + uint64_t pdpo = ((vaddr & 0x00007fc0000000) >> 30)*8; + uint64_t pdo = ((vaddr & 0x0000003fe00000) >> 21)*8; + uint64_t pml4e = (tlb_base + 0x1000) | 1 | (1 << 2); + uint64_t pdpe = (tlb_base + 0x2000) | 1 | (1 << 2); + uint64_t pde = (tlb_base + 0x3000) | 1 | (1 << 2); + err = uc_mem_write(uc, tlb_base + pml4o, &pml4e, sizeof(pml4o)); + if (err) { + printf("failed to write pml4e\n"); + exit(1); + } + err = uc_mem_write(uc, tlb_base + 0x1000 + pdpo, &pdpe, sizeof(pdpe)); + if (err) { + printf("failed to write pml4e\n"); + exit(1); + } + err = uc_mem_write(uc, tlb_base + 0x2000 + pdo, &pde, sizeof(pde)); + if (err) { + printf("failed to write pde\n"); + exit(1); + } + err = uc_reg_write(uc, UC_X86_REG_CR3, &tlb_base); + if (err) { + printf("failed to write CR3\n"); + exit(1); + } + err = uc_reg_read(uc, UC_X86_REG_CR0, &cr0); + if (err) { + printf("failed to read CR0\n"); + exit(1); + } + err = uc_reg_read(uc, UC_X86_REG_CR4, &cr4); + if (err) { + printf("failed to read CR4\n"); + exit(1); + } + err = uc_reg_read(uc, UC_X86_REG_MSR, &msr); + if (err) { + printf("failed to read MSR\n"); + exit(1); + } + + cr0 |= 1; //enable protected mode + cr0 |= 1l << 31; //enable paging + cr4 |= 1l << 5; //enable physical address extension + msr.value |= 1l << 8; //enable long mode + + err = uc_reg_write(uc, UC_X86_REG_CR0, &cr0); + if (err) { + printf("failed to write CR0\n"); + exit(1); + } + err = uc_reg_write(uc, UC_X86_REG_CR4, &cr4); + if (err) { + printf("failed to write CR4\n"); + exit(1); + } + err = uc_reg_write(uc, UC_X86_REG_MSR, &msr); + if (err) { + printf("failed to write MSR\n"); + exit(1); + } +} + +static void x86_mmu_pt_set(uc_engine *uc, uint64_t vaddr, uint64_t paddr, uint64_t tlb_base) +{ + uint64_t pto = ((vaddr & 0x000000001ff000) >> 12)*8; + uint32_t pte = (paddr) | 1 | (1 << 2); + uc_mem_write(uc, tlb_base + 0x3000 + pto, &pte, sizeof(pte)); +} + +static void x86_mmu_callback(uc_engine *uc, void *userdata) +{ + uc_err err; + bool *parrent_done = userdata; + uint64_t rax; + err = uc_reg_read(uc, UC_X86_REG_RAX, &rax); + if (err) { + printf("failed to read rax\n"); + exit(1); + } + switch (rax) { + case 57: + /* fork */ + break; + case 60: + /* exit */ + uc_emu_stop(uc); + return; + default: + printf("unknown syscall"); + exit(1); + } + + if (!(*parrent_done)) { + *parrent_done = true; + rax = 27; + err = uc_reg_write(uc, UC_X86_REG_RAX, &rax); + if (err) { + printf("failed to write rax\n"); + exit(1); + } + uc_emu_stop(uc); + } +} + +int main(void) +{ + uint64_t tlb_base = 0x3000; + uint64_t rax, rip; + bool parrent_done = false; + uint64_t parrent, child; + uc_context *context; + uc_engine *uc; + uc_err err; + uc_hook h1, h2; + + /* + * mov rax, 57 + * syscall + * test rax, rax + * jz child + * xor rax, rax + * mov rax, 60 + * mov [0x4000], rax + * syscall + * + * child: + * xor rcx, rcx + * mov rcx, 42 + * mov [0x4000], rcx + * mov rax, 60 + * syscall + */ + char code[] = "\xB8\x39\x00\x00\x00\x0F\x05\x48\x85\xC0\x74\x0F\xB8\x3C\x00\x00\x00\x48\x89\x04\x25\x00\x40\x00\x00\x0F\x05\xB9\x2A\x00\x00\x00\x48\x89\x0C\x25\x00\x40\x00\x00\xB8\x3C\x00\x00\x00\x0F\x05"; + printf("Emulate x86 amd64 code with mmu enabled and switch mappings\n"); + + err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + exit(1); + } + err = uc_context_alloc(uc, &context); + if (err) { + printf("Failed on uc_context_alloc() with error returned: %u\n", err); + exit(1); + } + + err = uc_hook_add(uc, &h1, UC_HOOK_INSN, &x86_mmu_callback, &parrent_done, 1, 0, UC_X86_INS_SYSCALL); + if (err) { + printf("Failed on uc_hook_add() with error returned: %u\n", err); + exit(1); + } + + // Memory hooks are called after the mmu translation, so hook the physicall addresses + err = uc_hook_add(uc, &h2, UC_HOOK_MEM_WRITE, &mmu_write_callback, NULL, 0x1000, 0x3000); + if (err) { + printf("Faled on uc_hook_add() with error returned: %u\n", err); + } + + printf("map code\n"); + err = uc_mem_map(uc, 0x0, 0x1000, UC_PROT_ALL); //Code + if (err) { + printf("Failed on uc_mem_map() with error return: %u\n", err); + exit(1); + } + err = uc_mem_write(uc, 0x0, code, sizeof(code) - 1); + if (err) { + printf("Failed on uc_mem_wirte() with error return: %u\n", err); + exit(1); + } + printf("map parrent memory\n"); + err = uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL); //Parrent + if (err) { + printf("Failed on uc_mem_map() with error return: %u\n", err); + exit(1); + } + printf("map child memory\n"); + err = uc_mem_map(uc, 0x2000, 0x1000, UC_PROT_ALL); //Child + if (err) { + printf("failed to map child memory\n"); + exit(1); + } + printf("map tlb memory\n"); + err = uc_mem_map(uc, tlb_base, 0x4000, UC_PROT_ALL); //TLB + if (err) { + printf("failed to map memory for tlb\n"); + exit(1); + } + + + printf("set up the tlb\n"); + x86_mmu_prepare_tlb(uc, 0x0, tlb_base); + x86_mmu_pt_set(uc, 0x2000, 0x0, tlb_base); + x86_mmu_pt_set(uc, 0x4000, 0x1000, tlb_base); + + err = uc_ctl_flush_tlb(uc); + if (err) { + printf("failed to flush tlb\n"); + exit(1); + } + printf("run the parrent\n"); + err = uc_emu_start(uc, 0x2000, 0x0, 0, 0); + if (err) { + printf("failed to run parrent\n"); + exit(1); + } + + printf("save the context for the child\n"); + err = uc_context_save(uc, context); + printf("finish the parrent\n"); + err = uc_reg_read(uc, UC_X86_REG_RIP, &rip); + if (err) { + printf("failed to read rip\n"); + exit(1); + } + + err = uc_emu_start(uc, rip, 0x0, 0, 0); + if (err) { + printf("failed to flush tlb\n"); + exit(1); + } + + printf("restore the context for the child\n"); + err = uc_context_restore(uc, context); + if (err) { + printf("failed to restore context\n"); + exit(1); + } + x86_mmu_prepare_tlb(uc, 0x0, tlb_base); + x86_mmu_pt_set(uc, 0x4000, 0x2000, tlb_base); + rax = 0; + err = uc_reg_write(uc, UC_X86_REG_RAX, &rax); + if (err) { + printf("failed to write rax\n"); + exit(1); + } + err = uc_ctl_flush_tlb(uc); + if (err) { + printf("failed to flush tlb\n"); + exit(1); + } + + err = uc_emu_start(uc, rip, 0x0, 0, 0); + if (err) { + printf("failed to run child\n"); + exit(1); + } + err = uc_mem_read(uc, 0x1000, &parrent, sizeof(parrent)); + if (err) { + printf("failed to read from parrent memory\n"); + exit(1); + } + err = uc_mem_read(uc, 0x2000, &child, sizeof(child)); + if (err) { + printf("failed to read from child memory\n"); + exit(1); + } + printf("parrent result == %lu\n", parrent); + printf("child result == %lu\n", child); +} From e25419bb2d252ea222d5603db972fdc42b10f161 Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Wed, 5 Oct 2022 16:53:24 +0200 Subject: [PATCH 19/26] add virtuall tlb this virtuall tlb allows to use mmu indipendent of the architectur --- CMakeLists.txt | 2 + include/uc_priv.h | 5 + include/unicorn/unicorn.h | 46 ++++++- qemu/aarch64.h | 1 + qemu/arm.h | 1 + qemu/include/hw/core/cpu.h | 3 + qemu/include/sysemu/cpus.h | 1 + qemu/m68k.h | 1 + qemu/mips.h | 1 + qemu/mips64.h | 1 + qemu/mips64el.h | 1 + qemu/mipsel.h | 1 + qemu/ppc.h | 1 + qemu/ppc64.h | 1 + qemu/riscv32.h | 1 + qemu/riscv64.h | 1 + qemu/s390x.h | 1 + qemu/softmmu/unicorn_vtlb.c | 106 ++++++++++++++ qemu/sparc.h | 1 + qemu/sparc64.h | 1 + qemu/target/arm/cpu.c | 1 + qemu/target/i386/cpu.c | 1 + qemu/target/m68k/cpu.c | 1 + qemu/target/mips/cpu.c | 1 + qemu/target/ppc/translate_init.inc.c | 1 + qemu/target/riscv/cpu.c | 1 + qemu/target/s390x/cpu.c | 1 + qemu/target/sparc/cpu.c | 1 + qemu/target/tricore/cpu.c | 1 + qemu/tricore.h | 1 + qemu/unicorn_common.h | 17 +++ qemu/x86_64.h | 1 + samples/sample_mmu.c | 199 ++++++++++++++++++++++++--- symbols.sh | 1 + tests/unit/test_x86.c | 31 +++++ uc.c | 23 ++++ 36 files changed, 434 insertions(+), 25 deletions(-) create mode 100644 qemu/softmmu/unicorn_vtlb.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b7e4ff0..6e467090 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -446,6 +446,8 @@ set(UNICORN_ARCH_COMMON qemu/accel/tcg/tcg-runtime-gvec.c qemu/accel/tcg/translate-all.c qemu/accel/tcg/translator.c + + qemu/softmmu/unicorn_vtlb.c ) if(UNICORN_HAS_X86) diff --git a/include/uc_priv.h b/include/uc_priv.h index 60a9b486..1eb8f1a9 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -146,6 +146,8 @@ typedef uc_err (*uc_gen_tb_t)(struct uc_struct *uc, uint64_t pc, uc_tb *out_tb); // tb flush typedef uc_tcg_flush_tlb uc_tb_flush_t; +typedef uc_err (*uc_set_tlb_t)(struct uc_struct *uc, int mode); + struct hook { int type; // UC_HOOK_* int insn; // instruction for HOOK_INSN @@ -202,6 +204,7 @@ typedef enum uc_hook_idx { UC_HOOK_INSN_INVALID_IDX, UC_HOOK_EDGE_GENERATED_IDX, UC_HOOK_TCG_OPCODE_IDX, + UC_HOOK_TLB_FILL_IDX, UC_HOOK_MAX, } uc_hook_idx; @@ -337,6 +340,8 @@ struct uc_struct { GHashTable *flat_views; bool memory_region_update_pending; + uc_set_tlb_t set_tlb; + // linked lists containing hooks per type struct list hook[UC_HOOK_MAX]; struct list hooks_to_del; diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 54ffd251..3e1f9248 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -244,6 +244,22 @@ typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data); +typedef struct uc_tlb_entry uc_tlb_entry; +typedef enum uc_mem_type uc_mem_type; + +/* + Callback function for tlb lookups + + @vaddr: virtuall address for lookup + @rw: the access mode + @result: result entry, contains physical address (paddr) and permitted access type (perms) for the entry + + @return: return true if the entry was found. If a callback is present but + no one returns true a pagefault is generated. +*/ +typedef bool (*uc_cb_tlbevent_t)(uc_engine *uc, uint64_t vaddr, uc_mem_type type, + uc_tlb_entry *result, void *user_data); + // Represent a TranslationBlock. typedef struct uc_tb { uint64_t pc; @@ -295,7 +311,7 @@ typedef void (*uc_cb_mmio_write_t)(uc_engine *uc, uint64_t offset, void *user_data); // All type of memory accesses for UC_HOOK_MEM_* -typedef enum uc_mem_type { +enum uc_mem_type { UC_MEM_READ = 16, // Memory is read from UC_MEM_WRITE, // Memory is written to UC_MEM_FETCH, // Memory is fetched @@ -306,7 +322,7 @@ typedef enum uc_mem_type { UC_MEM_READ_PROT, // Read from read protected, but mapped, memory UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory UC_MEM_READ_AFTER, // Memory is read from (successful access) -} uc_mem_type; +}; // These are all op codes we support to hook for UC_HOOK_TCG_OP_CODE. // Be cautious since it may bring much more overhead than UC_HOOK_CODE without @@ -369,6 +385,10 @@ typedef enum uc_hook_type { // Hook on specific tcg op code. The usage of this hook is similar to // UC_HOOK_INSN. UC_HOOK_TCG_OPCODE = 1 << 16, + // Hook on tlb fill requests. + // Register tlb fill request hook on the virtuall addresses. + // The callback will be triggert if the tlb cache don't contain an address. + UC_HOOK_TLB_FILL = 1 << 17, } uc_hook_type; // Hook type for all events of unmapped memory access @@ -490,6 +510,16 @@ typedef enum uc_query_type { #define UC_CTL_WRITE(type, nr) UC_CTL(type, nr, UC_CTL_IO_WRITE) #define UC_CTL_READ_WRITE(type, nr) UC_CTL(type, nr, UC_CTL_IO_READ_WRITE) +// unicorn tlb type selection +typedef enum uc_tlb_type { + // The tlb implementation of the CPU, best to use for full system emulation. + UC_TLB_CPU = 0, + // The default unicorn virtuall TLB implementation. + // This tlb defaults to virtuall address == physical address + // Also a hook is availible to override the tlb entries (see uc_cb_tlbevent_t). + UC_TLB_VIRTUAL +} uc_tlb_type; + // All type of controls for uc_ctl API. // The controls are organized in a tree level. // If a control don't have `Set` or `Get` for @args, it means it's r/o or w/o. @@ -536,7 +566,11 @@ typedef enum uc_control_type { UC_CTL_TB_REMOVE_CACHE, // Invalidate all translation blocks. // No arguments. - UC_CTL_TB_FLUSH + UC_CTL_TB_FLUSH, + // Change the tlb implementation + // see uc_tlb_type for current implemented types + // Write: @args = (int) + UC_CTL_TLB_TYPE } uc_control_type; @@ -612,6 +646,7 @@ See sample_ctl.c for a detailed example. #define uc_ctl_request_cache(uc, address, tb) \ uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_TB_REQUEST_CACHE, 2), (address), (tb)) #define uc_ctl_flush_tlb(uc) uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_FLUSH, 0)) +#define uc_ctl_tlb_mode(uc, mode) uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TLB_TYPE, 1), (mode)) // Opaque storage for CPU context, used with uc_context_*() struct uc_context; typedef struct uc_context uc_context; @@ -898,6 +933,11 @@ typedef enum uc_prot { UC_PROT_ALL = 7, } uc_prot; +struct uc_tlb_entry { + uint64_t paddr; + uc_prot perms; +}; + /* Map memory in for emulation. This API adds a memory region that can be used by emulation. diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 7b8b40df..c678501b 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64 #endif +#define unicorn_fill_tlb unicorn_fill_tlb_aarch64 #define uc_add_inline_hook uc_add_inline_hook_aarch64 #define uc_del_inline_hook uc_del_inline_hook_aarch64 #define tb_invalidate_phys_range tb_invalidate_phys_range_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index 871a604f..13e8ffee 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _arm #endif +#define unicorn_fill_tlb unicorn_fill_tlb_arm #define uc_add_inline_hook uc_add_inline_hook_arm #define uc_del_inline_hook uc_del_inline_hook_arm #define tb_invalidate_phys_range tb_invalidate_phys_range_arm diff --git a/qemu/include/hw/core/cpu.h b/qemu/include/hw/core/cpu.h index 097a7f63..e01ff76c 100644 --- a/qemu/include/hw/core/cpu.h +++ b/qemu/include/hw/core/cpu.h @@ -117,6 +117,9 @@ typedef struct CPUClass { bool (*tlb_fill)(CPUState *cpu, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); + bool (*tlb_fill_cpu)(CPUState *cpu, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr); hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr, MemTxAttrs *attrs); diff --git a/qemu/include/sysemu/cpus.h b/qemu/include/sysemu/cpus.h index ee8fb60d..37e7dd9c 100644 --- a/qemu/include/sysemu/cpus.h +++ b/qemu/include/sysemu/cpus.h @@ -2,6 +2,7 @@ #define QEMU_CPUS_H #include "qemu/timer.h" +#include "hw/core/cpu.h" /* cpus.c */ bool qemu_in_vcpu_thread(void); diff --git a/qemu/m68k.h b/qemu/m68k.h index 1d0352c1..23f5d93a 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _m68k #endif +#define unicorn_fill_tlb unicorn_fill_tlb_m68k #define uc_add_inline_hook uc_add_inline_hook_m68k #define uc_del_inline_hook uc_del_inline_hook_m68k #define tb_invalidate_phys_range tb_invalidate_phys_range_m68k diff --git a/qemu/mips.h b/qemu/mips.h index f1666d06..8aaa4de4 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips #endif +#define unicorn_fill_tlb unicorn_fill_tlb_mips #define uc_add_inline_hook uc_add_inline_hook_mips #define uc_del_inline_hook uc_del_inline_hook_mips #define tb_invalidate_phys_range tb_invalidate_phys_range_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index bdcb4dae..30f6b0ac 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64 #endif +#define unicorn_fill_tlb unicorn_fill_tlb_mips64 #define uc_add_inline_hook uc_add_inline_hook_mips64 #define uc_del_inline_hook uc_del_inline_hook_mips64 #define tb_invalidate_phys_range tb_invalidate_phys_range_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index ea1c1874..115aa427 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64el #endif +#define unicorn_fill_tlb unicorn_fill_tlb_mips64el #define uc_add_inline_hook uc_add_inline_hook_mips64el #define uc_del_inline_hook uc_del_inline_hook_mips64el #define tb_invalidate_phys_range tb_invalidate_phys_range_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 67b11060..552c968e 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mipsel #endif +#define unicorn_fill_tlb unicorn_fill_tlb_mipsel #define uc_add_inline_hook uc_add_inline_hook_mipsel #define uc_del_inline_hook uc_del_inline_hook_mipsel #define tb_invalidate_phys_range tb_invalidate_phys_range_mipsel diff --git a/qemu/ppc.h b/qemu/ppc.h index eff4b69d..67e3c4b9 100644 --- a/qemu/ppc.h +++ b/qemu/ppc.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc #endif +#define unicorn_fill_tlb unicorn_fill_tlb_ppc #define uc_add_inline_hook uc_add_inline_hook_ppc #define uc_del_inline_hook uc_del_inline_hook_ppc #define tb_invalidate_phys_range tb_invalidate_phys_range_ppc diff --git a/qemu/ppc64.h b/qemu/ppc64.h index c08ee2d6..36ffbc64 100644 --- a/qemu/ppc64.h +++ b/qemu/ppc64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc64 #endif +#define unicorn_fill_tlb unicorn_fill_tlb_ppc64 #define uc_add_inline_hook uc_add_inline_hook_ppc64 #define uc_del_inline_hook uc_del_inline_hook_ppc64 #define tb_invalidate_phys_range tb_invalidate_phys_range_ppc64 diff --git a/qemu/riscv32.h b/qemu/riscv32.h index 432b9bb3..94a8fc02 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv32 #endif +#define unicorn_fill_tlb unicorn_fill_tlb_riscv32 #define uc_add_inline_hook uc_add_inline_hook_riscv32 #define uc_del_inline_hook uc_del_inline_hook_riscv32 #define tb_invalidate_phys_range tb_invalidate_phys_range_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index f0aa87d1..bfc0bff4 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv64 #endif +#define unicorn_fill_tlb unicorn_fill_tlb_riscv64 #define uc_add_inline_hook uc_add_inline_hook_riscv64 #define uc_del_inline_hook uc_del_inline_hook_riscv64 #define tb_invalidate_phys_range tb_invalidate_phys_range_riscv64 diff --git a/qemu/s390x.h b/qemu/s390x.h index dcda0fd4..b4295cbc 100644 --- a/qemu/s390x.h +++ b/qemu/s390x.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _s390x #endif +#define unicorn_fill_tlb unicorn_fill_tlb_s390x #define uc_add_inline_hook uc_add_inline_hook_s390x #define uc_del_inline_hook uc_del_inline_hook_s390x #define tb_invalidate_phys_range tb_invalidate_phys_range_s390x diff --git a/qemu/softmmu/unicorn_vtlb.c b/qemu/softmmu/unicorn_vtlb.c new file mode 100644 index 00000000..3b629bda --- /dev/null +++ b/qemu/softmmu/unicorn_vtlb.c @@ -0,0 +1,106 @@ +#include +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "exec/exec-all.h" +#include "uc_priv.h" + +#include + +static void raise_mmu_exception(CPUState *cs, target_ulong address, + int rw, uintptr_t retaddr) +{ + cs->uc->invalid_error = UC_ERR_EXCEPTION; + cs->uc->invalid_addr = address; + cpu_exit(cs->uc->cpu); + cpu_loop_exit_restore(cs, retaddr); +} + +static uc_mem_type rw_to_mem_type(int rw) +{ + switch (rw) { + case MMU_DATA_LOAD: + return UC_MEM_READ; + case MMU_DATA_STORE: + return UC_MEM_WRITE; + case MMU_INST_FETCH: + return UC_MEM_FETCH; + default: + return UC_MEM_READ; + } +} + +static int perms_to_prot(int perms) +{ + int ret = 0; + if (perms & UC_PROT_READ) { + ret |= PAGE_READ; + } + if (perms & UC_PROT_WRITE) { + ret |= PAGE_WRITE; + } + if (perms & UC_PROT_EXEC) { + ret |= PAGE_EXEC; + } + return ret; +} + +bool unicorn_fill_tlb(CPUState *cs, vaddr address, int size, + MMUAccessType rw, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + bool handled = false; + bool ret = false; + struct uc_struct *uc = cs->uc; + uc_tlb_entry e; + struct hook *hook; + HOOK_FOREACH_VAR_DECLARE; + + HOOK_FOREACH(uc, hook, UC_HOOK_TLB_FILL) { + if (hook->to_delete) { + continue; + } + if (!HOOK_BOUND_CHECK(hook, address)) { + continue; + } + handled = true; + if ((ret = ((uc_cb_tlbevent_t)hook->callback)(uc, address & TARGET_PAGE_MASK, rw_to_mem_type(rw), &e, hook->user_data))) { + break; + } + } + + if (handled && !ret) { + goto tlb_miss; + } + + if (!handled) { + e.paddr = address & TARGET_PAGE_MASK; + e.perms = UC_PROT_READ|UC_PROT_WRITE|UC_PROT_EXEC; + } + + switch (rw) { + case MMU_DATA_LOAD: + ret = e.perms & UC_PROT_READ; + break; + case MMU_DATA_STORE: + ret = e.perms & UC_PROT_WRITE; + break; + case MMU_INST_FETCH: + ret = e.perms & UC_PROT_EXEC; + break; + default: + ret = false; + break; + } + + if (ret) { + tlb_set_page(cs, address & TARGET_PAGE_MASK, e.paddr & TARGET_PAGE_MASK, perms_to_prot(e.perms), mmu_idx, TARGET_PAGE_SIZE); + return true; + } + +tlb_miss: + if (probe) { + return false; + } + raise_mmu_exception(cs, address, rw, retaddr); + return false; +} diff --git a/qemu/sparc.h b/qemu/sparc.h index 5b57febc..7083a74f 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc #endif +#define unicorn_fill_tlb unicorn_fill_tlb_sparc #define uc_add_inline_hook uc_add_inline_hook_sparc #define uc_del_inline_hook uc_del_inline_hook_sparc #define tb_invalidate_phys_range tb_invalidate_phys_range_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 5a792deb..e70362dc 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc64 #endif +#define unicorn_fill_tlb unicorn_fill_tlb_sparc64 #define uc_add_inline_hook uc_add_inline_hook_sparc64 #define uc_del_inline_hook uc_del_inline_hook_sparc64 #define tb_invalidate_phys_range tb_invalidate_phys_range_sparc64 diff --git a/qemu/target/arm/cpu.c b/qemu/target/arm/cpu.c index 45540fe6..9bff7fff 100644 --- a/qemu/target/arm/cpu.c +++ b/qemu/target/arm/cpu.c @@ -2081,6 +2081,7 @@ void arm_cpu_class_init(struct uc_struct *uc, CPUClass *oc) cc->asidx_from_attrs = arm_asidx_from_attrs; cc->tcg_initialize = arm_translate_init; cc->tlb_fill = arm_cpu_tlb_fill; + cc->tlb_fill_cpu = arm_cpu_tlb_fill; cc->debug_excp_handler = arm_debug_excp_handler; cc->do_unaligned_access = arm_cpu_do_unaligned_access; } diff --git a/qemu/target/i386/cpu.c b/qemu/target/i386/cpu.c index 12953daa..56a0603c 100644 --- a/qemu/target/i386/cpu.c +++ b/qemu/target/i386/cpu.c @@ -5067,6 +5067,7 @@ static void x86_cpu_common_class_init(struct uc_struct *uc, CPUClass *oc, void * cc->cpu_exec_exit = x86_cpu_exec_exit; cc->tcg_initialize = tcg_x86_init; cc->tlb_fill = x86_cpu_tlb_fill; + cc->tlb_fill_cpu = x86_cpu_tlb_fill; } X86CPU *cpu_x86_init(struct uc_struct *uc) diff --git a/qemu/target/m68k/cpu.c b/qemu/target/m68k/cpu.c index 915b82ac..19b31d93 100644 --- a/qemu/target/m68k/cpu.c +++ b/qemu/target/m68k/cpu.c @@ -232,6 +232,7 @@ static void m68k_cpu_class_init(CPUClass *c) cc->cpu_exec_interrupt = m68k_cpu_exec_interrupt; cc->set_pc = m68k_cpu_set_pc; cc->tlb_fill = m68k_cpu_tlb_fill; + cc->tlb_fill_cpu = m68k_cpu_tlb_fill; cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug; cc->tcg_initialize = m68k_tcg_init; } diff --git a/qemu/target/mips/cpu.c b/qemu/target/mips/cpu.c index 4ddf65e0..63c5cfa3 100644 --- a/qemu/target/mips/cpu.c +++ b/qemu/target/mips/cpu.c @@ -148,6 +148,7 @@ static void mips_cpu_class_init(CPUClass *c) cc->get_phys_page_debug = mips_cpu_get_phys_page_debug; cc->tcg_initialize = mips_tcg_init; cc->tlb_fill = mips_cpu_tlb_fill; + cc->tlb_fill_cpu = mips_cpu_tlb_fill; } MIPSCPU *cpu_mips_init(struct uc_struct *uc) diff --git a/qemu/target/ppc/translate_init.inc.c b/qemu/target/ppc/translate_init.inc.c index caef69be..02eaee0a 100644 --- a/qemu/target/ppc/translate_init.inc.c +++ b/qemu/target/ppc/translate_init.inc.c @@ -10254,6 +10254,7 @@ static void ppc_cpu_class_init(struct uc_struct *uc, CPUClass *oc) cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug; cc->tcg_initialize = ppc_translate_init; cc->tlb_fill = ppc_cpu_tlb_fill; + cc->tlb_fill_cpu = ppc_cpu_tlb_fill; cc->cpu_exec_enter = ppc_cpu_exec_enter; cc->cpu_exec_exit = ppc_cpu_exec_exit; } diff --git a/qemu/target/riscv/cpu.c b/qemu/target/riscv/cpu.c index d58204ad..6197abd0 100644 --- a/qemu/target/riscv/cpu.c +++ b/qemu/target/riscv/cpu.c @@ -308,6 +308,7 @@ static void riscv_cpu_class_init(struct uc_struct *uc, CPUClass *c, void *data) cc->do_unaligned_access = riscv_cpu_do_unaligned_access; cc->tcg_initialize = riscv_translate_init; cc->tlb_fill = riscv_cpu_tlb_fill; + cc->tlb_fill_cpu = riscv_cpu_tlb_fill; } typedef struct CPUModelInfo { diff --git a/qemu/target/s390x/cpu.c b/qemu/target/s390x/cpu.c index f6ccf9d1..00e50831 100644 --- a/qemu/target/s390x/cpu.c +++ b/qemu/target/s390x/cpu.c @@ -234,6 +234,7 @@ static void s390_cpu_class_init(struct uc_struct *uc, CPUClass *oc) cc->do_unaligned_access = s390x_cpu_do_unaligned_access; cc->tcg_initialize = s390x_translate_init; cc->tlb_fill = s390_cpu_tlb_fill; + cc->tlb_fill_cpu = s390_cpu_tlb_fill; // s390_cpu_model_class_register_props(oc); } diff --git a/qemu/target/sparc/cpu.c b/qemu/target/sparc/cpu.c index 489819bc..87b531f7 100644 --- a/qemu/target/sparc/cpu.c +++ b/qemu/target/sparc/cpu.c @@ -505,6 +505,7 @@ static void sparc_cpu_class_init(struct uc_struct *uc, CPUClass *oc) cc->set_pc = sparc_cpu_set_pc; cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb; cc->tlb_fill = sparc_cpu_tlb_fill; + cc->tlb_fill_cpu = sparc_cpu_tlb_fill; cc->do_unaligned_access = sparc_cpu_do_unaligned_access; cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug; cc->tcg_initialize = sparc_tcg_init; diff --git a/qemu/target/tricore/cpu.c b/qemu/target/tricore/cpu.c index a55ca63e..b016c1a4 100644 --- a/qemu/target/tricore/cpu.c +++ b/qemu/target/tricore/cpu.c @@ -138,6 +138,7 @@ static void tricore_cpu_class_init(CPUClass *c) cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug; cc->tlb_fill = tricore_cpu_tlb_fill; + cc->tlb_fill_cpu = tricore_cpu_tlb_fill; cc->tcg_initialize = tricore_tcg_init; } diff --git a/qemu/tricore.h b/qemu/tricore.h index 3f41fc76..a7219654 100644 --- a/qemu/tricore.h +++ b/qemu/tricore.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _tricore #endif +#define unicorn_fill_tlb unicorn_fill_tlb_tricore #define uc_add_inline_hook uc_add_inline_hook_tricore #define uc_del_inline_hook uc_del_inline_hook_tricore #define tb_invalidate_phys_range tb_invalidate_phys_range_tricore diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 3e06ccac..d7802b3b 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -11,6 +11,9 @@ void vm_start(struct uc_struct*); void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size); +bool unicorn_fill_tlb(CPUState *cs, vaddr address, int size, + MMUAccessType rw, int mmu_idx, + bool probe, uintptr_t retaddr); // return true on success, false on failure static inline bool cpu_physical_mem_read(AddressSpace *as, hwaddr addr, @@ -91,6 +94,19 @@ static inline void target_page_init(struct uc_struct* uc) uc->target_page_align = TARGET_PAGE_SIZE - 1; } +static uc_err uc_set_tlb(struct uc_struct *uc, int mode) { + switch (mode) { + case UC_TLB_VIRTUAL: + uc->cpu->cc->tlb_fill = unicorn_fill_tlb; + return UC_ERR_OK; + case UC_TLB_CPU: + uc->cpu->cc->tlb_fill = uc->cpu->cc->tlb_fill_cpu; + return UC_ERR_OK; + default: + return UC_ERR_ARG; + } +} + void softfloat_init(void); static inline void uc_common_init(struct uc_struct* uc) { @@ -107,6 +123,7 @@ static inline void uc_common_init(struct uc_struct* uc) uc->softfloat_initialize = softfloat_init; uc->tcg_flush_tlb = tcg_flush_softmmu_tlb; uc->memory_map_io = memory_map_io; + uc->set_tlb = uc_set_tlb; if (!uc->release) uc->release = release_common; diff --git a/qemu/x86_64.h b/qemu/x86_64.h index ef4f4ad4..aa03182d 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _x86_64 #endif +#define unicorn_fill_tlb unicorn_fill_tlb_x86_64 #define uc_add_inline_hook uc_add_inline_hook_x86_64 #define uc_del_inline_hook uc_del_inline_hook_x86_64 #define tb_invalidate_phys_range tb_invalidate_phys_range_x86_64 diff --git a/samples/sample_mmu.c b/samples/sample_mmu.c index ea39b87c..84baa2a0 100644 --- a/samples/sample_mmu.c +++ b/samples/sample_mmu.c @@ -1,6 +1,25 @@ #include #include +/* + * mov rax, 57 + * syscall + * test rax, rax + * jz child + * xor rax, rax + * mov rax, 60 + * mov [0x4000], rax + * syscall + * + * child: + * xor rcx, rcx + * mov rcx, 42 + * mov [0x4000], rcx + * mov rax, 60 + * syscall + */ +char code[] = "\xB8\x39\x00\x00\x00\x0F\x05\x48\x85\xC0\x74\x0F\xB8\x3C\x00\x00\x00\x48\x89\x04\x25\x00\x40\x00\x00\x0F\x05\xB9\x2A\x00\x00\x00\x48\x89\x0C\x25\x00\x40\x00\x00\xB8\x3C\x00\x00\x00\x0F\x05"; + static void mmu_write_callback(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) { printf("write at 0x%lx: 0x%lx\n", address, value); @@ -83,7 +102,7 @@ static void x86_mmu_pt_set(uc_engine *uc, uint64_t vaddr, uint64_t paddr, uint64 uc_mem_write(uc, tlb_base + 0x3000 + pto, &pte, sizeof(pte)); } -static void x86_mmu_callback(uc_engine *uc, void *userdata) +static void x86_mmu_syscall_callback(uc_engine *uc, void *userdata) { uc_err err; bool *parrent_done = userdata; @@ -99,6 +118,7 @@ static void x86_mmu_callback(uc_engine *uc, void *userdata) break; case 60: /* exit */ + *parrent_done = true; uc_emu_stop(uc); return; default: @@ -107,7 +127,6 @@ static void x86_mmu_callback(uc_engine *uc, void *userdata) } if (!(*parrent_done)) { - *parrent_done = true; rax = 27; err = uc_reg_write(uc, UC_X86_REG_RAX, &rax); if (err) { @@ -118,7 +137,7 @@ static void x86_mmu_callback(uc_engine *uc, void *userdata) } } -int main(void) +void cpu_tlb(void) { uint64_t tlb_base = 0x3000; uint64_t rax, rip; @@ -129,24 +148,6 @@ int main(void) uc_err err; uc_hook h1, h2; - /* - * mov rax, 57 - * syscall - * test rax, rax - * jz child - * xor rax, rax - * mov rax, 60 - * mov [0x4000], rax - * syscall - * - * child: - * xor rcx, rcx - * mov rcx, 42 - * mov [0x4000], rcx - * mov rax, 60 - * syscall - */ - char code[] = "\xB8\x39\x00\x00\x00\x0F\x05\x48\x85\xC0\x74\x0F\xB8\x3C\x00\x00\x00\x48\x89\x04\x25\x00\x40\x00\x00\x0F\x05\xB9\x2A\x00\x00\x00\x48\x89\x0C\x25\x00\x40\x00\x00\xB8\x3C\x00\x00\x00\x0F\x05"; printf("Emulate x86 amd64 code with mmu enabled and switch mappings\n"); err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc); @@ -154,13 +155,14 @@ int main(void) printf("Failed on uc_open() with error returned: %u\n", err); exit(1); } + uc_ctl_tlb_mode(uc, UC_TLB_CPU); err = uc_context_alloc(uc, &context); if (err) { printf("Failed on uc_context_alloc() with error returned: %u\n", err); exit(1); } - err = uc_hook_add(uc, &h1, UC_HOOK_INSN, &x86_mmu_callback, &parrent_done, 1, 0, UC_X86_INS_SYSCALL); + err = uc_hook_add(uc, &h1, UC_HOOK_INSN, &x86_mmu_syscall_callback, &parrent_done, 1, 0, UC_X86_INS_SYSCALL); if (err) { printf("Failed on uc_hook_add() with error returned: %u\n", err); exit(1); @@ -272,4 +274,157 @@ int main(void) } printf("parrent result == %lu\n", parrent); printf("child result == %lu\n", child); + uc_close(uc); +} + +static bool virtual_tlb_callback(uc_engine *uc, uint64_t addr, uc_mem_type type, uc_tlb_entry *result, void *user_data) +{ + bool *parrent_done = user_data; + printf("tlb lookup for address: 0x%lX\n", addr); + switch (addr & ~(0xfff)) { + case 0x2000: + result->paddr = 0x0; + result->perms = UC_PROT_EXEC; + return true; + case 0x4000: + if (*parrent_done) { + result->paddr = 0x2000; + } else { + result->paddr = 0x1000; + } + result->perms = UC_PROT_READ | UC_PROT_WRITE; + return true; + default: + break; + } + return false; +} + +void virtual_tlb(void) +{ + uint64_t rax, rip; + bool parrent_done = false; + uint64_t parrent, child; + uc_context *context; + uc_engine *uc; + uc_err err; + uc_hook h1, h2, h3; + + printf("Emulate x86 amd64 code with virtual mmu\n"); + + err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + exit(1); + } + uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL); + err = uc_context_alloc(uc, &context); + if (err) { + printf("Failed on uc_context_alloc() with error returned: %u\n", err); + exit(1); + } + + err = uc_hook_add(uc, &h1, UC_HOOK_INSN, &x86_mmu_syscall_callback, &parrent_done, 1, 0, UC_X86_INS_SYSCALL); + if (err) { + printf("Failed on uc_hook_add() with error returned: %u\n", err); + exit(1); + } + + // Memory hooks are called after the mmu translation, so hook the physicall addresses + err = uc_hook_add(uc, &h2, UC_HOOK_MEM_WRITE, &mmu_write_callback, NULL, 0x1000, 0x3000); + if (err) { + printf("Faled on uc_hook_add() with error returned: %u\n", err); + } + + printf("map code\n"); + err = uc_mem_map(uc, 0x0, 0x1000, UC_PROT_ALL); //Code + if (err) { + printf("Failed on uc_mem_map() with error return: %u\n", err); + exit(1); + } + err = uc_mem_write(uc, 0x0, code, sizeof(code) - 1); + if (err) { + printf("Failed on uc_mem_wirte() with error return: %u\n", err); + exit(1); + } + printf("map parrent memory\n"); + err = uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL); //Parrent + if (err) { + printf("Failed on uc_mem_map() with error return: %u\n", err); + exit(1); + } + printf("map child memory\n"); + err = uc_mem_map(uc, 0x2000, 0x1000, UC_PROT_ALL); //Child + if (err) { + printf("failed to map child memory\n"); + exit(1); + } + + err = uc_hook_add(uc, &h3, UC_HOOK_TLB_FILL, virtual_tlb_callback, &parrent_done, 1, 0); + + printf("run the parrent\n"); + err = uc_emu_start(uc, 0x2000, 0x0, 0, 0); + if (err) { + printf("failed to run parrent\n"); + exit(1); + } + + printf("save the context for the child\n"); + err = uc_context_save(uc, context); + printf("finish the parrent\n"); + err = uc_reg_read(uc, UC_X86_REG_RIP, &rip); + if (err) { + printf("failed to read rip\n"); + exit(1); + } + + err = uc_emu_start(uc, rip, 0x0, 0, 0); + if (err) { + printf("failed to flush tlb\n"); + exit(1); + } + + printf("restore the context for the child\n"); + err = uc_context_restore(uc, context); + if (err) { + printf("failed to restore context\n"); + exit(1); + } + rax = 0; + parrent_done = true; + err = uc_reg_write(uc, UC_X86_REG_RAX, &rax); + if (err) { + printf("failed to write rax\n"); + exit(1); + } + err = uc_ctl_flush_tlb(uc); + if (err) { + printf("failed to flush tlb\n"); + exit(1); + } + + err = uc_emu_start(uc, rip, 0x0, 0, 0); + if (err) { + printf("failed to run child\n"); + exit(1); + } + err = uc_mem_read(uc, 0x1000, &parrent, sizeof(parrent)); + if (err) { + printf("failed to read from parrent memory\n"); + exit(1); + } + err = uc_mem_read(uc, 0x2000, &child, sizeof(child)); + if (err) { + printf("failed to read from child memory\n"); + exit(1); + } + printf("parrent result == %lu\n", parrent); + printf("child result == %lu\n", child); + uc_close(uc); +} + +int main(void) +{ + cpu_tlb(); + virtual_tlb(); } diff --git a/symbols.sh b/symbols.sh index f2d0a114..cbf5f0db 100755 --- a/symbols.sh +++ b/symbols.sh @@ -4,6 +4,7 @@ CMD_PATH=$(realpath $0) SOURCE_DIR=$(dirname ${CMD_PATH}) COMMON_SYMBOLS=" +unicorn_fill_tlb \ uc_add_inline_hook \ uc_del_inline_hook \ tb_invalidate_phys_range \ diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 9bcb7d81..9edb5db7 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1384,6 +1384,36 @@ static void test_x86_mmu(void) TEST_CHECK(child == 42); } +static bool test_x86_vtlb_callback(uc_engine *uc, uint64_t addr, uc_mem_type type, uc_tlb_entry *result, void *user_data) +{ + result->paddr = addr; + result->perms = UC_PROT_ALL; + return true; +} + +static void test_x86_vtlb(void) +{ + uc_engine *uc; + uc_hook hook; + char code[] = "\xeb\x02\x90\x90\x90\x90\x90\x90"; // jmp 4; nop; nop; nop; + // nop; nop; nop + uint64_t r_eip = 0; + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); + + OK(uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL)); + OK(uc_hook_add(uc, &hook, UC_HOOK_TLB_FILL, test_x86_vtlb_callback, NULL, 1, 0)); + + OK(uc_emu_start(uc, code_start, code_start + 4, 0, 0)); + + OK(uc_reg_read(uc, UC_X86_REG_EIP, &r_eip)); + + TEST_CHECK(r_eip == code_start + 4); + + OK(uc_close(uc)); +} + + TEST_LIST = { {"test_x86_in", test_x86_in}, {"test_x86_out", test_x86_out}, @@ -1428,4 +1458,5 @@ TEST_LIST = { {"test_x86_lazy_mapping", test_x86_lazy_mapping}, {"test_x86_16_incorrect_ip", test_x86_16_incorrect_ip}, {"test_x86_mmu", test_x86_mmu}, + {"test_x86_vtlb", test_x86_vtlb}, {NULL, NULL}}; diff --git a/uc.c b/uc.c index a1a71366..da576f9f 100644 --- a/uc.c +++ b/uc.c @@ -2377,6 +2377,19 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) } break; + case UC_CTL_TLB_TYPE: { + + UC_INIT(uc); + + if (rw == UC_CTL_IO_WRITE) { + int mode = va_arg(args, int); + err = uc->set_tlb(uc, mode); + } else { + err = UC_ERR_ARG; + } + break; + } + default: err = UC_ERR_ARG; break; @@ -2387,6 +2400,16 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) return err; } +gint cmp_vaddr(gconstpointer a, gconstpointer b, gpointer user_data) +{ + uint64_t va = (uint64_t)a; + uint64_t vb = (uint64_t)b; + if (va == vb) { + return 0; + } + return va < vb ? -1 : 1; +} + #ifdef UNICORN_TRACER uc_tracer *get_tracer() { From e96ac42b2e8f8ded790fd156ef5a5d55ac088acb Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Mon, 13 Feb 2023 15:07:40 +0100 Subject: [PATCH 20/26] Remove MMU hacks Unicorn has included some ugly hacks to provide a envirement where vaddr == paddr. These hacks where to use the full 64 bit mappings on x86 without init the mmu and some memory redirect for MIPS. The UC_TLB_CPU mode defaults to vaddr == paddr, therfor these hacks aren't required anymore. --- include/uc_priv.h | 4 --- qemu/target/arm/cpu.c | 1 - qemu/target/i386/cpu.c | 1 - qemu/target/i386/excp_helper.c | 7 +----- qemu/target/m68k/cpu.c | 1 - qemu/target/mips/cpu.c | 1 - qemu/target/mips/unicorn.c | 16 ------------ qemu/target/ppc/translate_init.inc.c | 1 - qemu/target/ppc/unicorn.c | 16 ------------ qemu/target/riscv/cpu.c | 1 - qemu/target/s390x/cpu.c | 1 - qemu/target/sparc/cpu.c | 1 - qemu/target/tricore/cpu.c | 1 - tests/unit/test_arm64.c | 1 + tests/unit/test_riscv.c | 1 + tests/unit/test_x86.c | 2 ++ uc.c | 37 ++++------------------------ 17 files changed, 10 insertions(+), 83 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index 1eb8f1a9..5b2bfed0 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -119,9 +119,6 @@ typedef MemoryRegion *(*uc_memory_map_io_t)(struct uc_struct *uc, // which interrupt should make emulation stop? typedef bool (*uc_args_int_t)(struct uc_struct *uc, int intno); -// some architecture redirect virtual memory to physical memory like Mips -typedef uint64_t (*uc_mem_redirect_t)(uint64_t address); - // validate if Unicorn supports hooking a given instruction typedef bool (*uc_insn_hook_validate)(uint32_t insn_enum); @@ -287,7 +284,6 @@ struct uc_struct { uc_args_uc_ram_size_ptr_t memory_map_ptr; uc_mem_unmap_t memory_unmap; uc_readonly_mem_t readonly_mem; - uc_mem_redirect_t mem_redirect; uc_cpus_init cpus_init; uc_target_page_init target_page; uc_softfloat_initialize softfloat_initialize; diff --git a/qemu/target/arm/cpu.c b/qemu/target/arm/cpu.c index 9bff7fff..bbcbe83f 100644 --- a/qemu/target/arm/cpu.c +++ b/qemu/target/arm/cpu.c @@ -2080,7 +2080,6 @@ void arm_cpu_class_init(struct uc_struct *uc, CPUClass *oc) cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug; cc->asidx_from_attrs = arm_asidx_from_attrs; cc->tcg_initialize = arm_translate_init; - cc->tlb_fill = arm_cpu_tlb_fill; cc->tlb_fill_cpu = arm_cpu_tlb_fill; cc->debug_excp_handler = arm_debug_excp_handler; cc->do_unaligned_access = arm_cpu_do_unaligned_access; diff --git a/qemu/target/i386/cpu.c b/qemu/target/i386/cpu.c index 56a0603c..826a89f8 100644 --- a/qemu/target/i386/cpu.c +++ b/qemu/target/i386/cpu.c @@ -5066,7 +5066,6 @@ static void x86_cpu_common_class_init(struct uc_struct *uc, CPUClass *oc, void * cc->cpu_exec_enter = x86_cpu_exec_enter; cc->cpu_exec_exit = x86_cpu_exec_exit; cc->tcg_initialize = tcg_x86_init; - cc->tlb_fill = x86_cpu_tlb_fill; cc->tlb_fill_cpu = x86_cpu_tlb_fill; } diff --git a/qemu/target/i386/excp_helper.c b/qemu/target/i386/excp_helper.c index 9a773bbb..cca25d32 100644 --- a/qemu/target/i386/excp_helper.c +++ b/qemu/target/i386/excp_helper.c @@ -635,12 +635,7 @@ do_check_protect_pse36: /* align to page_size */ pte &= PG_ADDRESS_MASK & ~(page_size - 1); page_offset = addr & (page_size - 1); - /* HACK allow full 64 bit mapping in u64 without paging */ - if (env->cr[0] & CR0_PG_MASK) { - paddr = get_hphys(cs, pte + page_offset, is_write1, &prot); - } else { - paddr = addr; - } + paddr = get_hphys(cs, pte + page_offset, is_write1, &prot); /* Even if 4MB pages, we map only one 4KB page in the cache to avoid filling it too fast */ diff --git a/qemu/target/m68k/cpu.c b/qemu/target/m68k/cpu.c index 19b31d93..e3dc9484 100644 --- a/qemu/target/m68k/cpu.c +++ b/qemu/target/m68k/cpu.c @@ -231,7 +231,6 @@ static void m68k_cpu_class_init(CPUClass *c) cc->do_interrupt = m68k_cpu_do_interrupt; cc->cpu_exec_interrupt = m68k_cpu_exec_interrupt; cc->set_pc = m68k_cpu_set_pc; - cc->tlb_fill = m68k_cpu_tlb_fill; cc->tlb_fill_cpu = m68k_cpu_tlb_fill; cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug; cc->tcg_initialize = m68k_tcg_init; diff --git a/qemu/target/mips/cpu.c b/qemu/target/mips/cpu.c index 63c5cfa3..27ad1199 100644 --- a/qemu/target/mips/cpu.c +++ b/qemu/target/mips/cpu.c @@ -147,7 +147,6 @@ static void mips_cpu_class_init(CPUClass *c) cc->do_unaligned_access = mips_cpu_do_unaligned_access; cc->get_phys_page_debug = mips_cpu_get_phys_page_debug; cc->tcg_initialize = mips_tcg_init; - cc->tlb_fill = mips_cpu_tlb_fill; cc->tlb_fill_cpu = mips_cpu_tlb_fill; } diff --git a/qemu/target/mips/unicorn.c b/qemu/target/mips/unicorn.c index 792fb45e..fb91e9c1 100644 --- a/qemu/target/mips/unicorn.c +++ b/qemu/target/mips/unicorn.c @@ -17,21 +17,6 @@ typedef uint32_t mipsreg_t; MIPSCPU *cpu_mips_init(struct uc_struct *uc); -static uint64_t mips_mem_redirect(uint64_t address) -{ - // kseg0 range masks off high address bit - if (address >= 0x80000000 && address <= 0x9fffffff) - return address & 0x7fffffff; - - // kseg1 range masks off top 3 address bits - if (address >= 0xa0000000 && address <= 0xbfffffff) { - return address & 0x1fffffff; - } - - // no redirect - return address; -} - static void mips_set_pc(struct uc_struct *uc, uint64_t address) { ((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC = address; @@ -272,7 +257,6 @@ void mipsel_uc_init(struct uc_struct *uc) uc->release = mips_release; uc->set_pc = mips_set_pc; uc->get_pc = mips_get_pc; - uc->mem_redirect = mips_mem_redirect; uc->cpus_init = mips_cpus_init; uc->cpu_context_size = offsetof(CPUMIPSState, end_reset_fields); uc_common_init(uc); diff --git a/qemu/target/ppc/translate_init.inc.c b/qemu/target/ppc/translate_init.inc.c index 02eaee0a..acedd2d1 100644 --- a/qemu/target/ppc/translate_init.inc.c +++ b/qemu/target/ppc/translate_init.inc.c @@ -10253,7 +10253,6 @@ static void ppc_cpu_class_init(struct uc_struct *uc, CPUClass *oc) cc->do_unaligned_access = ppc_cpu_do_unaligned_access; cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug; cc->tcg_initialize = ppc_translate_init; - cc->tlb_fill = ppc_cpu_tlb_fill; cc->tlb_fill_cpu = ppc_cpu_tlb_fill; cc->cpu_exec_enter = ppc_cpu_exec_enter; cc->cpu_exec_exit = ppc_cpu_exec_exit; diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index fc8e24f1..b3e75f7d 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -77,21 +77,6 @@ static inline int uc_ppc_store_msr(CPUPPCState *env, target_ulong value, return 0; } -static uint64_t ppc_mem_redirect(uint64_t address) -{ - /* // kseg0 range masks off high address bit - if (address >= 0x80000000 && address <= 0x9fffffff) - return address & 0x7fffffff; - - // kseg1 range masks off top 3 address bits - if (address >= 0xa0000000 && address <= 0xbfffffff) { - return address & 0x1fffffff; - }*/ - - // no redirect - return address; -} - static void ppc_set_pc(struct uc_struct *uc, uint64_t address) { ((CPUPPCState *)uc->cpu->env_ptr)->nip = address; @@ -435,7 +420,6 @@ void ppc_uc_init(struct uc_struct *uc) uc->release = ppc_release; uc->set_pc = ppc_set_pc; uc->get_pc = ppc_get_pc; - uc->mem_redirect = ppc_mem_redirect; uc->cpus_init = ppc_cpus_init; uc->cpu_context_size = offsetof(CPUPPCState, uc); uc_common_init(uc); diff --git a/qemu/target/riscv/cpu.c b/qemu/target/riscv/cpu.c index 6197abd0..6405abd4 100644 --- a/qemu/target/riscv/cpu.c +++ b/qemu/target/riscv/cpu.c @@ -307,7 +307,6 @@ static void riscv_cpu_class_init(struct uc_struct *uc, CPUClass *c, void *data) cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb; cc->do_unaligned_access = riscv_cpu_do_unaligned_access; cc->tcg_initialize = riscv_translate_init; - cc->tlb_fill = riscv_cpu_tlb_fill; cc->tlb_fill_cpu = riscv_cpu_tlb_fill; } diff --git a/qemu/target/s390x/cpu.c b/qemu/target/s390x/cpu.c index 00e50831..a9068715 100644 --- a/qemu/target/s390x/cpu.c +++ b/qemu/target/s390x/cpu.c @@ -233,7 +233,6 @@ static void s390_cpu_class_init(struct uc_struct *uc, CPUClass *oc) cc->debug_excp_handler = s390x_cpu_debug_excp_handler; cc->do_unaligned_access = s390x_cpu_do_unaligned_access; cc->tcg_initialize = s390x_translate_init; - cc->tlb_fill = s390_cpu_tlb_fill; cc->tlb_fill_cpu = s390_cpu_tlb_fill; // s390_cpu_model_class_register_props(oc); diff --git a/qemu/target/sparc/cpu.c b/qemu/target/sparc/cpu.c index 87b531f7..e1386a15 100644 --- a/qemu/target/sparc/cpu.c +++ b/qemu/target/sparc/cpu.c @@ -504,7 +504,6 @@ static void sparc_cpu_class_init(struct uc_struct *uc, CPUClass *oc) cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt; cc->set_pc = sparc_cpu_set_pc; cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb; - cc->tlb_fill = sparc_cpu_tlb_fill; cc->tlb_fill_cpu = sparc_cpu_tlb_fill; cc->do_unaligned_access = sparc_cpu_do_unaligned_access; cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug; diff --git a/qemu/target/tricore/cpu.c b/qemu/target/tricore/cpu.c index b016c1a4..8a871f45 100644 --- a/qemu/target/tricore/cpu.c +++ b/qemu/target/tricore/cpu.c @@ -137,7 +137,6 @@ static void tricore_cpu_class_init(CPUClass *c) cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb; cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug; - cc->tlb_fill = tricore_cpu_tlb_fill; cc->tlb_fill_cpu = tricore_cpu_tlb_fill; cc->tcg_initialize = tricore_tcg_init; } diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 8fcc9f04..8a03945c 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -416,6 +416,7 @@ static void test_arm64_mmu(void) TEST_CHECK(data != NULL); OK(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc)); + OK(uc_ctl_tlb_mode(uc, UC_TLB_CPU)); OK(uc_mem_map(uc, 0, 0x2000, UC_PROT_ALL)); OK(uc_mem_write(uc, 0, code, sizeof(code) - 1)); diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 00dbc08d..7c66f89d 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -689,6 +689,7 @@ static void test_riscv_mmu(void) char code_s[] = "\xb7\x42\x41\x41" "\x9b\x82\x12\x14" "\x37\x63\x01\x00" "\x23\x20\x53\x00" "\x13\x00\x00\x00"; OK(uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc)); + OK(uc_ctl_tlb_mode(uc, UC_TLB_CPU)); OK(uc_hook_add(uc, &h, UC_HOOK_CODE, test_riscv_mmu_hook_code, NULL, 1, 0)); OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL)); OK(uc_mem_map(uc, code_address, 0x1000, UC_PROT_ALL)); diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 9edb5db7..e1cc9a5c 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1090,6 +1090,7 @@ static void test_x86_correct_address_in_long_jump_hook(void) uc_hook hook; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1); + OK(uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL)); OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED, test_x86_correct_address_in_long_jump_hook_callback, NULL, 1, 0)); @@ -1348,6 +1349,7 @@ static void test_x86_mmu(void) char code[] = "\xB8\x39\x00\x00\x00\x0F\x05\x48\x85\xC0\x74\x0F\xB8\x3C\x00\x00\x00\x48\x89\x04\x25\x00\x40\x00\x00\x0F\x05\xB9\x2A\x00\x00\x00\x48\x89\x0C\x25\x00\x40\x00\x00\xB8\x3C\x00\x00\x00\x0F\x05"; OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + OK(uc_ctl_tlb_mode(uc, UC_TLB_CPU)); OK(uc_hook_add(uc, &h1, UC_HOOK_INSN, &test_x86_mmu_callback, &parrent_done, 1, 0, UC_X86_INS_SYSCALL)); OK(uc_context_alloc(uc, &context)); diff --git a/uc.c b/uc.c index da576f9f..b0326a01 100644 --- a/uc.c +++ b/uc.c @@ -230,6 +230,11 @@ static uc_err uc_init(uc_engine *uc) return UC_ERR_RESOURCE; } + // init tlb function + if (!uc->cpu->cc->tlb_fill) { + uc->set_tlb(uc, UC_TLB_CPU); + } + // init fpu softfloat uc->softfloat_initialize(); @@ -577,10 +582,6 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) if (size > INT_MAX) return UC_ERR_ARG; - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - if (!check_mem_area(uc, address, size)) { return UC_ERR_READ_UNMAPPED; } @@ -622,10 +623,6 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, if (size > INT_MAX) return UC_ERR_ARG; - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - if (!check_mem_area(uc, address, size)) { return UC_ERR_WRITE_UNMAPPED; } @@ -1039,10 +1036,6 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) UC_INIT(uc); - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - res = mem_map_check(uc, address, size, perms); if (res) { return res; @@ -1063,10 +1056,6 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, return UC_ERR_ARG; } - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - res = mem_map_check(uc, address, size, perms); if (res) { return res; @@ -1084,10 +1073,6 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, UC_INIT(uc); - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - res = mem_map_check(uc, address, size, UC_PROT_ALL); if (res) return res; @@ -1387,10 +1372,6 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, return UC_ERR_ARG; } - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - // check that user's entire requested block is mapped if (!check_mem_area(uc, address, size)) { return UC_ERR_NOMEM; @@ -1467,10 +1448,6 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) return UC_ERR_ARG; } - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - // check that user's entire requested block is mapped if (!check_mem_area(uc, address, size)) { return UC_ERR_NOMEM; @@ -1515,10 +1492,6 @@ MemoryRegion *find_memory_region(struct uc_struct *uc, uint64_t address) return NULL; } - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - // try with the cache index first i = uc->mapped_block_cache_index; From 8b2c477578c15fbaff5f08536f42e4d1ceab60a5 Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Fri, 17 Feb 2023 14:22:25 +0100 Subject: [PATCH 21/26] clear the TLB cache in uc_ctl_flush_tlb uc_ctl_flush_tlb implies that the tlb is flushed. This change adds UC_CTL_TLB_FLUSH which clears the TLB and set the uc_ctl_flush_tlb alias to UC_CTL_TLB_FLUSH. Also adds a uc_ctl_flush_tb alias for UC_CTL_TB_FLUSH. --- include/unicorn/unicorn.h | 6 +++++- tests/unit/test_ctl.c | 37 +++++++++++++++++++++++++++++++++++++ uc.c | 11 +++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 3e1f9248..2ddb8b9e 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -567,6 +567,9 @@ typedef enum uc_control_type { // Invalidate all translation blocks. // No arguments. UC_CTL_TB_FLUSH, + // Invalidate all TLB cache entries and translation blocks. + // No arguments + UC_CTL_TLB_FLUSH, // Change the tlb implementation // see uc_tlb_type for current implemented types // Write: @args = (int) @@ -645,7 +648,8 @@ See sample_ctl.c for a detailed example. uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_REMOVE_CACHE, 2), (address), (end)) #define uc_ctl_request_cache(uc, address, tb) \ uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_TB_REQUEST_CACHE, 2), (address), (tb)) -#define uc_ctl_flush_tlb(uc) uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_FLUSH, 0)) +#define uc_ctl_flush_tb(uc) uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_FLUSH, 0)) +#define uc_ctl_flush_tlb(uc) uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TLB_FLUSH, 0)) #define uc_ctl_tlb_mode(uc, mode) uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TLB_TYPE, 1), (mode)) // Opaque storage for CPU context, used with uc_context_*() struct uc_context; diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index e1e467d3..9cfcd7dd 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -338,6 +338,42 @@ static void test_uc_emu_stop_set_ip(void) OK(uc_close(uc)); } +static bool test_tlb_clear_tlb(uc_engine *uc, uint64_t addr, uc_mem_type type, uc_tlb_entry *result, void *user_data) +{ + size_t *tlbcount = (size_t*)user_data; + *tlbcount += 1; + result->paddr = addr; + result->perms = UC_PROT_ALL; + return true; +} + +static void test_tlb_clear_syscall(uc_engine *uc, void *user_data) +{ + OK(uc_ctl_flush_tlb(uc)); +} + +static void test_tlb_clear(void) +{ + uc_engine *uc; + uc_hook hook1, hook2; + size_t tlbcount = 0; + char code[] = "\xa3\x00\x00\x20\x00\x00\x00\x00\x00\x0f\x05\xa3\x00\x00\x20\x00\x00\x00\x00\x00"; //movabs dword ptr [0x200000], eax; syscall; movabs dword ptr [0x200000], eax + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1); + OK(uc_mem_map(uc, 0x200000, 0x1000, UC_PROT_ALL)); + + OK(uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL)); + OK(uc_hook_add(uc, &hook1, UC_HOOK_TLB_FILL, test_tlb_clear_tlb, &tlbcount, 1, 0)); + OK(uc_hook_add(uc, &hook2, UC_HOOK_INSN, test_tlb_clear_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + TEST_CHECK(tlbcount == 4); + + OK(uc_close(uc)); +} + + TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_page_size", test_uc_ctl_page_size}, {"test_uc_ctl_arch", test_uc_ctl_arch}, @@ -350,4 +386,5 @@ TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, #endif {"test_uc_hook_cached_uaf", test_uc_hook_cached_uaf}, {"test_uc_emu_stop_set_ip", test_uc_emu_stop_set_ip}, + {"test_tlb_clear", test_tlb_clear}, {NULL, NULL}}; diff --git a/uc.c b/uc.c index b0326a01..0a8626cf 100644 --- a/uc.c +++ b/uc.c @@ -2350,6 +2350,17 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) } break; + case UC_CTL_TLB_FLUSH: + + UC_INIT(uc); + + if (rw == UC_CTL_IO_WRITE) { + uc->tcg_flush_tlb(uc); + } else { + err = UC_ERR_ARG; + } + break; + case UC_CTL_TLB_TYPE: { UC_INIT(uc); From 9f00bb2ed5685ae295c1e6f0716ff7e46b8bd395 Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Tue, 21 Feb 2023 14:48:58 +0100 Subject: [PATCH 22/26] update faq add How can I interact with MMU/TLB --- docs/FAQ.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index ce29a62a..b0bdd622 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -113,6 +113,19 @@ To provide end users with simple API, Unicorn does lots of dirty hacks within qe Yes, it’s possible but that is not Unicorn’s goal and there is no simple switch in qemu to disable softmmu. +## How can I interact with MMU/TLB? + +By default Unicorn will emulate the MMU depending on the emulated architecture. +So you can use the features and interfaces of this MMU. +You or the emulated code can write to the memory and corresponding register to use the MMU. + +There is also use the `UC_TLB_VIRTUAL` mode. +This mode defaults to a simple paddr := vaddr mapping. + +You can also add an `UC_HOOK_TLB_FILL` hook to manage the TLB. +The hook is called, when a virtuall address is not cached and Unicorn is in `UC_TLB_VIRTUAL` mode. +You can manual flush the cache with `uc_ctl_flush_tlb`. + ## I'd like to make contributions, where do I start? See [milestones](https://github.com/unicorn-engine/unicorn/milestones) and [coding convention](https://github.com/unicorn-engine/unicorn/wiki/Coding-Convention @@ -122,4 +135,4 @@ Be sure to send pull requests for our **dev** branch only. ## Which qemu version is Unicorn based on? -Prior to 2.0.0, Unicorn is based on qemu 2.2.1. After that, Unicorn is based on qemu 5.0.1. \ No newline at end of file +Prior to 2.0.0, Unicorn is based on qemu 2.2.1. After that, Unicorn is based on qemu 5.0.1. From 9c01d23ed3febc90ee3b05c521dc93b121b0471e Mon Sep 17 00:00:00 2001 From: Mio Date: Tue, 28 Mar 2023 15:09:45 +0800 Subject: [PATCH 23/26] Update bindings const --- bindings/dotnet/UnicornEngine/Const/Common.fs | 6 ++++++ bindings/go/unicorn/unicorn_const.go | 6 ++++++ bindings/java/unicorn/UnicornConst.java | 6 ++++++ bindings/pascal/unicorn/UnicornConst.pas | 6 ++++++ bindings/python/unicorn/unicorn_const.py | 6 ++++++ .../lib/unicorn_engine/unicorn_const.rb | 6 ++++++ bindings/zig/unicorn/unicorn_const.zig | 14 ++++++++++---- 7 files changed, 46 insertions(+), 4 deletions(-) diff --git a/bindings/dotnet/UnicornEngine/Const/Common.fs b/bindings/dotnet/UnicornEngine/Const/Common.fs index d0ed7b98..f44d1149 100644 --- a/bindings/dotnet/UnicornEngine/Const/Common.fs +++ b/bindings/dotnet/UnicornEngine/Const/Common.fs @@ -111,6 +111,7 @@ module Common = let UC_HOOK_INSN_INVALID = 16384 let UC_HOOK_EDGE_GENERATED = 32768 let UC_HOOK_TCG_OPCODE = 65536 + let UC_HOOK_TLB_FILL = 131072 let UC_HOOK_MEM_UNMAPPED = 112 let UC_HOOK_MEM_PROT = 896 let UC_HOOK_MEM_READ_INVALID = 144 @@ -128,6 +129,9 @@ module Common = let UC_CTL_IO_READ = 2 let UC_CTL_IO_READ_WRITE = 3 + let UC_TLB_CPU = 0 + let UC_TLB_VIRTUAL = 1 + let UC_CTL_UC_MODE = 0 let UC_CTL_UC_PAGE_SIZE = 1 let UC_CTL_UC_ARCH = 2 @@ -139,6 +143,8 @@ module Common = let UC_CTL_TB_REQUEST_CACHE = 8 let UC_CTL_TB_REMOVE_CACHE = 9 let UC_CTL_TB_FLUSH = 10 + let UC_CTL_TLB_FLUSH = 11 + let UC_CTL_TLB_TYPE = 12 let UC_PROT_NONE = 0 let UC_PROT_READ = 1 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 34c97b4a..f82cf916 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -106,6 +106,7 @@ const ( HOOK_INSN_INVALID = 16384 HOOK_EDGE_GENERATED = 32768 HOOK_TCG_OPCODE = 65536 + HOOK_TLB_FILL = 131072 HOOK_MEM_UNMAPPED = 112 HOOK_MEM_PROT = 896 HOOK_MEM_READ_INVALID = 144 @@ -123,6 +124,9 @@ const ( CTL_IO_READ = 2 CTL_IO_READ_WRITE = 3 + TLB_CPU = 0 + TLB_VIRTUAL = 1 + CTL_UC_MODE = 0 CTL_UC_PAGE_SIZE = 1 CTL_UC_ARCH = 2 @@ -134,6 +138,8 @@ const ( CTL_TB_REQUEST_CACHE = 8 CTL_TB_REMOVE_CACHE = 9 CTL_TB_FLUSH = 10 + CTL_TLB_FLUSH = 11 + CTL_TLB_TYPE = 12 PROT_NONE = 0 PROT_READ = 1 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index e63afb79..afd0580e 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -108,6 +108,7 @@ public interface UnicornConst { public static final int UC_HOOK_INSN_INVALID = 16384; public static final int UC_HOOK_EDGE_GENERATED = 32768; public static final int UC_HOOK_TCG_OPCODE = 65536; + public static final int UC_HOOK_TLB_FILL = 131072; public static final int UC_HOOK_MEM_UNMAPPED = 112; public static final int UC_HOOK_MEM_PROT = 896; public static final int UC_HOOK_MEM_READ_INVALID = 144; @@ -125,6 +126,9 @@ public interface UnicornConst { public static final int UC_CTL_IO_READ = 2; public static final int UC_CTL_IO_READ_WRITE = 3; + public static final int UC_TLB_CPU = 0; + public static final int UC_TLB_VIRTUAL = 1; + public static final int UC_CTL_UC_MODE = 0; public static final int UC_CTL_UC_PAGE_SIZE = 1; public static final int UC_CTL_UC_ARCH = 2; @@ -136,6 +140,8 @@ public interface UnicornConst { public static final int UC_CTL_TB_REQUEST_CACHE = 8; public static final int UC_CTL_TB_REMOVE_CACHE = 9; public static final int UC_CTL_TB_FLUSH = 10; + public static final int UC_CTL_TLB_FLUSH = 11; + public static final int UC_CTL_TLB_TYPE = 12; public static final int UC_PROT_NONE = 0; public static final int UC_PROT_READ = 1; diff --git a/bindings/pascal/unicorn/UnicornConst.pas b/bindings/pascal/unicorn/UnicornConst.pas index 2d75d4ae..8b38e8e0 100644 --- a/bindings/pascal/unicorn/UnicornConst.pas +++ b/bindings/pascal/unicorn/UnicornConst.pas @@ -109,6 +109,7 @@ const UC_API_MAJOR = 2; UC_HOOK_INSN_INVALID = 16384; UC_HOOK_EDGE_GENERATED = 32768; UC_HOOK_TCG_OPCODE = 65536; + UC_HOOK_TLB_FILL = 131072; UC_HOOK_MEM_UNMAPPED = 112; UC_HOOK_MEM_PROT = 896; UC_HOOK_MEM_READ_INVALID = 144; @@ -126,6 +127,9 @@ const UC_API_MAJOR = 2; UC_CTL_IO_READ = 2; UC_CTL_IO_READ_WRITE = 3; + UC_TLB_CPU = 0; + UC_TLB_VIRTUAL = 1; + UC_CTL_UC_MODE = 0; UC_CTL_UC_PAGE_SIZE = 1; UC_CTL_UC_ARCH = 2; @@ -137,6 +141,8 @@ const UC_API_MAJOR = 2; UC_CTL_TB_REQUEST_CACHE = 8; UC_CTL_TB_REMOVE_CACHE = 9; UC_CTL_TB_FLUSH = 10; + UC_CTL_TLB_FLUSH = 11; + UC_CTL_TLB_TYPE = 12; UC_PROT_NONE = 0; UC_PROT_READ = 1; diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 96f2949b..64247899 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -104,6 +104,7 @@ UC_HOOK_MEM_READ_AFTER = 8192 UC_HOOK_INSN_INVALID = 16384 UC_HOOK_EDGE_GENERATED = 32768 UC_HOOK_TCG_OPCODE = 65536 +UC_HOOK_TLB_FILL = 131072 UC_HOOK_MEM_UNMAPPED = 112 UC_HOOK_MEM_PROT = 896 UC_HOOK_MEM_READ_INVALID = 144 @@ -121,6 +122,9 @@ UC_CTL_IO_WRITE = 1 UC_CTL_IO_READ = 2 UC_CTL_IO_READ_WRITE = 3 +UC_TLB_CPU = 0 +UC_TLB_VIRTUAL = 1 + UC_CTL_UC_MODE = 0 UC_CTL_UC_PAGE_SIZE = 1 UC_CTL_UC_ARCH = 2 @@ -132,6 +136,8 @@ UC_CTL_CPU_MODEL = 7 UC_CTL_TB_REQUEST_CACHE = 8 UC_CTL_TB_REMOVE_CACHE = 9 UC_CTL_TB_FLUSH = 10 +UC_CTL_TLB_FLUSH = 11 +UC_CTL_TLB_TYPE = 12 UC_PROT_NONE = 0 UC_PROT_READ = 1 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb index 6dbc46e0..8eaf2c36 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb @@ -106,6 +106,7 @@ module UnicornEngine UC_HOOK_INSN_INVALID = 16384 UC_HOOK_EDGE_GENERATED = 32768 UC_HOOK_TCG_OPCODE = 65536 + UC_HOOK_TLB_FILL = 131072 UC_HOOK_MEM_UNMAPPED = 112 UC_HOOK_MEM_PROT = 896 UC_HOOK_MEM_READ_INVALID = 144 @@ -123,6 +124,9 @@ module UnicornEngine UC_CTL_IO_READ = 2 UC_CTL_IO_READ_WRITE = 3 + UC_TLB_CPU = 0 + UC_TLB_VIRTUAL = 1 + UC_CTL_UC_MODE = 0 UC_CTL_UC_PAGE_SIZE = 1 UC_CTL_UC_ARCH = 2 @@ -134,6 +138,8 @@ module UnicornEngine UC_CTL_TB_REQUEST_CACHE = 8 UC_CTL_TB_REMOVE_CACHE = 9 UC_CTL_TB_FLUSH = 10 + UC_CTL_TLB_FLUSH = 11 + UC_CTL_TLB_TYPE = 12 UC_PROT_NONE = 0 UC_PROT_READ = 1 diff --git a/bindings/zig/unicorn/unicorn_const.zig b/bindings/zig/unicorn/unicorn_const.zig index b7ccad62..afebcd76 100644 --- a/bindings/zig/unicorn/unicorn_const.zig +++ b/bindings/zig/unicorn/unicorn_const.zig @@ -4,13 +4,13 @@ pub const unicornConst = enum(c_int) { API_MAJOR = 2, API_MINOR = 0, - API_PATCH = 1, - API_EXTRA = 255, + API_PATCH = 2, + API_EXTRA = 1, VERSION_MAJOR = 2, VERSION_MINOR = 0, - VERSION_PATCH = 1, - VERSION_EXTRA = 255, + VERSION_PATCH = 2, + VERSION_EXTRA = 1, SECOND_SCALE = 1000000, MILISECOND_SCALE = 1000, ARCH_ARM = 1, @@ -106,6 +106,7 @@ pub const unicornConst = enum(c_int) { HOOK_INSN_INVALID = 16384, HOOK_EDGE_GENERATED = 32768, HOOK_TCG_OPCODE = 65536, + HOOK_TLB_FILL = 131072, HOOK_MEM_UNMAPPED = 112, HOOK_MEM_PROT = 896, HOOK_MEM_READ_INVALID = 144, @@ -123,6 +124,9 @@ pub const unicornConst = enum(c_int) { CTL_IO_READ = 2, CTL_IO_READ_WRITE = 3, + TLB_CPU = 0, + TLB_VIRTUAL = 1, + CTL_UC_MODE = 0, CTL_UC_PAGE_SIZE = 1, CTL_UC_ARCH = 2, @@ -134,6 +138,8 @@ pub const unicornConst = enum(c_int) { CTL_TB_REQUEST_CACHE = 8, CTL_TB_REMOVE_CACHE = 9, CTL_TB_FLUSH = 10, + CTL_TLB_FLUSH = 11, + CTL_TLB_TYPE = 12, PROT_NONE = 0, PROT_READ = 1, From 0ba69d6b2fbc90193d8fe196099350f712c8aa04 Mon Sep 17 00:00:00 2001 From: Mio Date: Tue, 28 Mar 2023 15:12:01 +0800 Subject: [PATCH 24/26] Add tlb_mode for python --- bindings/python/unicorn/unicorn.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index 0aacfb13..e893d6fe 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -806,6 +806,9 @@ class Uc(object): def ctl_flush_tb(self): self.ctl(self.__ctl_w(uc.UC_CTL_TB_FLUSH, 0)) + def ctl_tlb_mode(self, mode: int): + self.__ctl_w_1_arg(uc.UC_CTL_TLB_TYPE, mode, ctypes.c_int) + # add a hook def hook_add(self, htype: int, callback: UC_HOOK_CALLBACK_TYPE , user_data: Any=None, begin: int=1, end: int=0, arg1: int=0, arg2: int=0): _h2 = uc_hook_h() From d403a0346e52665a177e44790f1643db646596bb Mon Sep 17 00:00:00 2001 From: Mio Date: Tue, 28 Mar 2023 21:16:19 +0800 Subject: [PATCH 25/26] Update FAQ --- docs/FAQ.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index b0bdd622..f3043abe 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -113,18 +113,15 @@ To provide end users with simple API, Unicorn does lots of dirty hacks within qe Yes, it’s possible but that is not Unicorn’s goal and there is no simple switch in qemu to disable softmmu. -## How can I interact with MMU/TLB? +Starting from 2.0.2, Unicorn will emulate the MMU depending on the emulated architecture without further hacks. That said, Unicorn offers the full ability of the target MMU implementation. While this enables more possibilities of Uncorn, it has a few drawbacks: -By default Unicorn will emulate the MMU depending on the emulated architecture. -So you can use the features and interfaces of this MMU. -You or the emulated code can write to the memory and corresponding register to use the MMU. +- As previous question points out already, some memory regions are not writable/executable. +- You have to always check architecture-specific registers to confirm MMU status. +- `uc_mem_map` will always deal with physical addresses while `uc_emu_start` accepts virtual addresses. -There is also use the `UC_TLB_VIRTUAL` mode. -This mode defaults to a simple paddr := vaddr mapping. +Therefore, if you still prefer the previous `paddr = vaddr` simple mapping, we have a simple experimental MMU implementation that can be switched on by: `uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL)`. With this mode, you could also add a `UC_HOOK_TLB_FILL` hook to manage the TLB. When a virtual address is not cached, the hook will be called. Besides, users are allowed to flush the tlb with `uc_ctl_flush_tlb`. -You can also add an `UC_HOOK_TLB_FILL` hook to manage the TLB. -The hook is called, when a virtuall address is not cached and Unicorn is in `UC_TLB_VIRTUAL` mode. -You can manual flush the cache with `uc_ctl_flush_tlb`. +In theory, `UC_TLB_VIRTUAL` will achieve better performance as it skips all MMU details, though not benchmarked. ## I'd like to make contributions, where do I start? From 45f22085f543a7e93f9be248535c3f27e7b68906 Mon Sep 17 00:00:00 2001 From: Mio Date: Tue, 28 Mar 2023 21:17:01 +0800 Subject: [PATCH 26/26] Update comments --- include/unicorn/unicorn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 2ddb8b9e..ed016dc0 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -512,9 +512,9 @@ typedef enum uc_query_type { // unicorn tlb type selection typedef enum uc_tlb_type { + // The default unicorn virtuall TLB implementation. // The tlb implementation of the CPU, best to use for full system emulation. UC_TLB_CPU = 0, - // The default unicorn virtuall TLB implementation. // This tlb defaults to virtuall address == physical address // Also a hook is availible to override the tlb entries (see uc_cb_tlbevent_t). UC_TLB_VIRTUAL