diff --git a/Makefile b/Makefile index bc79b8b3..fa458470 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,13 @@ include pkgconfig.mk # package version LIBNAME = unicorn UNAME_S := $(shell uname -s) +# SMP_MFLAGS is used for controlling the amount of parallelism used +# in external 'make' invocations. If the user doesn't override it, it +# does "-j4". That is, it uses 4 job threads. If you want to use more or less, +# pass in a different -jX, with X being the number of threads. +# For example, to completely disable parallel building, pass "-j1". +# If you want to use 16 job threads, use "-j16". +SMP_MFLAGS := -j4 GENOBJ = $(shell find qemu/$(1) -name "*.o" 2>/dev/null) @@ -204,7 +211,7 @@ qemu/config-host.h-timestamp: cd qemu && \ ./configure --cc="${CC}" --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ${UNICORN_QEMU_FLAGS} printf "$(UNICORN_ARCHS)" > config.log - $(MAKE) -C qemu -j 4 + $(MAKE) -C qemu $(SMP_MFLAGS) $(eval UC_TARGET_OBJ += $$(wildcard qemu/util/*.o) $$(wildcard qemu/*.o) $$(wildcard qemu/qom/*.o) $$(wildcard qemu/hw/core/*.o) $$(wildcard qemu/qapi/*.o) $$(wildcard qemu/qobject/*.o)) unicorn: $(LIBRARY) $(ARCHIVE) diff --git a/bindings/Makefile b/bindings/Makefile index 14e88df8..1e3c179a 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -42,7 +42,7 @@ python: $(ENV_VARS) python python/$(@:%.txt=%) > $@ %.py.test: %.c.txt %.py.txt - $(DIFF) $(@:%.py.test=%.c.txt) $(@:%.py.test=%.py.txt) + $(DIFF) -u $(@:%.py.test=%.c.txt) $(@:%.py.test=%.py.txt) clean: # rm -rf *.txt diff --git a/bindings/dotnet/UnicornManaged/Const/X86.fs b/bindings/dotnet/UnicornManaged/Const/X86.fs index d0526f87..2dc3f61f 100644 --- a/bindings/dotnet/UnicornManaged/Const/X86.fs +++ b/bindings/dotnet/UnicornManaged/Const/X86.fs @@ -257,7 +257,8 @@ module X86 = let UC_X86_REG_TR = 245 let UC_X86_REG_FPCW = 246 let UC_X86_REG_FPTAG = 247 - let UC_X86_REG_ENDING = 248 + let UC_X86_REG_MSR = 248 + let UC_X86_REG_ENDING = 249 // X86 instructions diff --git a/bindings/go/unicorn/x86_const.go b/bindings/go/unicorn/x86_const.go index ef18c08e..bd47e3e2 100644 --- a/bindings/go/unicorn/x86_const.go +++ b/bindings/go/unicorn/x86_const.go @@ -252,7 +252,8 @@ const ( X86_REG_TR = 245 X86_REG_FPCW = 246 X86_REG_FPTAG = 247 - X86_REG_ENDING = 248 + X86_REG_MSR = 248 + X86_REG_ENDING = 249 // X86 instructions diff --git a/bindings/haskell/.gitignore b/bindings/haskell/.gitignore index 3b5b7859..9966d825 100644 --- a/bindings/haskell/.gitignore +++ b/bindings/haskell/.gitignore @@ -21,3 +21,4 @@ SampleMips SampleSparc SampleX86 Shellcode +SampleBatchReg diff --git a/bindings/haskell/samples/SampleBatchReg.hs b/bindings/haskell/samples/SampleBatchReg.hs new file mode 100644 index 00000000..9b40b3f5 --- /dev/null +++ b/bindings/haskell/samples/SampleBatchReg.hs @@ -0,0 +1,99 @@ +import Unicorn +import Unicorn.Hook +import qualified Unicorn.CPU.X86 as X86 + +import Control.Monad.Trans.Class (lift) +import qualified Data.ByteString as BS +import Data.Int +import Data.List (intercalate) +import Data.Word +import qualified Numeric as N (showHex) +import System.IO (hPutStrLn, stderr) + +syscallABI :: [X86.Register] +syscallABI = [ X86.Rax + , X86.Rdi + , X86.Rsi + , X86.Rdx + , X86.R10 + , X86.R8 + , X86.R9 + ] + +vals :: [Int64] +vals = [ 200 + , 10 + , 11 + , 12 + , 13 + , 14 + , 15 + ] + +ucPerror :: Error + -> IO () +ucPerror err = + hPutStrLn stderr $ "Error " ++ ": " ++ strerror err + +base :: Word64 +base = 0x10000 + +-- mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov r9, 6; syscall +code :: BS.ByteString +code = BS.pack [ 0x48, 0xc7, 0xc0, 0x64, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc7 + , 0x01, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x02, 0x00, 0x00 + , 0x00, 0x48, 0xc7, 0xc2, 0x03, 0x00, 0x00, 0x00, 0x49, 0xc7 + , 0xc2, 0x04, 0x00, 0x00, 0x00, 0x49, 0xc7, 0xc0, 0x05, 0x00 + , 0x00, 0x00, 0x49, 0xc7, 0xc1, 0x06, 0x00, 0x00, 0x00, 0x0f + , 0x05 + ] + +-- Pretty-print integral as hex +showHex :: (Integral a, Show a) => a -> String +showHex i = + N.showHex (fromIntegral i :: Word64) "" + +-- Write a string (with a newline character) to standard output in the emulator +emuPutStrLn :: String -> Emulator () +emuPutStrLn = + lift . putStrLn + +hookSyscall :: SyscallHook () +hookSyscall uc _ = do + runEmulator $ do + readVals <- regReadBatch uc syscallABI + emuPutStrLn $ "syscall: {" + ++ intercalate ", " (map show readVals) + ++ "}" + return () + +hookCode :: CodeHook () +hookCode _ addr size _ = do + putStrLn $ "HOOK_CODE: 0x" ++ showHex addr ++ ", 0x" ++ + maybe "0" showHex size + +main :: IO () +main = do + result <- runEmulator $ do + uc <- open ArchX86 [Mode64] + + -- regWriteBatch + emuPutStrLn "regWriteBatch {200, 10, 11, 12, 13, 14, 15}" + regWriteBatch uc syscallABI vals + + readVals <- regReadBatch uc syscallABI + + emuPutStrLn $ "regReadBatch = {" + ++ intercalate ", " (map show readVals) + ++ "}" + + -- syscall + emuPutStrLn "running syscall shellcode" + syscallHookAdd uc hookSyscall () 1 0 + memMap uc base (0x1000) [ProtAll] + memWrite uc base code + let codeLen = fromIntegral $ BS.length code + start uc base (base + codeLen) Nothing Nothing + case result of + Right _ -> return () + Left err -> ucPerror err diff --git a/bindings/haskell/samples/SampleX86.hs b/bindings/haskell/samples/SampleX86.hs index e395ed75..5f4640e6 100644 --- a/bindings/haskell/samples/SampleX86.hs +++ b/bindings/haskell/samples/SampleX86.hs @@ -98,7 +98,7 @@ hookCode :: CodeHook () hookCode uc addr size _ = do runEmulator $ do emuPutStrLn $ ">>> Tracing instruction at 0x" ++ showHex addr ++ - ", instruction size = 0x" ++ (maybe "0" showHex size) + ", instruction size = 0x" ++ maybe "0" showHex size eflags <- regRead uc X86.Eflags emuPutStrLn $ ">>> --- EFLAGS is 0x" ++ showHex eflags diff --git a/bindings/haskell/src/Unicorn.hs b/bindings/haskell/src/Unicorn.hs index 19c07f8c..a605015d 100644 --- a/bindings/haskell/src/Unicorn.hs +++ b/bindings/haskell/src/Unicorn.hs @@ -25,6 +25,8 @@ module Unicorn -- * Register operations , regWrite , regRead + , regWriteBatch + , regReadBatch -- * Memory operations , MemoryPermission(..) @@ -140,13 +142,11 @@ stop uc = do -- | Write to register. regWrite :: Reg r => Engine -- ^ 'Unicorn' engine handle - -> r -- ^ Register ID to write to + -> r -- ^ Register to write to -> Int64 -- ^ Value to write to register -> Emulator () -- ^ An 'Error' on failure -regWrite uc regId value = do - err <- lift . alloca $ \ptr -> do - poke ptr value - ucRegWrite uc regId ptr +regWrite uc reg value = do + err <- lift $ ucRegWrite uc reg value if err == ErrOk then right () else @@ -155,16 +155,49 @@ regWrite uc regId value = do -- | Read register value. regRead :: Reg r => Engine -- ^ 'Unicorn' engine handle - -> r -- ^ Register ID to read from + -> r -- ^ Register to read from -> Emulator Int64 -- ^ The value read from the register on success, -- or an 'Error' on failure -regRead uc regId = do - (err, val) <- lift $ ucRegRead uc regId +regRead uc reg = do + (err, val) <- lift $ ucRegRead uc reg if err == ErrOk then right val else left err +-- | Write multiple register values. +regWriteBatch :: Reg r + => Engine -- ^ 'Unicorn' engine handle + -> [r] -- ^ List of registers to write to + -> [Int64] -- ^ List of values to write to the registers + -> Emulator () -- ^ An 'Error' on failure +regWriteBatch uc regs vals = do + err <- lift $ ucRegWriteBatch uc regs vals (length regs) + if err == ErrOk then + right () + else + left err + +-- | Read multiple register values. +regReadBatch :: Reg r + => Engine -- ^ 'Unicorn' engine handle + -> [r] -- ^ List of registers to read from + -> Emulator [Int64] -- ^ A list of register values on success, + -- or an 'Error' on failure +regReadBatch uc regs = do + -- Allocate an array of the given size + let size = length regs + result <- lift . allocaArray size $ \array -> do + err <- ucRegReadBatch uc regs array size + if err == ErrOk then + -- If ucRegReadBatch completed successfully, pack the contents of + -- the array into a list and return it + liftM Right (peekArray size array) + else + -- Otherwise return the error + return $ Left err + hoistEither result + ------------------------------------------------------------------------------- -- Memory operations ------------------------------------------------------------------------------- @@ -190,12 +223,12 @@ memRead :: Engine -- ^ 'Unicorn' engine handle -- an 'Error' on failure memRead uc address size = do -- Allocate an array of the given size - result <- lift . allocaArray size $ \ptr -> do - err <- ucMemRead uc address ptr size + result <- lift . allocaArray size $ \array -> do + err <- ucMemRead uc address array size if err == ErrOk then -- If ucMemRead completed successfully, pack the contents of the -- array into a ByteString and return it - liftM (Right . pack) (peekArray size ptr) + liftM (Right . pack) (peekArray size array) else -- Otherwise return the error return $ Left err diff --git a/bindings/haskell/src/Unicorn/Internal/Hook.chs b/bindings/haskell/src/Unicorn/Internal/Hook.chs index affed872..261adf12 100644 --- a/bindings/haskell/src/Unicorn/Internal/Hook.chs +++ b/bindings/haskell/src/Unicorn/Internal/Hook.chs @@ -314,7 +314,7 @@ marshalMemoryHook memoryHook = maybeValue = case memAccess of MemRead -> Nothing MemWrite -> Just $ fromIntegral value - _ -> undefined -- XX Handle this? + _ -> error "Invalid memory access" memoryHook uc memAccess address (fromIntegral size) maybeValue userData -- | Callback function for hooking memory reads. @@ -390,7 +390,7 @@ marshalMemoryEventHook eventMemoryHook = MemReadProt -> Nothing MemWriteUnmapped -> Just $ fromIntegral value MemWriteProt -> Just $ fromIntegral value - _ -> undefined -- XX Handle this? + _ -> error "Invalid memory access" res <- eventMemoryHook uc memAccess address (fromIntegral size) maybeValue userData return $ boolToInt res diff --git a/bindings/haskell/src/Unicorn/Internal/Unicorn.chs b/bindings/haskell/src/Unicorn/Internal/Unicorn.chs index bfe8bd37..db975520 100644 --- a/bindings/haskell/src/Unicorn/Internal/Unicorn.chs +++ b/bindings/haskell/src/Unicorn/Internal/Unicorn.chs @@ -28,6 +28,8 @@ module Unicorn.Internal.Unicorn , ucEmuStop , ucRegWrite , ucRegRead + , ucRegWriteBatch + , ucRegReadBatch , ucMemWrite , ucMemRead , ucMemMap @@ -154,7 +156,8 @@ mkContext ptr = , `Word64' , `Word64' , `Int' - , `Int'} -> `Error' + , `Int' + } -> `Error' #} {# fun uc_emu_stop as ^ @@ -166,19 +169,37 @@ mkContext ptr = -- Register operations ------------------------------------------------------------------------------- -{# fun uc_reg_write as ^ +{# fun uc_reg_write_wrapper as ucRegWrite `Reg r' => { `Engine' , enumToNum `r' - , castPtr `Ptr Int64' + , withIntegral* `Int64' } -> `Error' #} -{# fun uc_reg_read as ^ +{# fun uc_reg_read_wrapper as ucRegRead `Reg r' => { `Engine' , enumToNum `r' - , allocaInt64ToVoid- `Int64' castPtrAndPeek* + , alloca- `Int64' castPtrAndPeek* + } -> `Error' +#} + +{# fun uc_reg_write_batch_wrapper as ucRegWriteBatch + `Reg r' => + { `Engine' + , withEnums* `[r]' + , integralListToArray* `[Int64]' + , `Int' + } -> `Error' +#} + +{# fun uc_reg_read_batch_wrapper as ucRegReadBatch + `Reg r' => + { `Engine' + , withEnums* `[r]' + , castPtr `Ptr Int64' + , `Int' } -> `Error' #} @@ -197,7 +218,8 @@ mkContext ptr = { `Engine' , `Word64' , castPtr `Ptr Word8' - , `Int'} -> `Error' + , `Int' + } -> `Error' #} {# fun uc_mem_map as ^ @@ -205,7 +227,8 @@ mkContext ptr = , `Word64' , `Int' , combineEnums `[MemoryPermission]' - } -> `Error' #} + } -> `Error' +#} {# fun uc_mem_unmap as ^ { `Engine' @@ -296,13 +319,32 @@ expandMemPerms perms = checkRWE _ [] = [] -allocaInt64ToVoid :: (Ptr () -> IO b) - -> IO b -allocaInt64ToVoid f = - alloca $ \(ptr :: Ptr Int64) -> poke ptr 0 >> f (castPtr ptr) +withIntegral :: (Integral a, Num b, Storable b) + => a + -> (Ptr b -> IO c) + -> IO c +withIntegral = + with . fromIntegral -withByteStringLen :: ByteString - -> ((Ptr (), CULong) -> IO a) - -> IO a +withByteStringLen :: Integral a + => ByteString + -> ((Ptr (), a) -> IO b) + -> IO b withByteStringLen bs f = useAsCStringLen bs $ \(ptr, len) -> f (castPtr ptr, fromIntegral len) + +withEnums :: Enum a + => [a] + -> (Ptr b -> IO c) + -> IO c +withEnums l f = + let ints :: [CInt] = map enumToNum l in + withArray ints $ \ptr -> f (castPtr ptr) + +integralListToArray :: (Integral a, Storable b, Num b) + => [a] + -> (Ptr b -> IO c) + -> IO c +integralListToArray l f = + let l' = map fromIntegral l in + withArray l' $ \array -> f array diff --git a/bindings/haskell/src/cbits/unicorn_wrapper.c b/bindings/haskell/src/cbits/unicorn_wrapper.c index 92251a7c..878518ee 100644 --- a/bindings/haskell/src/cbits/unicorn_wrapper.c +++ b/bindings/haskell/src/cbits/unicorn_wrapper.c @@ -1,3 +1,5 @@ +#include + #include "unicorn_wrapper.h" void uc_close_wrapper(uc_engine *uc) { @@ -7,6 +9,42 @@ void uc_close_wrapper(uc_engine *uc) { void uc_close_dummy(uc_engine *uc) { } +uc_err uc_reg_write_wrapper(uc_engine *uc, int regid, const int64_t *value) { + return uc_reg_write(uc, regid, (const void*) value); +} + +uc_err uc_reg_read_wrapper(uc_engine *uc, int regid, int64_t *value) { + return uc_reg_read(uc, regid, (void*) value); +} + +uc_err uc_reg_write_batch_wrapper(uc_engine *uc, int *regs, int64_t *vals, int count) { + void **valsPtr = malloc(sizeof(void*) * count); + int i; + + for (i = 0; i < count; ++i) { + valsPtr[i] = (void*) &vals[i]; + } + + uc_err ret = uc_reg_write_batch(uc, regs, (void *const*) valsPtr, count); + free(valsPtr); + + return ret; +} + +uc_err uc_reg_read_batch_wrapper(uc_engine *uc, int *regs, int64_t *vals, int count) { + void **valsPtr = malloc(sizeof(void*) * count); + int i; + + for (i = 0; i < count; ++i) { + valsPtr[i] = (void*) &vals[i]; + } + + uc_err ret = uc_reg_read_batch(uc, regs, valsPtr, count); + free(valsPtr); + + return ret; +} + void uc_free_wrapper(void *mem) { uc_free(mem); } diff --git a/bindings/haskell/src/include/unicorn_wrapper.h b/bindings/haskell/src/include/unicorn_wrapper.h index 77174750..31757163 100644 --- a/bindings/haskell/src/include/unicorn_wrapper.h +++ b/bindings/haskell/src/include/unicorn_wrapper.h @@ -1,6 +1,7 @@ #ifndef UNICORN_WRAPPER_H #define UNICORN_WRAPPER_H +#include #include /* @@ -13,6 +14,14 @@ void uc_close_wrapper(uc_engine *uc); */ void uc_close_dummy(uc_engine *uc); +/* + * Wrappers for register read/write functions that accept int64_t pointers. + */ +uc_err uc_reg_write_wrapper(uc_engine *uc, int regid, const int64_t *value); +uc_err uc_reg_read_wrapper(uc_engine *uc, int regid, int64_t *value); +uc_err uc_reg_write_batch_wrapper(uc_engine *uc, int *regs, int64_t *vals, int count); +uc_err uc_reg_read_batch_wrapper(uc_engine *uc, int *regs, int64_t *vals, int count); + /* * Wrap Unicorn's uc_free function and ignore the returned error code. */ diff --git a/bindings/java/unicorn/X86Const.java b/bindings/java/unicorn/X86Const.java index 7afed1f9..c41ccfc9 100644 --- a/bindings/java/unicorn/X86Const.java +++ b/bindings/java/unicorn/X86Const.java @@ -254,7 +254,8 @@ public interface X86Const { public static final int UC_X86_REG_TR = 245; public static final int UC_X86_REG_FPCW = 246; public static final int UC_X86_REG_FPTAG = 247; - public static final int UC_X86_REG_ENDING = 248; + public static final int UC_X86_REG_MSR = 248; + public static final int UC_X86_REG_ENDING = 249; // X86 instructions diff --git a/bindings/python/sample_arm.py b/bindings/python/sample_arm.py index 402ba57a..5fae6b6b 100755 --- a/bindings/python/sample_arm.py +++ b/bindings/python/sample_arm.py @@ -41,7 +41,8 @@ def test_arm(): mu.reg_write(UC_ARM_REG_R0, 0x1234) mu.reg_write(UC_ARM_REG_R2, 0x6789) mu.reg_write(UC_ARM_REG_R3, 0x3333) - + mu.reg_write(UC_ARM_REG_APSR, 0xFFFFFFFF) #All application flags turned on + # tracing all basic blocks with customized callback mu.hook_add(UC_HOOK_BLOCK, hook_block) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index 18751ae4..fa50ad1f 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -9,7 +9,7 @@ import os.path import sys import weakref -from . import x86_const, unicorn_const as uc +from . import x86_const, arm64_const, unicorn_const as uc if not hasattr(sys.modules[__name__], "__file__"): __file__ = inspect.getfile(inspect.currentframe()) @@ -202,6 +202,11 @@ class uc_x86_mmr(ctypes.Structure): ("flags", ctypes.c_uint32), # not used by GDTR and IDTR ] +class uc_x86_msr(ctypes.Structure): + _fields_ = [ + ("rid", ctypes.c_uint32), + ("value", ctypes.c_uint64), + ] class uc_x86_float80(ctypes.Structure): """Float80""" @@ -218,6 +223,13 @@ class uc_x86_xmm(ctypes.Structure): ("high_qword", ctypes.c_uint64), ] +class uc_arm64_neon128(ctypes.Structure): + """128-bit neon register""" + _fields_ = [ + ("low_qword", ctypes.c_uint64), + ("high_qword", ctypes.c_uint64), + ] + # Subclassing ref to allow property assignment. class UcRef(weakref.ref): pass @@ -282,7 +294,7 @@ class Uc(object): raise UcError(status) # return the value of a register - def reg_read(self, reg_id): + def reg_read(self, reg_id, opt=None): if self._arch == uc.UC_ARCH_X86: if reg_id in [x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]: reg = uc_x86_mmr() @@ -302,6 +314,23 @@ class Uc(object): if status != uc.UC_ERR_OK: raise UcError(status) return reg.low_qword | (reg.high_qword << 64) + if reg_id is x86_const.UC_X86_REG_MSR: + if opt is None: + raise UcError(uc.UC_ERR_ARG) + reg = uc_x86_msr() + reg.rid = opt + status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg)) + if status != uc.UC_ERR_OK: + raise UcError(status) + return reg.value + + if self._arch == uc.UC_ARCH_ARM64: + if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1): + reg = uc_arm64_neon128() + status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg)) + if status != uc.UC_ERR_OK: + raise UcError(status) + return reg.low_qword | (reg.high_qword << 64) # read to 64bit number to be safe reg = ctypes.c_uint64(0) @@ -330,6 +359,16 @@ class Uc(object): reg = uc_x86_xmm() reg.low_qword = value & 0xffffffffffffffff reg.high_qword = value >> 64 + if reg_id is x86_const.UC_X86_REG_MSR: + reg = uc_x86_msr() + reg.rid = value[0] + reg.value = value[1] + + if self._arch == uc.UC_ARCH_ARM64: + if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1): + reg = uc_arm64_neon128() + reg.low_qword = value & 0xffffffffffffffff + reg.high_qword = value >> 64 if reg is None: # convert to 64bit number to be safe @@ -339,6 +378,14 @@ class Uc(object): if status != uc.UC_ERR_OK: raise UcError(status) + # read from MSR - X86 only + def msr_read(self, msr_id): + return self.reg_read(x86_const.UC_X86_REG_MSR, msr_id) + + # write to MSR - X86 only + def msr_write(self, msr_id, value): + return self.reg_write(x86_const.UC_X86_REG_MSR, (msr_id, value)) + # read data from memory def mem_read(self, address, size): data = ctypes.create_string_buffer(size) diff --git a/bindings/python/unicorn/x86_const.py b/bindings/python/unicorn/x86_const.py index ee5ba38f..5642c543 100644 --- a/bindings/python/unicorn/x86_const.py +++ b/bindings/python/unicorn/x86_const.py @@ -250,7 +250,8 @@ UC_X86_REG_LDTR = 244 UC_X86_REG_TR = 245 UC_X86_REG_FPCW = 246 UC_X86_REG_FPTAG = 247 -UC_X86_REG_ENDING = 248 +UC_X86_REG_MSR = 248 +UC_X86_REG_ENDING = 249 # X86 instructions diff --git a/bindings/ruby/unicorn_gem/lib/unicorn/x86_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn/x86_const.rb index 2226de17..f85ae21a 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn/x86_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn/x86_const.rb @@ -252,7 +252,8 @@ module Unicorn UC_X86_REG_TR = 245 UC_X86_REG_FPCW = 246 UC_X86_REG_FPTAG = 247 - UC_X86_REG_ENDING = 248 + UC_X86_REG_MSR = 248 + UC_X86_REG_ENDING = 249 # X86 instructions diff --git a/include/uc_priv.h b/include/uc_priv.h index 4251b06b..e16ad943 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -253,3 +253,4 @@ struct uc_context { MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address); #endif +/* vim: set ts=4 noet: */ diff --git a/include/unicorn/x86.h b/include/unicorn/x86.h index cb3f1d93..40e3e3c7 100644 --- a/include/unicorn/x86.h +++ b/include/unicorn/x86.h @@ -19,64 +19,72 @@ typedef struct uc_x86_mmr { uint32_t flags; /* not used by GDTR and IDTR */ } uc_x86_mmr; +// Model-Specific Register structure, use this with UC_X86_REG_MSR (as the register ID) in +// call to uc_reg_write/uc_reg_read() to manipulate MSRs. +typedef struct uc_x86_msr { + uint32_t rid; // MSR id + uint64_t value; // MSR value +} uc_x86_msr; + // Callback function for tracing SYSCALL/SYSENTER (for uc_hook_intr()) // @user_data: user data passed to tracing APIs. typedef void (*uc_cb_insn_syscall_t)(struct uc_struct *uc, void *user_data); //> X86 registers typedef enum uc_x86_reg { - UC_X86_REG_INVALID = 0, - UC_X86_REG_AH, UC_X86_REG_AL, UC_X86_REG_AX, UC_X86_REG_BH, UC_X86_REG_BL, - UC_X86_REG_BP, UC_X86_REG_BPL, UC_X86_REG_BX, UC_X86_REG_CH, UC_X86_REG_CL, - UC_X86_REG_CS, UC_X86_REG_CX, UC_X86_REG_DH, UC_X86_REG_DI, UC_X86_REG_DIL, - UC_X86_REG_DL, UC_X86_REG_DS, UC_X86_REG_DX, UC_X86_REG_EAX, UC_X86_REG_EBP, - UC_X86_REG_EBX, UC_X86_REG_ECX, UC_X86_REG_EDI, UC_X86_REG_EDX, UC_X86_REG_EFLAGS, - UC_X86_REG_EIP, UC_X86_REG_EIZ, UC_X86_REG_ES, UC_X86_REG_ESI, UC_X86_REG_ESP, - UC_X86_REG_FPSW, UC_X86_REG_FS, UC_X86_REG_GS, UC_X86_REG_IP, UC_X86_REG_RAX, - UC_X86_REG_RBP, UC_X86_REG_RBX, UC_X86_REG_RCX, UC_X86_REG_RDI, UC_X86_REG_RDX, - UC_X86_REG_RIP, UC_X86_REG_RIZ, UC_X86_REG_RSI, UC_X86_REG_RSP, UC_X86_REG_SI, - UC_X86_REG_SIL, UC_X86_REG_SP, UC_X86_REG_SPL, UC_X86_REG_SS, UC_X86_REG_CR0, - UC_X86_REG_CR1, UC_X86_REG_CR2, UC_X86_REG_CR3, UC_X86_REG_CR4, UC_X86_REG_CR5, - UC_X86_REG_CR6, UC_X86_REG_CR7, UC_X86_REG_CR8, UC_X86_REG_CR9, UC_X86_REG_CR10, - UC_X86_REG_CR11, UC_X86_REG_CR12, UC_X86_REG_CR13, UC_X86_REG_CR14, UC_X86_REG_CR15, - UC_X86_REG_DR0, UC_X86_REG_DR1, UC_X86_REG_DR2, UC_X86_REG_DR3, UC_X86_REG_DR4, - UC_X86_REG_DR5, UC_X86_REG_DR6, UC_X86_REG_DR7, UC_X86_REG_DR8, UC_X86_REG_DR9, - UC_X86_REG_DR10, UC_X86_REG_DR11, UC_X86_REG_DR12, UC_X86_REG_DR13, UC_X86_REG_DR14, - UC_X86_REG_DR15, UC_X86_REG_FP0, UC_X86_REG_FP1, UC_X86_REG_FP2, UC_X86_REG_FP3, - UC_X86_REG_FP4, UC_X86_REG_FP5, UC_X86_REG_FP6, UC_X86_REG_FP7, - UC_X86_REG_K0, UC_X86_REG_K1, UC_X86_REG_K2, UC_X86_REG_K3, UC_X86_REG_K4, - UC_X86_REG_K5, UC_X86_REG_K6, UC_X86_REG_K7, UC_X86_REG_MM0, UC_X86_REG_MM1, - UC_X86_REG_MM2, UC_X86_REG_MM3, UC_X86_REG_MM4, UC_X86_REG_MM5, UC_X86_REG_MM6, - UC_X86_REG_MM7, UC_X86_REG_R8, UC_X86_REG_R9, UC_X86_REG_R10, UC_X86_REG_R11, - UC_X86_REG_R12, UC_X86_REG_R13, UC_X86_REG_R14, UC_X86_REG_R15, - UC_X86_REG_ST0, UC_X86_REG_ST1, UC_X86_REG_ST2, UC_X86_REG_ST3, - UC_X86_REG_ST4, UC_X86_REG_ST5, UC_X86_REG_ST6, UC_X86_REG_ST7, - UC_X86_REG_XMM0, UC_X86_REG_XMM1, UC_X86_REG_XMM2, UC_X86_REG_XMM3, UC_X86_REG_XMM4, - UC_X86_REG_XMM5, UC_X86_REG_XMM6, UC_X86_REG_XMM7, UC_X86_REG_XMM8, UC_X86_REG_XMM9, - UC_X86_REG_XMM10, UC_X86_REG_XMM11, UC_X86_REG_XMM12, UC_X86_REG_XMM13, UC_X86_REG_XMM14, - UC_X86_REG_XMM15, UC_X86_REG_XMM16, UC_X86_REG_XMM17, UC_X86_REG_XMM18, UC_X86_REG_XMM19, - UC_X86_REG_XMM20, UC_X86_REG_XMM21, UC_X86_REG_XMM22, UC_X86_REG_XMM23, UC_X86_REG_XMM24, - UC_X86_REG_XMM25, UC_X86_REG_XMM26, UC_X86_REG_XMM27, UC_X86_REG_XMM28, UC_X86_REG_XMM29, - UC_X86_REG_XMM30, UC_X86_REG_XMM31, UC_X86_REG_YMM0, UC_X86_REG_YMM1, UC_X86_REG_YMM2, - UC_X86_REG_YMM3, UC_X86_REG_YMM4, UC_X86_REG_YMM5, UC_X86_REG_YMM6, UC_X86_REG_YMM7, - UC_X86_REG_YMM8, UC_X86_REG_YMM9, UC_X86_REG_YMM10, UC_X86_REG_YMM11, UC_X86_REG_YMM12, - UC_X86_REG_YMM13, UC_X86_REG_YMM14, UC_X86_REG_YMM15, UC_X86_REG_YMM16, UC_X86_REG_YMM17, - UC_X86_REG_YMM18, UC_X86_REG_YMM19, UC_X86_REG_YMM20, UC_X86_REG_YMM21, UC_X86_REG_YMM22, - UC_X86_REG_YMM23, UC_X86_REG_YMM24, UC_X86_REG_YMM25, UC_X86_REG_YMM26, UC_X86_REG_YMM27, - UC_X86_REG_YMM28, UC_X86_REG_YMM29, UC_X86_REG_YMM30, UC_X86_REG_YMM31, UC_X86_REG_ZMM0, - UC_X86_REG_ZMM1, UC_X86_REG_ZMM2, UC_X86_REG_ZMM3, UC_X86_REG_ZMM4, UC_X86_REG_ZMM5, - UC_X86_REG_ZMM6, UC_X86_REG_ZMM7, UC_X86_REG_ZMM8, UC_X86_REG_ZMM9, UC_X86_REG_ZMM10, - UC_X86_REG_ZMM11, UC_X86_REG_ZMM12, UC_X86_REG_ZMM13, UC_X86_REG_ZMM14, UC_X86_REG_ZMM15, - UC_X86_REG_ZMM16, UC_X86_REG_ZMM17, UC_X86_REG_ZMM18, UC_X86_REG_ZMM19, UC_X86_REG_ZMM20, - UC_X86_REG_ZMM21, UC_X86_REG_ZMM22, UC_X86_REG_ZMM23, UC_X86_REG_ZMM24, UC_X86_REG_ZMM25, - UC_X86_REG_ZMM26, UC_X86_REG_ZMM27, UC_X86_REG_ZMM28, UC_X86_REG_ZMM29, UC_X86_REG_ZMM30, - UC_X86_REG_ZMM31, UC_X86_REG_R8B, UC_X86_REG_R9B, UC_X86_REG_R10B, UC_X86_REG_R11B, - UC_X86_REG_R12B, UC_X86_REG_R13B, UC_X86_REG_R14B, UC_X86_REG_R15B, UC_X86_REG_R8D, - UC_X86_REG_R9D, UC_X86_REG_R10D, UC_X86_REG_R11D, UC_X86_REG_R12D, UC_X86_REG_R13D, - UC_X86_REG_R14D, UC_X86_REG_R15D, UC_X86_REG_R8W, UC_X86_REG_R9W, UC_X86_REG_R10W, - UC_X86_REG_R11W, UC_X86_REG_R12W, UC_X86_REG_R13W, UC_X86_REG_R14W, UC_X86_REG_R15W, - UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR, UC_X86_REG_FPCW, - UC_X86_REG_FPTAG, + UC_X86_REG_INVALID = 0, + UC_X86_REG_AH, UC_X86_REG_AL, UC_X86_REG_AX, UC_X86_REG_BH, UC_X86_REG_BL, + UC_X86_REG_BP, UC_X86_REG_BPL, UC_X86_REG_BX, UC_X86_REG_CH, UC_X86_REG_CL, + UC_X86_REG_CS, UC_X86_REG_CX, UC_X86_REG_DH, UC_X86_REG_DI, UC_X86_REG_DIL, + UC_X86_REG_DL, UC_X86_REG_DS, UC_X86_REG_DX, UC_X86_REG_EAX, UC_X86_REG_EBP, + UC_X86_REG_EBX, UC_X86_REG_ECX, UC_X86_REG_EDI, UC_X86_REG_EDX, UC_X86_REG_EFLAGS, + UC_X86_REG_EIP, UC_X86_REG_EIZ, UC_X86_REG_ES, UC_X86_REG_ESI, UC_X86_REG_ESP, + UC_X86_REG_FPSW, UC_X86_REG_FS, UC_X86_REG_GS, UC_X86_REG_IP, UC_X86_REG_RAX, + UC_X86_REG_RBP, UC_X86_REG_RBX, UC_X86_REG_RCX, UC_X86_REG_RDI, UC_X86_REG_RDX, + UC_X86_REG_RIP, UC_X86_REG_RIZ, UC_X86_REG_RSI, UC_X86_REG_RSP, UC_X86_REG_SI, + UC_X86_REG_SIL, UC_X86_REG_SP, UC_X86_REG_SPL, UC_X86_REG_SS, UC_X86_REG_CR0, + UC_X86_REG_CR1, UC_X86_REG_CR2, UC_X86_REG_CR3, UC_X86_REG_CR4, UC_X86_REG_CR5, + UC_X86_REG_CR6, UC_X86_REG_CR7, UC_X86_REG_CR8, UC_X86_REG_CR9, UC_X86_REG_CR10, + UC_X86_REG_CR11, UC_X86_REG_CR12, UC_X86_REG_CR13, UC_X86_REG_CR14, UC_X86_REG_CR15, + UC_X86_REG_DR0, UC_X86_REG_DR1, UC_X86_REG_DR2, UC_X86_REG_DR3, UC_X86_REG_DR4, + UC_X86_REG_DR5, UC_X86_REG_DR6, UC_X86_REG_DR7, UC_X86_REG_DR8, UC_X86_REG_DR9, + UC_X86_REG_DR10, UC_X86_REG_DR11, UC_X86_REG_DR12, UC_X86_REG_DR13, UC_X86_REG_DR14, + UC_X86_REG_DR15, UC_X86_REG_FP0, UC_X86_REG_FP1, UC_X86_REG_FP2, UC_X86_REG_FP3, + UC_X86_REG_FP4, UC_X86_REG_FP5, UC_X86_REG_FP6, UC_X86_REG_FP7, + UC_X86_REG_K0, UC_X86_REG_K1, UC_X86_REG_K2, UC_X86_REG_K3, UC_X86_REG_K4, + UC_X86_REG_K5, UC_X86_REG_K6, UC_X86_REG_K7, UC_X86_REG_MM0, UC_X86_REG_MM1, + UC_X86_REG_MM2, UC_X86_REG_MM3, UC_X86_REG_MM4, UC_X86_REG_MM5, UC_X86_REG_MM6, + UC_X86_REG_MM7, UC_X86_REG_R8, UC_X86_REG_R9, UC_X86_REG_R10, UC_X86_REG_R11, + UC_X86_REG_R12, UC_X86_REG_R13, UC_X86_REG_R14, UC_X86_REG_R15, + UC_X86_REG_ST0, UC_X86_REG_ST1, UC_X86_REG_ST2, UC_X86_REG_ST3, + UC_X86_REG_ST4, UC_X86_REG_ST5, UC_X86_REG_ST6, UC_X86_REG_ST7, + UC_X86_REG_XMM0, UC_X86_REG_XMM1, UC_X86_REG_XMM2, UC_X86_REG_XMM3, UC_X86_REG_XMM4, + UC_X86_REG_XMM5, UC_X86_REG_XMM6, UC_X86_REG_XMM7, UC_X86_REG_XMM8, UC_X86_REG_XMM9, + UC_X86_REG_XMM10, UC_X86_REG_XMM11, UC_X86_REG_XMM12, UC_X86_REG_XMM13, UC_X86_REG_XMM14, + UC_X86_REG_XMM15, UC_X86_REG_XMM16, UC_X86_REG_XMM17, UC_X86_REG_XMM18, UC_X86_REG_XMM19, + UC_X86_REG_XMM20, UC_X86_REG_XMM21, UC_X86_REG_XMM22, UC_X86_REG_XMM23, UC_X86_REG_XMM24, + UC_X86_REG_XMM25, UC_X86_REG_XMM26, UC_X86_REG_XMM27, UC_X86_REG_XMM28, UC_X86_REG_XMM29, + UC_X86_REG_XMM30, UC_X86_REG_XMM31, UC_X86_REG_YMM0, UC_X86_REG_YMM1, UC_X86_REG_YMM2, + UC_X86_REG_YMM3, UC_X86_REG_YMM4, UC_X86_REG_YMM5, UC_X86_REG_YMM6, UC_X86_REG_YMM7, + UC_X86_REG_YMM8, UC_X86_REG_YMM9, UC_X86_REG_YMM10, UC_X86_REG_YMM11, UC_X86_REG_YMM12, + UC_X86_REG_YMM13, UC_X86_REG_YMM14, UC_X86_REG_YMM15, UC_X86_REG_YMM16, UC_X86_REG_YMM17, + UC_X86_REG_YMM18, UC_X86_REG_YMM19, UC_X86_REG_YMM20, UC_X86_REG_YMM21, UC_X86_REG_YMM22, + UC_X86_REG_YMM23, UC_X86_REG_YMM24, UC_X86_REG_YMM25, UC_X86_REG_YMM26, UC_X86_REG_YMM27, + UC_X86_REG_YMM28, UC_X86_REG_YMM29, UC_X86_REG_YMM30, UC_X86_REG_YMM31, UC_X86_REG_ZMM0, + UC_X86_REG_ZMM1, UC_X86_REG_ZMM2, UC_X86_REG_ZMM3, UC_X86_REG_ZMM4, UC_X86_REG_ZMM5, + UC_X86_REG_ZMM6, UC_X86_REG_ZMM7, UC_X86_REG_ZMM8, UC_X86_REG_ZMM9, UC_X86_REG_ZMM10, + UC_X86_REG_ZMM11, UC_X86_REG_ZMM12, UC_X86_REG_ZMM13, UC_X86_REG_ZMM14, UC_X86_REG_ZMM15, + UC_X86_REG_ZMM16, UC_X86_REG_ZMM17, UC_X86_REG_ZMM18, UC_X86_REG_ZMM19, UC_X86_REG_ZMM20, + UC_X86_REG_ZMM21, UC_X86_REG_ZMM22, UC_X86_REG_ZMM23, UC_X86_REG_ZMM24, UC_X86_REG_ZMM25, + UC_X86_REG_ZMM26, UC_X86_REG_ZMM27, UC_X86_REG_ZMM28, UC_X86_REG_ZMM29, UC_X86_REG_ZMM30, + UC_X86_REG_ZMM31, UC_X86_REG_R8B, UC_X86_REG_R9B, UC_X86_REG_R10B, UC_X86_REG_R11B, + UC_X86_REG_R12B, UC_X86_REG_R13B, UC_X86_REG_R14B, UC_X86_REG_R15B, UC_X86_REG_R8D, + UC_X86_REG_R9D, UC_X86_REG_R10D, UC_X86_REG_R11D, UC_X86_REG_R12D, UC_X86_REG_R13D, + UC_X86_REG_R14D, UC_X86_REG_R15D, UC_X86_REG_R8W, UC_X86_REG_R9W, UC_X86_REG_R10W, + UC_X86_REG_R11W, UC_X86_REG_R12W, UC_X86_REG_R13W, UC_X86_REG_R14W, UC_X86_REG_R15W, + UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR, UC_X86_REG_FPCW, + UC_X86_REG_FPTAG, + UC_X86_REG_MSR, // Model-Specific Register UC_X86_REG_ENDING // <-- mark the end of the list of registers } uc_x86_reg; diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 6cb47c34..7a7a5ea7 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_AARCH64_H #define UNICORN_AUTOGEN_AARCH64_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_aarch64 +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_aarch64 #define use_idiv_instructions_rt use_idiv_instructions_rt_aarch64 #define tcg_target_deposit_valid tcg_target_deposit_valid_aarch64 #define helper_power_down helper_power_down_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index 5ab27471..80225bdd 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_ARM_H #define UNICORN_AUTOGEN_ARM_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_arm +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_arm #define use_idiv_instructions_rt use_idiv_instructions_rt_arm #define tcg_target_deposit_valid tcg_target_deposit_valid_arm #define helper_power_down helper_power_down_arm diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 0561817d..047f6358 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -8,6 +8,7 @@ import sys symbols = ( 'aarch64_tb_set_jmp_target', + 'ppc_tb_set_jmp_target', 'use_idiv_instructions_rt', 'tcg_target_deposit_valid', 'helper_power_down', diff --git a/qemu/include/elf.h b/qemu/include/elf.h index c9b16056..b55aaa6f 100644 --- a/qemu/include/elf.h +++ b/qemu/include/elf.h @@ -126,11 +126,15 @@ /* Bits present in AT_HWCAP for Sparc. */ #define HWCAP_SPARC_VIS3 0x00020000 +/* Bits present in AT_HWCAP for PowerPC. */ +#define PPC_FEATURE_ARCH_2_06 0x00000100 + /* Symbolic values for the entries in the auxiliary table put on the initial stack */ #define AT_PLATFORM 15 /* string identifying CPU for optimizations */ #define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ - +#define AT_DCACHEBSIZE 19 /* data cache block size */ +#define AT_ICACHEBSIZE 20 /* instruction cache block size */ /* * 68k ELF relocation types diff --git a/qemu/m68k.h b/qemu/m68k.h index 9a265549..f40a8dc4 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_M68K_H #define UNICORN_AUTOGEN_M68K_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_m68k +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_m68k #define use_idiv_instructions_rt use_idiv_instructions_rt_m68k #define tcg_target_deposit_valid tcg_target_deposit_valid_m68k #define helper_power_down helper_power_down_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 57bb375a..1b8e9e2b 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_MIPS_H #define UNICORN_AUTOGEN_MIPS_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_mips #define use_idiv_instructions_rt use_idiv_instructions_rt_mips #define tcg_target_deposit_valid tcg_target_deposit_valid_mips #define helper_power_down helper_power_down_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index a6af4eeb..06b30666 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_MIPS64_H #define UNICORN_AUTOGEN_MIPS64_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips64 +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_mips64 #define use_idiv_instructions_rt use_idiv_instructions_rt_mips64 #define tcg_target_deposit_valid tcg_target_deposit_valid_mips64 #define helper_power_down helper_power_down_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index c453400d..87cc74c8 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_MIPS64EL_H #define UNICORN_AUTOGEN_MIPS64EL_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips64el +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_mips64el #define use_idiv_instructions_rt use_idiv_instructions_rt_mips64el #define tcg_target_deposit_valid tcg_target_deposit_valid_mips64el #define helper_power_down helper_power_down_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 4ad7be8d..a8a3fb4f 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_MIPSEL_H #define UNICORN_AUTOGEN_MIPSEL_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mipsel +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_mipsel #define use_idiv_instructions_rt use_idiv_instructions_rt_mipsel #define tcg_target_deposit_valid tcg_target_deposit_valid_mipsel #define helper_power_down helper_power_down_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 80520561..fd831d98 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_POWERPC_H #define UNICORN_AUTOGEN_POWERPC_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_powerpc +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_powerpc #define use_idiv_instructions_rt use_idiv_instructions_rt_powerpc #define tcg_target_deposit_valid tcg_target_deposit_valid_powerpc #define helper_power_down helper_power_down_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index b3c6d853..fda21bf4 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_SPARC_H #define UNICORN_AUTOGEN_SPARC_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_sparc +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_sparc #define use_idiv_instructions_rt use_idiv_instructions_rt_sparc #define tcg_target_deposit_valid tcg_target_deposit_valid_sparc #define helper_power_down helper_power_down_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index c8860863..aaafd634 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_SPARC64_H #define UNICORN_AUTOGEN_SPARC64_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_sparc64 +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_sparc64 #define use_idiv_instructions_rt use_idiv_instructions_rt_sparc64 #define tcg_target_deposit_valid tcg_target_deposit_valid_sparc64 #define helper_power_down helper_power_down_sparc64 diff --git a/qemu/target-arm/unicorn_aarch64.c b/qemu/target-arm/unicorn_aarch64.c index 3631e9ce..9a884b70 100644 --- a/qemu/target-arm/unicorn_aarch64.c +++ b/qemu/target-arm/unicorn_aarch64.c @@ -52,10 +52,27 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; + // V & Q registers are the same + if (regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31) { + regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0; + } if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) { *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0]; } else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { *(int32_t *)value = READ_DWORD(ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_W0]); + } else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { + float64 *dst = (float64*) value; + uint32_t reg_index = 2*(regid - UC_ARM64_REG_Q0); + dst[0] = ARM_CPU(uc, mycpu)->env.vfp.regs[reg_index]; + dst[1] = ARM_CPU(uc, mycpu)->env.vfp.regs[reg_index+1]; + } else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) { + *(float64*)value = ARM_CPU(uc, mycpu)->env.vfp.regs[2*(regid - UC_ARM64_REG_D0)]; + } else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) { + *(int32_t*)value = READ_DWORD(ARM_CPU(uc, mycpu)->env.vfp.regs[2*(regid - UC_ARM64_REG_S0)]); + } else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) { + *(int16_t*)value = READ_WORD(ARM_CPU(uc, mycpu)->env.vfp.regs[2*(regid - UC_ARM64_REG_H0)]); + } else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) { + *(int8_t*)value = READ_BYTE_L(ARM_CPU(uc, mycpu)->env.vfp.regs[2*(regid - UC_ARM64_REG_B0)]); } else { switch(regid) { default: break; @@ -86,10 +103,26 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; + if (regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31) { + regid += UC_ARM64_REG_Q0 - UC_ARM64_REG_V0; + } if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) { ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value; } else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { WRITE_DWORD(ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_W0], *(uint32_t *)value); + } else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { + float64 *src = (float64*) value; + uint32_t reg_index = 2*(regid - UC_ARM64_REG_Q0); + ARM_CPU(uc, mycpu)->env.vfp.regs[reg_index] = src[0]; + ARM_CPU(uc, mycpu)->env.vfp.regs[reg_index+1] = src[1]; + } else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) { + ARM_CPU(uc, mycpu)->env.vfp.regs[2*(regid - UC_ARM64_REG_D0)] = * (float64*) value; + } else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) { + WRITE_DWORD(ARM_CPU(uc, mycpu)->env.vfp.regs[2*(regid - UC_ARM64_REG_S0)], *(int32_t*) value); + } else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) { + WRITE_WORD(ARM_CPU(uc, mycpu)->env.vfp.regs[2*(regid - UC_ARM64_REG_H0)], *(int16_t*) value); + } else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) { + WRITE_BYTE_L(ARM_CPU(uc, mycpu)->env.vfp.regs[2*(regid - UC_ARM64_REG_B0)], *(int8_t*) value); } else { switch(regid) { default: break; diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index a7ecc249..3d07683f 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -64,6 +64,9 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun *(float64 *)value = ARM_CPU(uc, mycpu)->env.vfp.regs[regid - UC_ARM_REG_D0]; else { switch(regid) { + case UC_ARM_REG_APSR: + *(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env) & CPSR_NZCV; + break; case UC_ARM_REG_CPSR: *(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env); break; @@ -109,6 +112,9 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, i ARM_CPU(uc, mycpu)->env.vfp.regs[regid - UC_ARM_REG_D0] = *(float64 *)value; else { switch(regid) { + case UC_ARM_REG_APSR: + cpsr_write(&ARM_CPU(uc, mycpu)->env, *(uint32_t *)value, CPSR_NZCV); + break; case UC_ARM_REG_CPSR: cpsr_write(&ARM_CPU(uc, mycpu)->env, *(uint32_t *)value, ~0); break; diff --git a/qemu/target-i386/unicorn.c b/qemu/target-i386/unicorn.c index 1c1aee92..8af79649 100644 --- a/qemu/target-i386/unicorn.c +++ b/qemu/target-i386/unicorn.c @@ -17,6 +17,10 @@ static void load_seg_16_helper(CPUX86State *env, int seg, uint32_t selector) cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, X86_NON_CS_FLAGS); } + +extern void helper_wrmsr(CPUX86State *env); +extern void helper_rdmsr(CPUX86State *env); + const int X86_REGS_STORAGE_SIZE = offsetof(CPUX86State, tlb_table); static void x86_set_pc(struct uc_struct *uc, uint64_t address) @@ -156,6 +160,49 @@ void x86_reg_reset(struct uc_struct *uc) } } +static int x86_msr_read(struct uc_struct *uc, uc_x86_msr *msr) +{ + CPUX86State *env = (CPUX86State *)uc->cpu->env_ptr; + uint64_t ecx = env->regs[R_ECX]; + uint64_t eax = env->regs[R_EAX]; + uint64_t edx = env->regs[R_EDX]; + + env->regs[R_ECX] = msr->rid; + helper_rdmsr(env); + + msr->value = ((uint32_t)env->regs[R_EAX]) | + ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); + + env->regs[R_EAX] = eax; + env->regs[R_ECX] = ecx; + env->regs[R_EDX] = edx; + + /* The implementation doesn't throw exception or return an error if there is one, so + * we will return 0. */ + return 0; +} + +static int x86_msr_write(struct uc_struct *uc, uc_x86_msr *msr) +{ + CPUX86State *env = (CPUX86State *)uc->cpu->env_ptr; + uint64_t ecx = env->regs[R_ECX]; + uint64_t eax = env->regs[R_EAX]; + uint64_t edx = env->regs[R_EDX]; + + env->regs[R_ECX] = msr->rid; + env->regs[R_EAX] = (unsigned int)msr->value; + env->regs[R_EDX] = (unsigned int)(msr->value >> 32); + helper_wrmsr(env); + + env->regs[R_ECX] = ecx; + env->regs[R_EAX] = eax; + env->regs[R_EDX] = edx; + + /* The implementation doesn't throw exception or return an error if there is one, so + * we will return 0. */ + return 0; +} + int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) { CPUState *mycpu = uc->cpu; @@ -401,6 +448,9 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector; ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags; break; + case UC_X86_REG_MSR: + x86_msr_read(uc, (uc_x86_msr *)value); + break; } break; @@ -680,6 +730,9 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun ((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector; ((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags; break; + case UC_X86_REG_MSR: + x86_msr_read(uc, (uc_x86_msr *)value); + break; } break; #endif @@ -924,6 +977,9 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags; break; + case UC_X86_REG_MSR: + x86_msr_write(uc, (uc_x86_msr *)value); + break; } break; @@ -1213,6 +1269,9 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags; break; + case UC_X86_REG_MSR: + x86_msr_write(uc, (uc_x86_msr *)value); + break; } break; #endif @@ -1257,3 +1316,5 @@ void x86_uc_init(struct uc_struct* uc) uc->stop_interrupt = x86_stop_interrupt; uc_common_init(uc); } + +/* vim: set ts=4 sts=4 sw=4 et: */ diff --git a/qemu/target-mips/unicorn.c b/qemu/target-mips/unicorn.c index 86dd5582..3d821528 100644 --- a/qemu/target-mips/unicorn.c +++ b/qemu/target-mips/unicorn.c @@ -18,6 +18,12 @@ const int MIPS_REGS_STORAGE_SIZE = offsetof(CPUMIPSState, tlb_table); #endif #endif +#ifdef TARGET_MIPS64 +typedef uint64_t mipsreg_t; +#else +typedef uint32_t mipsreg_t; +#endif + static uint64_t mips_mem_redirect(uint64_t address) { // kseg0 range masks off high address bit @@ -91,7 +97,7 @@ int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int cou switch(regid) { default: break; case UC_MIPS_REG_PC: - *(int32_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.PC; + *(mipsreg_t *)value = MIPS_CPU(uc, mycpu)->env.active_tc.PC; break; } } @@ -109,12 +115,12 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, unsigned int regid = regs[i]; const void *value = vals[i]; if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) - MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0] = *(uint32_t *)value; + MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0] = *(mipsreg_t *)value; else { switch(regid) { default: break; case UC_MIPS_REG_PC: - MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(uint32_t *)value; + MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(mipsreg_t *)value; // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index 56e1da4b..c82e33b7 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -717,8 +717,8 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret, int is_64bit = sizemask & (1 << (i+1)*2); if (is_64bit) { TCGv_i64 orig = MAKE_TCGV_I64(args[i]); - TCGv_i32 h = tcg_temp_new_i32(); - TCGv_i32 l = tcg_temp_new_i32(); + TCGv_i32 h = tcg_temp_new_i32(s); + TCGv_i32 l = tcg_temp_new_i32(s); tcg_gen_extr_i64_i32(l, h, orig); split_args[real_args++] = GET_TCGV_I32(h); split_args[real_args++] = GET_TCGV_I32(l); @@ -738,9 +738,9 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret, TCGv_i64 temp = tcg_temp_new_i64(s); TCGv_i64 orig = MAKE_TCGV_I64(args[i]); if (is_signed) { - tcg_gen_ext32s_i64(temp, orig); + tcg_gen_ext32s_i64(s, temp, orig); } else { - tcg_gen_ext32u_i64(temp, orig); + tcg_gen_ext32u_i64(s, temp, orig); } args[i] = GET_TCGV_I64(temp); } @@ -834,8 +834,8 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret, if (is_64bit) { TCGv_i32 h = MAKE_TCGV_I32(args[real_args++]); TCGv_i32 l = MAKE_TCGV_I32(args[real_args++]); - tcg_temp_free_i32(h); - tcg_temp_free_i32(l); + tcg_temp_free_i32(s, h); + tcg_temp_free_i32(s, l); } else { real_args++; } @@ -845,15 +845,15 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret, Note that describing these as TCGv_i64 eliminates an unnecessary zero-extension that tcg_gen_concat_i32_i64 would create. */ tcg_gen_concat32_i64(MAKE_TCGV_I64(ret), retl, reth); - tcg_temp_free_i64(retl); - tcg_temp_free_i64(reth); + tcg_temp_free_i64(s, retl); + tcg_temp_free_i64(s, reth); } #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64 for (i = 0; i < nargs; ++i) { int is_64bit = sizemask & (1 << (i+1)*2); if (!is_64bit) { TCGv_i64 temp = MAKE_TCGV_I64(args[i]); - tcg_temp_free_i64(temp); + tcg_temp_free_i64(s, temp); } } #endif /* TCG_TARGET_EXTEND_ARGS */ diff --git a/qemu/x86_64.h b/qemu/x86_64.h index df86439d..71025141 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -2,6 +2,7 @@ #ifndef UNICORN_AUTOGEN_X86_64_H #define UNICORN_AUTOGEN_X86_64_H #define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_x86_64 +#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_x86_64 #define use_idiv_instructions_rt use_idiv_instructions_rt_x86_64 #define tcg_target_deposit_valid tcg_target_deposit_valid_x86_64 #define helper_power_down helper_power_down_x86_64 diff --git a/samples/sample_all.sh b/samples/sample_all.sh index 502171d4..026e0107 100755 --- a/samples/sample_all.sh +++ b/samples/sample_all.sh @@ -42,3 +42,18 @@ if test -e $DIR/sample_m68k; then echo "==========================" $DIR/sample_m68k fi + +if test -e $DIR/mem_apis; then + echo "==========================" + $DIR/mem_apis +fi + +if test -e $DIR/sample_batch_reg; then + echo "==========================" + $DIR/sample_batch_reg +fi + +if test -e $DIR/sample_x86_32_gdt_and_seg_regs; then + echo "==========================" + $DIR/sample_x86_32_gdt_and_seg_regs +fi diff --git a/tests/regress/.gitignore b/tests/regress/.gitignore index 00144a35..ca97ad9b 100644 --- a/tests/regress/.gitignore +++ b/tests/regress/.gitignore @@ -1,5 +1,6 @@ !*.c +arm_enable_vfp map_crash sigill sigill2 diff --git a/tests/regress/eflags_noset.c b/tests/regress/eflags_noset.c index 9d4f2291..7f1b9710 100644 --- a/tests/regress/eflags_noset.c +++ b/tests/regress/eflags_noset.c @@ -23,26 +23,32 @@ typedef uint64_t puint; uint32_t realEflags() { puint val = 0; - puint i = 0xFFFFFEFF; //attempt to set ALL bits except trap flag. #if defined(__i386__) + puint i = 0xFFFFFEFF; //attempt to set ALL bits except trap flag. + __asm__("pushf\n\t" "push %0\n\t" "popf\n\t" "pushf\n\t" "pop %0\n\t" "popf" -#else + : "=r"(val) + : "r"(i) + : "%0"); +#elif defined(__x86_64__) + puint i = 0xFFFFFEFF; //attempt to set ALL bits except trap flag. + __asm__("pushfq\n\t" "pushq %0\n\t" "popfq\n\t" "pushfq\n\t" "popq %0\n\t" "popfq" -#endif : "=r"(val) : "r"(i) : "%0"); +#endif printf("Real system eflags: 0x%08"PRIX3264"\n", val); @@ -51,7 +57,7 @@ uint32_t realEflags() static void VM_exec() { - +#if defined(__i386__) || defined(__x86_64__) uc_engine *uc; uc_err err; unsigned int r_eax, eflags, r_esp, realflags = 0; @@ -110,6 +116,7 @@ static void VM_exec() realflags = realEflags(); assert(r_eax == realflags); +#endif } int main(int argc, char *argv[]) diff --git a/uc.c b/uc.c index 65e82087..be0d288e 100644 --- a/uc.c +++ b/uc.c @@ -380,14 +380,12 @@ uc_err uc_reg_read(uc_engine *uc, int regid, void *value) return uc_reg_read_batch(uc, ®id, &value, 1); } - UNICORN_EXPORT uc_err uc_reg_write(uc_engine *uc, int regid, const void *value) { return uc_reg_write_batch(uc, ®id, (void *const *)&value, 1); } - // check if a memory area is mapped // this is complicated because an area can overlap adjacent blocks static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size)