Merge branch 'dev' into uc-py-next

This commit is contained in:
Eli
2023-04-09 14:50:29 +03:00
committed by GitHub
86 changed files with 5356 additions and 486 deletions

View File

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

View File

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

View File

@@ -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)
@@ -1188,7 +1190,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()

View File

@@ -22,6 +22,7 @@ exclude = [
"/bindings/python",
"/bindings/ruby",
"/bindings/vb6",
"/bindings/zig",
"/samples",
"/tests",
]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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<Int32, List<(EventMemHook * Object)>>()
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<Int32, List<(EventMemHook * (UIntPtr * Object * Object))>>()
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<nativeint>()
let _hookInternals = new List<Object>();
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<EventMemHook * Object>()))
|> Seq.iter (fun eventType -> _memEventHooks.Add(eventType, new List<EventMemHook * (UIntPtr * Object * Object)>()))
// 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
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
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
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
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
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) =
member this.AddInHook(callback: InHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
let trampoline(u: IntPtr) (port: Int32) (size: Int32) (user: IntPtr) =
_inHooks
|> Seq.map(fun (callback, userData) -> callback.Invoke(this, port, size, userData))
|> Seq.last
callback.Invoke(this, port, size, userData)
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
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 -> ()
_inHooks.Add(callback, userData)
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
_inHooks.Add(callback, (hh, userData, inHookInternal))
member this.AddInHook(callback: InHook, userData: Object) =
this.AddInHook(callback, userData, 1, 0)
member this.AddInHook(callback: InHook) =
this.AddInHook(callback, null)
member this.AddOutHook(callback: OutHook, userData: Object) =
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))
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) =
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
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) =
let trampoline(u: IntPtr) (user: IntPtr) =
_syscallHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, userData))
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) =
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
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)

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
# New and improved Unicorn Python bindings by elicn
# based on Nguyen Anh Quynnh's work
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, ucsubclass, uc_version, uc_arch_supported, version_bind, debug, UcError, __version__

View File

@@ -1073,6 +1073,11 @@ class Uc(RegStateManager):
def ctl_flush_tb(self) -> None:
self.__ctl_w(uc.UC_CTL_TB_FLUSH)
def ctl_tlb_mode(self, mode: int) -> None:
self.__ctl_w(uc.UC_CTL_TLB_TYPE,
(ctypes.c_uint, mode)
)
class UcContext(RegStateManager):
def __init__(self, h, arch: int, mode: int):

View File

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

View File

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

10
bindings/zig/README.md Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,150 @@
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
pub const unicornConst = enum(c_int) {
API_MAJOR = 2,
API_MINOR = 0,
API_PATCH = 2,
API_EXTRA = 1,
VERSION_MAJOR = 2,
VERSION_MINOR = 0,
VERSION_PATCH = 2,
VERSION_EXTRA = 1,
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_TLB_FILL = 131072,
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,
TLB_CPU = 0,
TLB_VIRTUAL = 1,
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,
CTL_TLB_FLUSH = 11,
CTL_TLB_TYPE = 12,
PROT_NONE = 0,
PROT_READ = 1,
PROT_WRITE = 2,
PROT_EXEC = 4,
PROT_ALL = 7,
};

File diff suppressed because it is too large Load Diff

View File

@@ -113,6 +113,16 @@ To provide end users with simple API, Unicorn does lots of dirty hacks within qe
Yes, its possible but that is not Unicorns goal and there is no simple switch in qemu to disable softmmu.
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:
- 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.
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`.
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?
See [milestones](https://github.com/unicorn-engine/unicorn/milestones) and [coding convention](https://github.com/unicorn-engine/unicorn/wiki/Coding-Convention

View File

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

View File

@@ -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);
@@ -146,6 +143,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 +201,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;
@@ -284,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;
@@ -337,6 +336,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;
@@ -486,6 +487,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, ...) \

View File

@@ -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 default unicorn virtuall TLB implementation.
// The tlb implementation of the CPU, best to use for full system emulation.
UC_TLB_CPU = 0,
// 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,14 @@ typedef enum uc_control_type {
UC_CTL_TB_REMOVE_CACHE,
// Invalidate all translation blocks.
// No arguments.
UC_CTL_TB_FLUSH
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)
UC_CTL_TLB_TYPE
} uc_control_type;
@@ -611,7 +648,9 @@ 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;
typedef struct uc_context uc_context;
@@ -898,6 +937,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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

106
qemu/softmmu/unicorn_vtlb.c Normal file
View File

@@ -0,0 +1,106 @@
#include <stdint.h>
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "exec/exec-all.h"
#include "uc_priv.h"
#include <stdio.h>
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;
}

View File

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

View File

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

View File

@@ -2080,7 +2080,7 @@ 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;
}

View File

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

View File

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

View File

@@ -5066,7 +5066,7 @@ 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;
}
X86CPU *cpu_x86_init(struct uc_struct *uc)

View File

@@ -643,11 +643,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;

View File

@@ -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:
@@ -1521,7 +1533,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 +1547,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

View File

@@ -231,7 +231,7 @@ 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;
}

View File

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

View File

@@ -147,7 +147,7 @@ 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;
}
MIPSCPU *cpu_mips_init(struct uc_struct *uc)

View File

@@ -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;
@@ -170,7 +155,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);
}
}
@@ -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);

View File

@@ -10253,7 +10253,7 @@ 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;
}

View File

@@ -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;
@@ -361,7 +346,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);
}
}
@@ -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);

View File

@@ -307,7 +307,7 @@ 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;
}
typedef struct CPUModelInfo {

View File

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

View File

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

View File

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

View File

@@ -504,7 +504,7 @@ 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;
cc->tcg_initialize = sparc_tcg_init;

View File

@@ -137,7 +137,7 @@ 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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

430
samples/sample_mmu.c Normal file
View File

@@ -0,0 +1,430 @@
#include <unicorn/unicorn.h>
#include <stdio.h>
/*
* 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);
}
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_syscall_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 */
*parrent_done = true;
uc_emu_stop(uc);
return;
default:
printf("unknown syscall");
exit(1);
}
if (!(*parrent_done)) {
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);
}
}
void cpu_tlb(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;
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);
}
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_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);
}
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);
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();
}

View File

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

View File

@@ -270,7 +270,7 @@
#include <string.h>
#include <setjmp.h>
#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 <errno.h>
#include <libgen.h>

View File

@@ -372,6 +372,107 @@ 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_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));
// 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 +486,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}};

View File

@@ -304,6 +304,76 @@ 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) {
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));
}
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},
@@ -315,4 +385,6 @@ 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},
{"test_tlb_clear", test_tlb_clear},
{NULL, NULL}};

View File

@@ -634,6 +634,77 @@ 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_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));
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 +728,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}};

View File

@@ -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));
@@ -1259,6 +1260,162 @@ 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_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));
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);
}
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},
@@ -1302,4 +1459,6 @@ 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},
{"test_x86_vtlb", test_x86_vtlb},
{NULL, NULL}};

90
uc.c
View File

@@ -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;
}
@@ -907,19 +904,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
@@ -1050,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;
@@ -1074,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;
@@ -1095,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;
@@ -1398,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;
@@ -1478,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;
@@ -1526,16 +1492,12 @@ 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;
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];
}
@@ -1543,8 +1505,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 - 1) {
uc->mapped_block_cache_index = i;
return uc->mapped_blocks[i];
}
// not found
return NULL;
@@ -2386,6 +2350,30 @@ 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);
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;
@@ -2396,6 +2384,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()
{