fix merge conflicts
This commit is contained in:
9
Makefile
9
Makefile
@ -9,6 +9,13 @@ include pkgconfig.mk # package version
|
|||||||
|
|
||||||
LIBNAME = unicorn
|
LIBNAME = unicorn
|
||||||
UNAME_S := $(shell uname -s)
|
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)
|
GENOBJ = $(shell find qemu/$(1) -name "*.o" 2>/dev/null)
|
||||||
|
|
||||||
@ -204,7 +211,7 @@ qemu/config-host.h-timestamp:
|
|||||||
cd qemu && \
|
cd qemu && \
|
||||||
./configure --cc="${CC}" --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ${UNICORN_QEMU_FLAGS}
|
./configure --cc="${CC}" --extra-cflags="$(UNICORN_CFLAGS)" --target-list="$(UNICORN_TARGETS)" ${UNICORN_QEMU_FLAGS}
|
||||||
printf "$(UNICORN_ARCHS)" > config.log
|
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))
|
$(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)
|
unicorn: $(LIBRARY) $(ARCHIVE)
|
||||||
|
@ -42,7 +42,7 @@ python:
|
|||||||
$(ENV_VARS) python python/$(@:%.txt=%) > $@
|
$(ENV_VARS) python python/$(@:%.txt=%) > $@
|
||||||
|
|
||||||
%.py.test: %.c.txt %.py.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:
|
clean:
|
||||||
# rm -rf *.txt
|
# rm -rf *.txt
|
||||||
|
@ -257,7 +257,8 @@ module X86 =
|
|||||||
let UC_X86_REG_TR = 245
|
let UC_X86_REG_TR = 245
|
||||||
let UC_X86_REG_FPCW = 246
|
let UC_X86_REG_FPCW = 246
|
||||||
let UC_X86_REG_FPTAG = 247
|
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
|
// X86 instructions
|
||||||
|
|
||||||
|
@ -252,7 +252,8 @@ const (
|
|||||||
X86_REG_TR = 245
|
X86_REG_TR = 245
|
||||||
X86_REG_FPCW = 246
|
X86_REG_FPCW = 246
|
||||||
X86_REG_FPTAG = 247
|
X86_REG_FPTAG = 247
|
||||||
X86_REG_ENDING = 248
|
X86_REG_MSR = 248
|
||||||
|
X86_REG_ENDING = 249
|
||||||
|
|
||||||
// X86 instructions
|
// X86 instructions
|
||||||
|
|
||||||
|
1
bindings/haskell/.gitignore
vendored
1
bindings/haskell/.gitignore
vendored
@ -21,3 +21,4 @@ SampleMips
|
|||||||
SampleSparc
|
SampleSparc
|
||||||
SampleX86
|
SampleX86
|
||||||
Shellcode
|
Shellcode
|
||||||
|
SampleBatchReg
|
||||||
|
99
bindings/haskell/samples/SampleBatchReg.hs
Normal file
99
bindings/haskell/samples/SampleBatchReg.hs
Normal file
@ -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
|
@ -98,7 +98,7 @@ hookCode :: CodeHook ()
|
|||||||
hookCode uc addr size _ = do
|
hookCode uc addr size _ = do
|
||||||
runEmulator $ do
|
runEmulator $ do
|
||||||
emuPutStrLn $ ">>> Tracing instruction at 0x" ++ showHex addr ++
|
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
|
eflags <- regRead uc X86.Eflags
|
||||||
emuPutStrLn $ ">>> --- EFLAGS is 0x" ++ showHex eflags
|
emuPutStrLn $ ">>> --- EFLAGS is 0x" ++ showHex eflags
|
||||||
|
@ -25,6 +25,8 @@ module Unicorn
|
|||||||
-- * Register operations
|
-- * Register operations
|
||||||
, regWrite
|
, regWrite
|
||||||
, regRead
|
, regRead
|
||||||
|
, regWriteBatch
|
||||||
|
, regReadBatch
|
||||||
|
|
||||||
-- * Memory operations
|
-- * Memory operations
|
||||||
, MemoryPermission(..)
|
, MemoryPermission(..)
|
||||||
@ -140,13 +142,11 @@ stop uc = do
|
|||||||
-- | Write to register.
|
-- | Write to register.
|
||||||
regWrite :: Reg r
|
regWrite :: Reg r
|
||||||
=> Engine -- ^ 'Unicorn' engine handle
|
=> Engine -- ^ 'Unicorn' engine handle
|
||||||
-> r -- ^ Register ID to write to
|
-> r -- ^ Register to write to
|
||||||
-> Int64 -- ^ Value to write to register
|
-> Int64 -- ^ Value to write to register
|
||||||
-> Emulator () -- ^ An 'Error' on failure
|
-> Emulator () -- ^ An 'Error' on failure
|
||||||
regWrite uc regId value = do
|
regWrite uc reg value = do
|
||||||
err <- lift . alloca $ \ptr -> do
|
err <- lift $ ucRegWrite uc reg value
|
||||||
poke ptr value
|
|
||||||
ucRegWrite uc regId ptr
|
|
||||||
if err == ErrOk then
|
if err == ErrOk then
|
||||||
right ()
|
right ()
|
||||||
else
|
else
|
||||||
@ -155,16 +155,49 @@ regWrite uc regId value = do
|
|||||||
-- | Read register value.
|
-- | Read register value.
|
||||||
regRead :: Reg r
|
regRead :: Reg r
|
||||||
=> Engine -- ^ 'Unicorn' engine handle
|
=> 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,
|
-> Emulator Int64 -- ^ The value read from the register on success,
|
||||||
-- or an 'Error' on failure
|
-- or an 'Error' on failure
|
||||||
regRead uc regId = do
|
regRead uc reg = do
|
||||||
(err, val) <- lift $ ucRegRead uc regId
|
(err, val) <- lift $ ucRegRead uc reg
|
||||||
if err == ErrOk then
|
if err == ErrOk then
|
||||||
right val
|
right val
|
||||||
else
|
else
|
||||||
left err
|
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
|
-- Memory operations
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -190,12 +223,12 @@ memRead :: Engine -- ^ 'Unicorn' engine handle
|
|||||||
-- an 'Error' on failure
|
-- an 'Error' on failure
|
||||||
memRead uc address size = do
|
memRead uc address size = do
|
||||||
-- Allocate an array of the given size
|
-- Allocate an array of the given size
|
||||||
result <- lift . allocaArray size $ \ptr -> do
|
result <- lift . allocaArray size $ \array -> do
|
||||||
err <- ucMemRead uc address ptr size
|
err <- ucMemRead uc address array size
|
||||||
if err == ErrOk then
|
if err == ErrOk then
|
||||||
-- If ucMemRead completed successfully, pack the contents of the
|
-- If ucMemRead completed successfully, pack the contents of the
|
||||||
-- array into a ByteString and return it
|
-- array into a ByteString and return it
|
||||||
liftM (Right . pack) (peekArray size ptr)
|
liftM (Right . pack) (peekArray size array)
|
||||||
else
|
else
|
||||||
-- Otherwise return the error
|
-- Otherwise return the error
|
||||||
return $ Left err
|
return $ Left err
|
||||||
|
@ -314,7 +314,7 @@ marshalMemoryHook memoryHook =
|
|||||||
maybeValue = case memAccess of
|
maybeValue = case memAccess of
|
||||||
MemRead -> Nothing
|
MemRead -> Nothing
|
||||||
MemWrite -> Just $ fromIntegral value
|
MemWrite -> Just $ fromIntegral value
|
||||||
_ -> undefined -- XX Handle this?
|
_ -> error "Invalid memory access"
|
||||||
memoryHook uc memAccess address (fromIntegral size) maybeValue userData
|
memoryHook uc memAccess address (fromIntegral size) maybeValue userData
|
||||||
|
|
||||||
-- | Callback function for hooking memory reads.
|
-- | Callback function for hooking memory reads.
|
||||||
@ -390,7 +390,7 @@ marshalMemoryEventHook eventMemoryHook =
|
|||||||
MemReadProt -> Nothing
|
MemReadProt -> Nothing
|
||||||
MemWriteUnmapped -> Just $ fromIntegral value
|
MemWriteUnmapped -> Just $ fromIntegral value
|
||||||
MemWriteProt -> Just $ fromIntegral value
|
MemWriteProt -> Just $ fromIntegral value
|
||||||
_ -> undefined -- XX Handle this?
|
_ -> error "Invalid memory access"
|
||||||
res <- eventMemoryHook uc memAccess address (fromIntegral size)
|
res <- eventMemoryHook uc memAccess address (fromIntegral size)
|
||||||
maybeValue userData
|
maybeValue userData
|
||||||
return $ boolToInt res
|
return $ boolToInt res
|
||||||
|
@ -28,6 +28,8 @@ module Unicorn.Internal.Unicorn
|
|||||||
, ucEmuStop
|
, ucEmuStop
|
||||||
, ucRegWrite
|
, ucRegWrite
|
||||||
, ucRegRead
|
, ucRegRead
|
||||||
|
, ucRegWriteBatch
|
||||||
|
, ucRegReadBatch
|
||||||
, ucMemWrite
|
, ucMemWrite
|
||||||
, ucMemRead
|
, ucMemRead
|
||||||
, ucMemMap
|
, ucMemMap
|
||||||
@ -154,7 +156,8 @@ mkContext ptr =
|
|||||||
, `Word64'
|
, `Word64'
|
||||||
, `Word64'
|
, `Word64'
|
||||||
, `Int'
|
, `Int'
|
||||||
, `Int'} -> `Error'
|
, `Int'
|
||||||
|
} -> `Error'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# fun uc_emu_stop as ^
|
{# fun uc_emu_stop as ^
|
||||||
@ -166,19 +169,37 @@ mkContext ptr =
|
|||||||
-- Register operations
|
-- Register operations
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
{# fun uc_reg_write as ^
|
{# fun uc_reg_write_wrapper as ucRegWrite
|
||||||
`Reg r' =>
|
`Reg r' =>
|
||||||
{ `Engine'
|
{ `Engine'
|
||||||
, enumToNum `r'
|
, enumToNum `r'
|
||||||
, castPtr `Ptr Int64'
|
, withIntegral* `Int64'
|
||||||
} -> `Error'
|
} -> `Error'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# fun uc_reg_read as ^
|
{# fun uc_reg_read_wrapper as ucRegRead
|
||||||
`Reg r' =>
|
`Reg r' =>
|
||||||
{ `Engine'
|
{ `Engine'
|
||||||
, enumToNum `r'
|
, 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'
|
} -> `Error'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
@ -197,7 +218,8 @@ mkContext ptr =
|
|||||||
{ `Engine'
|
{ `Engine'
|
||||||
, `Word64'
|
, `Word64'
|
||||||
, castPtr `Ptr Word8'
|
, castPtr `Ptr Word8'
|
||||||
, `Int'} -> `Error'
|
, `Int'
|
||||||
|
} -> `Error'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# fun uc_mem_map as ^
|
{# fun uc_mem_map as ^
|
||||||
@ -205,7 +227,8 @@ mkContext ptr =
|
|||||||
, `Word64'
|
, `Word64'
|
||||||
, `Int'
|
, `Int'
|
||||||
, combineEnums `[MemoryPermission]'
|
, combineEnums `[MemoryPermission]'
|
||||||
} -> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun uc_mem_unmap as ^
|
{# fun uc_mem_unmap as ^
|
||||||
{ `Engine'
|
{ `Engine'
|
||||||
@ -296,13 +319,32 @@ expandMemPerms perms =
|
|||||||
checkRWE _ [] =
|
checkRWE _ [] =
|
||||||
[]
|
[]
|
||||||
|
|
||||||
allocaInt64ToVoid :: (Ptr () -> IO b)
|
withIntegral :: (Integral a, Num b, Storable b)
|
||||||
-> IO b
|
=> a
|
||||||
allocaInt64ToVoid f =
|
-> (Ptr b -> IO c)
|
||||||
alloca $ \(ptr :: Ptr Int64) -> poke ptr 0 >> f (castPtr ptr)
|
-> IO c
|
||||||
|
withIntegral =
|
||||||
|
with . fromIntegral
|
||||||
|
|
||||||
withByteStringLen :: ByteString
|
withByteStringLen :: Integral a
|
||||||
-> ((Ptr (), CULong) -> IO a)
|
=> ByteString
|
||||||
-> IO a
|
-> ((Ptr (), a) -> IO b)
|
||||||
|
-> IO b
|
||||||
withByteStringLen bs f =
|
withByteStringLen bs f =
|
||||||
useAsCStringLen bs $ \(ptr, len) -> f (castPtr ptr, fromIntegral len)
|
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
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "unicorn_wrapper.h"
|
#include "unicorn_wrapper.h"
|
||||||
|
|
||||||
void uc_close_wrapper(uc_engine *uc) {
|
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) {
|
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) {
|
void uc_free_wrapper(void *mem) {
|
||||||
uc_free(mem);
|
uc_free(mem);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef UNICORN_WRAPPER_H
|
#ifndef UNICORN_WRAPPER_H
|
||||||
#define UNICORN_WRAPPER_H
|
#define UNICORN_WRAPPER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -13,6 +14,14 @@ void uc_close_wrapper(uc_engine *uc);
|
|||||||
*/
|
*/
|
||||||
void uc_close_dummy(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.
|
* Wrap Unicorn's uc_free function and ignore the returned error code.
|
||||||
*/
|
*/
|
||||||
|
@ -254,7 +254,8 @@ public interface X86Const {
|
|||||||
public static final int UC_X86_REG_TR = 245;
|
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_FPCW = 246;
|
||||||
public static final int UC_X86_REG_FPTAG = 247;
|
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
|
// X86 instructions
|
||||||
|
|
||||||
|
@ -41,7 +41,8 @@ def test_arm():
|
|||||||
mu.reg_write(UC_ARM_REG_R0, 0x1234)
|
mu.reg_write(UC_ARM_REG_R0, 0x1234)
|
||||||
mu.reg_write(UC_ARM_REG_R2, 0x6789)
|
mu.reg_write(UC_ARM_REG_R2, 0x6789)
|
||||||
mu.reg_write(UC_ARM_REG_R3, 0x3333)
|
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
|
# tracing all basic blocks with customized callback
|
||||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import os.path
|
|||||||
import sys
|
import sys
|
||||||
import weakref
|
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__"):
|
if not hasattr(sys.modules[__name__], "__file__"):
|
||||||
__file__ = inspect.getfile(inspect.currentframe())
|
__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
|
("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):
|
class uc_x86_float80(ctypes.Structure):
|
||||||
"""Float80"""
|
"""Float80"""
|
||||||
@ -218,6 +223,13 @@ class uc_x86_xmm(ctypes.Structure):
|
|||||||
("high_qword", ctypes.c_uint64),
|
("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.
|
# Subclassing ref to allow property assignment.
|
||||||
class UcRef(weakref.ref):
|
class UcRef(weakref.ref):
|
||||||
pass
|
pass
|
||||||
@ -282,7 +294,7 @@ class Uc(object):
|
|||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
|
|
||||||
# return the value of a register
|
# 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 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]:
|
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()
|
reg = uc_x86_mmr()
|
||||||
@ -302,6 +314,23 @@ class Uc(object):
|
|||||||
if status != uc.UC_ERR_OK:
|
if status != uc.UC_ERR_OK:
|
||||||
raise UcError(status)
|
raise UcError(status)
|
||||||
return reg.low_qword | (reg.high_qword << 64)
|
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
|
# read to 64bit number to be safe
|
||||||
reg = ctypes.c_uint64(0)
|
reg = ctypes.c_uint64(0)
|
||||||
@ -330,6 +359,16 @@ class Uc(object):
|
|||||||
reg = uc_x86_xmm()
|
reg = uc_x86_xmm()
|
||||||
reg.low_qword = value & 0xffffffffffffffff
|
reg.low_qword = value & 0xffffffffffffffff
|
||||||
reg.high_qword = value >> 64
|
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:
|
if reg is None:
|
||||||
# convert to 64bit number to be safe
|
# convert to 64bit number to be safe
|
||||||
@ -339,6 +378,14 @@ class Uc(object):
|
|||||||
if status != uc.UC_ERR_OK:
|
if status != uc.UC_ERR_OK:
|
||||||
raise UcError(status)
|
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
|
# read data from memory
|
||||||
def mem_read(self, address, size):
|
def mem_read(self, address, size):
|
||||||
data = ctypes.create_string_buffer(size)
|
data = ctypes.create_string_buffer(size)
|
||||||
|
@ -250,7 +250,8 @@ UC_X86_REG_LDTR = 244
|
|||||||
UC_X86_REG_TR = 245
|
UC_X86_REG_TR = 245
|
||||||
UC_X86_REG_FPCW = 246
|
UC_X86_REG_FPCW = 246
|
||||||
UC_X86_REG_FPTAG = 247
|
UC_X86_REG_FPTAG = 247
|
||||||
UC_X86_REG_ENDING = 248
|
UC_X86_REG_MSR = 248
|
||||||
|
UC_X86_REG_ENDING = 249
|
||||||
|
|
||||||
# X86 instructions
|
# X86 instructions
|
||||||
|
|
||||||
|
@ -252,7 +252,8 @@ module Unicorn
|
|||||||
UC_X86_REG_TR = 245
|
UC_X86_REG_TR = 245
|
||||||
UC_X86_REG_FPCW = 246
|
UC_X86_REG_FPCW = 246
|
||||||
UC_X86_REG_FPTAG = 247
|
UC_X86_REG_FPTAG = 247
|
||||||
UC_X86_REG_ENDING = 248
|
UC_X86_REG_MSR = 248
|
||||||
|
UC_X86_REG_ENDING = 249
|
||||||
|
|
||||||
# X86 instructions
|
# X86 instructions
|
||||||
|
|
||||||
|
@ -253,3 +253,4 @@ struct uc_context {
|
|||||||
MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address);
|
MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
/* vim: set ts=4 noet: */
|
||||||
|
@ -19,64 +19,72 @@ typedef struct uc_x86_mmr {
|
|||||||
uint32_t flags; /* not used by GDTR and IDTR */
|
uint32_t flags; /* not used by GDTR and IDTR */
|
||||||
} uc_x86_mmr;
|
} 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())
|
// Callback function for tracing SYSCALL/SYSENTER (for uc_hook_intr())
|
||||||
// @user_data: user data passed to tracing APIs.
|
// @user_data: user data passed to tracing APIs.
|
||||||
typedef void (*uc_cb_insn_syscall_t)(struct uc_struct *uc, void *user_data);
|
typedef void (*uc_cb_insn_syscall_t)(struct uc_struct *uc, void *user_data);
|
||||||
|
|
||||||
//> X86 registers
|
//> X86 registers
|
||||||
typedef enum uc_x86_reg {
|
typedef enum uc_x86_reg {
|
||||||
UC_X86_REG_INVALID = 0,
|
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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR, UC_X86_REG_FPCW,
|
||||||
UC_X86_REG_FPTAG,
|
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_ENDING // <-- mark the end of the list of registers
|
||||||
} uc_x86_reg;
|
} uc_x86_reg;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_AARCH64_H
|
#ifndef UNICORN_AUTOGEN_AARCH64_H
|
||||||
#define UNICORN_AUTOGEN_AARCH64_H
|
#define UNICORN_AUTOGEN_AARCH64_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_aarch64
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_aarch64
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_aarch64
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_aarch64
|
||||||
#define helper_power_down helper_power_down_aarch64
|
#define helper_power_down helper_power_down_aarch64
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_ARM_H
|
#ifndef UNICORN_AUTOGEN_ARM_H
|
||||||
#define UNICORN_AUTOGEN_ARM_H
|
#define UNICORN_AUTOGEN_ARM_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_arm
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_arm
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_arm
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_arm
|
||||||
#define helper_power_down helper_power_down_arm
|
#define helper_power_down helper_power_down_arm
|
||||||
|
@ -8,6 +8,7 @@ import sys
|
|||||||
|
|
||||||
symbols = (
|
symbols = (
|
||||||
'aarch64_tb_set_jmp_target',
|
'aarch64_tb_set_jmp_target',
|
||||||
|
'ppc_tb_set_jmp_target',
|
||||||
'use_idiv_instructions_rt',
|
'use_idiv_instructions_rt',
|
||||||
'tcg_target_deposit_valid',
|
'tcg_target_deposit_valid',
|
||||||
'helper_power_down',
|
'helper_power_down',
|
||||||
|
@ -126,11 +126,15 @@
|
|||||||
/* Bits present in AT_HWCAP for Sparc. */
|
/* Bits present in AT_HWCAP for Sparc. */
|
||||||
#define HWCAP_SPARC_VIS3 0x00020000
|
#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
|
/* Symbolic values for the entries in the auxiliary table
|
||||||
put on the initial stack */
|
put on the initial stack */
|
||||||
#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
|
#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
|
||||||
#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
|
#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
|
* 68k ELF relocation types
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_M68K_H
|
#ifndef UNICORN_AUTOGEN_M68K_H
|
||||||
#define UNICORN_AUTOGEN_M68K_H
|
#define UNICORN_AUTOGEN_M68K_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_m68k
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_m68k
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_m68k
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_m68k
|
||||||
#define helper_power_down helper_power_down_m68k
|
#define helper_power_down helper_power_down_m68k
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_MIPS_H
|
#ifndef UNICORN_AUTOGEN_MIPS_H
|
||||||
#define UNICORN_AUTOGEN_MIPS_H
|
#define UNICORN_AUTOGEN_MIPS_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_mips
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_mips
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_mips
|
||||||
#define helper_power_down helper_power_down_mips
|
#define helper_power_down helper_power_down_mips
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_MIPS64_H
|
#ifndef UNICORN_AUTOGEN_MIPS64_H
|
||||||
#define UNICORN_AUTOGEN_MIPS64_H
|
#define UNICORN_AUTOGEN_MIPS64_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips64
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_mips64
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_mips64
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_mips64
|
||||||
#define helper_power_down helper_power_down_mips64
|
#define helper_power_down helper_power_down_mips64
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_MIPS64EL_H
|
#ifndef UNICORN_AUTOGEN_MIPS64EL_H
|
||||||
#define UNICORN_AUTOGEN_MIPS64EL_H
|
#define UNICORN_AUTOGEN_MIPS64EL_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips64el
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_mips64el
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_mips64el
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_mips64el
|
||||||
#define helper_power_down helper_power_down_mips64el
|
#define helper_power_down helper_power_down_mips64el
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_MIPSEL_H
|
#ifndef UNICORN_AUTOGEN_MIPSEL_H
|
||||||
#define UNICORN_AUTOGEN_MIPSEL_H
|
#define UNICORN_AUTOGEN_MIPSEL_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mipsel
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_mipsel
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_mipsel
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_mipsel
|
||||||
#define helper_power_down helper_power_down_mipsel
|
#define helper_power_down helper_power_down_mipsel
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_POWERPC_H
|
#ifndef UNICORN_AUTOGEN_POWERPC_H
|
||||||
#define UNICORN_AUTOGEN_POWERPC_H
|
#define UNICORN_AUTOGEN_POWERPC_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_powerpc
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_powerpc
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_powerpc
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_powerpc
|
||||||
#define helper_power_down helper_power_down_powerpc
|
#define helper_power_down helper_power_down_powerpc
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_SPARC_H
|
#ifndef UNICORN_AUTOGEN_SPARC_H
|
||||||
#define UNICORN_AUTOGEN_SPARC_H
|
#define UNICORN_AUTOGEN_SPARC_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_sparc
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_sparc
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_sparc
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_sparc
|
||||||
#define helper_power_down helper_power_down_sparc
|
#define helper_power_down helper_power_down_sparc
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_SPARC64_H
|
#ifndef UNICORN_AUTOGEN_SPARC64_H
|
||||||
#define UNICORN_AUTOGEN_SPARC64_H
|
#define UNICORN_AUTOGEN_SPARC64_H
|
||||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_sparc64
|
#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 use_idiv_instructions_rt use_idiv_instructions_rt_sparc64
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_sparc64
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_sparc64
|
||||||
#define helper_power_down helper_power_down_sparc64
|
#define helper_power_down helper_power_down_sparc64
|
||||||
|
@ -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++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
void *value = vals[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) {
|
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];
|
*(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) {
|
} 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]);
|
*(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 {
|
} else {
|
||||||
switch(regid) {
|
switch(regid) {
|
||||||
default: break;
|
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++) {
|
for (i = 0; i < count; i++) {
|
||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[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) {
|
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;
|
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) {
|
} 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);
|
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 {
|
} else {
|
||||||
switch(regid) {
|
switch(regid) {
|
||||||
default: break;
|
default: break;
|
||||||
|
@ -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];
|
*(float64 *)value = ARM_CPU(uc, mycpu)->env.vfp.regs[regid - UC_ARM_REG_D0];
|
||||||
else {
|
else {
|
||||||
switch(regid) {
|
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:
|
case UC_ARM_REG_CPSR:
|
||||||
*(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env);
|
*(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env);
|
||||||
break;
|
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;
|
ARM_CPU(uc, mycpu)->env.vfp.regs[regid - UC_ARM_REG_D0] = *(float64 *)value;
|
||||||
else {
|
else {
|
||||||
switch(regid) {
|
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:
|
case UC_ARM_REG_CPSR:
|
||||||
cpsr_write(&ARM_CPU(uc, mycpu)->env, *(uint32_t *)value, ~0);
|
cpsr_write(&ARM_CPU(uc, mycpu)->env, *(uint32_t *)value, ~0);
|
||||||
break;
|
break;
|
||||||
|
@ -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);
|
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);
|
const int X86_REGS_STORAGE_SIZE = offsetof(CPUX86State, tlb_table);
|
||||||
|
|
||||||
static void x86_set_pc(struct uc_struct *uc, uint64_t address)
|
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)
|
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||||
{
|
{
|
||||||
CPUState *mycpu = uc->cpu;
|
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)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector;
|
||||||
((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags;
|
((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags;
|
||||||
break;
|
break;
|
||||||
|
case UC_X86_REG_MSR:
|
||||||
|
x86_msr_read(uc, (uc_x86_msr *)value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
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)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector;
|
||||||
((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags;
|
((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags;
|
||||||
break;
|
break;
|
||||||
|
case UC_X86_REG_MSR:
|
||||||
|
x86_msr_read(uc, (uc_x86_msr *)value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#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.selector = (uint16_t)((uc_x86_mmr *)value)->selector;
|
||||||
X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags;
|
X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags;
|
||||||
break;
|
break;
|
||||||
|
case UC_X86_REG_MSR:
|
||||||
|
x86_msr_write(uc, (uc_x86_msr *)value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
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.selector = (uint16_t)((uc_x86_mmr *)value)->selector;
|
||||||
X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags;
|
X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags;
|
||||||
break;
|
break;
|
||||||
|
case UC_X86_REG_MSR:
|
||||||
|
x86_msr_write(uc, (uc_x86_msr *)value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -1257,3 +1316,5 @@ void x86_uc_init(struct uc_struct* uc)
|
|||||||
uc->stop_interrupt = x86_stop_interrupt;
|
uc->stop_interrupt = x86_stop_interrupt;
|
||||||
uc_common_init(uc);
|
uc_common_init(uc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vim: set ts=4 sts=4 sw=4 et: */
|
||||||
|
@ -18,6 +18,12 @@ const int MIPS_REGS_STORAGE_SIZE = offsetof(CPUMIPSState, tlb_table);
|
|||||||
#endif
|
#endif
|
||||||
#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)
|
static uint64_t mips_mem_redirect(uint64_t address)
|
||||||
{
|
{
|
||||||
// kseg0 range masks off high address bit
|
// 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) {
|
switch(regid) {
|
||||||
default: break;
|
default: break;
|
||||||
case UC_MIPS_REG_PC:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,12 +115,12 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
|||||||
unsigned int regid = regs[i];
|
unsigned int regid = regs[i];
|
||||||
const void *value = vals[i];
|
const void *value = vals[i];
|
||||||
if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
|
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 {
|
else {
|
||||||
switch(regid) {
|
switch(regid) {
|
||||||
default: break;
|
default: break;
|
||||||
case UC_MIPS_REG_PC:
|
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
|
// force to quit execution and flush TB
|
||||||
uc->quit_request = true;
|
uc->quit_request = true;
|
||||||
uc_emu_stop(uc);
|
uc_emu_stop(uc);
|
||||||
|
@ -717,8 +717,8 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
|
|||||||
int is_64bit = sizemask & (1 << (i+1)*2);
|
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||||
if (is_64bit) {
|
if (is_64bit) {
|
||||||
TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
|
TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
|
||||||
TCGv_i32 h = tcg_temp_new_i32();
|
TCGv_i32 h = tcg_temp_new_i32(s);
|
||||||
TCGv_i32 l = tcg_temp_new_i32();
|
TCGv_i32 l = tcg_temp_new_i32(s);
|
||||||
tcg_gen_extr_i64_i32(l, h, orig);
|
tcg_gen_extr_i64_i32(l, h, orig);
|
||||||
split_args[real_args++] = GET_TCGV_I32(h);
|
split_args[real_args++] = GET_TCGV_I32(h);
|
||||||
split_args[real_args++] = GET_TCGV_I32(l);
|
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 temp = tcg_temp_new_i64(s);
|
||||||
TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
|
TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
|
||||||
if (is_signed) {
|
if (is_signed) {
|
||||||
tcg_gen_ext32s_i64(temp, orig);
|
tcg_gen_ext32s_i64(s, temp, orig);
|
||||||
} else {
|
} else {
|
||||||
tcg_gen_ext32u_i64(temp, orig);
|
tcg_gen_ext32u_i64(s, temp, orig);
|
||||||
}
|
}
|
||||||
args[i] = GET_TCGV_I64(temp);
|
args[i] = GET_TCGV_I64(temp);
|
||||||
}
|
}
|
||||||
@ -834,8 +834,8 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
|
|||||||
if (is_64bit) {
|
if (is_64bit) {
|
||||||
TCGv_i32 h = MAKE_TCGV_I32(args[real_args++]);
|
TCGv_i32 h = MAKE_TCGV_I32(args[real_args++]);
|
||||||
TCGv_i32 l = MAKE_TCGV_I32(args[real_args++]);
|
TCGv_i32 l = MAKE_TCGV_I32(args[real_args++]);
|
||||||
tcg_temp_free_i32(h);
|
tcg_temp_free_i32(s, h);
|
||||||
tcg_temp_free_i32(l);
|
tcg_temp_free_i32(s, l);
|
||||||
} else {
|
} else {
|
||||||
real_args++;
|
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
|
Note that describing these as TCGv_i64 eliminates an unnecessary
|
||||||
zero-extension that tcg_gen_concat_i32_i64 would create. */
|
zero-extension that tcg_gen_concat_i32_i64 would create. */
|
||||||
tcg_gen_concat32_i64(MAKE_TCGV_I64(ret), retl, reth);
|
tcg_gen_concat32_i64(MAKE_TCGV_I64(ret), retl, reth);
|
||||||
tcg_temp_free_i64(retl);
|
tcg_temp_free_i64(s, retl);
|
||||||
tcg_temp_free_i64(reth);
|
tcg_temp_free_i64(s, reth);
|
||||||
}
|
}
|
||||||
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
|
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
|
||||||
for (i = 0; i < nargs; ++i) {
|
for (i = 0; i < nargs; ++i) {
|
||||||
int is_64bit = sizemask & (1 << (i+1)*2);
|
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||||
if (!is_64bit) {
|
if (!is_64bit) {
|
||||||
TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
|
TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
|
||||||
tcg_temp_free_i64(temp);
|
tcg_temp_free_i64(s, temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* TCG_TARGET_EXTEND_ARGS */
|
#endif /* TCG_TARGET_EXTEND_ARGS */
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef UNICORN_AUTOGEN_X86_64_H
|
#ifndef UNICORN_AUTOGEN_X86_64_H
|
||||||
#define 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 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 use_idiv_instructions_rt use_idiv_instructions_rt_x86_64
|
||||||
#define tcg_target_deposit_valid tcg_target_deposit_valid_x86_64
|
#define tcg_target_deposit_valid tcg_target_deposit_valid_x86_64
|
||||||
#define helper_power_down helper_power_down_x86_64
|
#define helper_power_down helper_power_down_x86_64
|
||||||
|
@ -42,3 +42,18 @@ if test -e $DIR/sample_m68k; then
|
|||||||
echo "=========================="
|
echo "=========================="
|
||||||
$DIR/sample_m68k
|
$DIR/sample_m68k
|
||||||
fi
|
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
|
||||||
|
1
tests/regress/.gitignore
vendored
1
tests/regress/.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
!*.c
|
!*.c
|
||||||
|
|
||||||
|
arm_enable_vfp
|
||||||
map_crash
|
map_crash
|
||||||
sigill
|
sigill
|
||||||
sigill2
|
sigill2
|
||||||
|
@ -23,26 +23,32 @@ typedef uint64_t puint;
|
|||||||
uint32_t realEflags()
|
uint32_t realEflags()
|
||||||
{
|
{
|
||||||
puint val = 0;
|
puint val = 0;
|
||||||
puint i = 0xFFFFFEFF; //attempt to set ALL bits except trap flag.
|
|
||||||
|
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
|
puint i = 0xFFFFFEFF; //attempt to set ALL bits except trap flag.
|
||||||
|
|
||||||
__asm__("pushf\n\t"
|
__asm__("pushf\n\t"
|
||||||
"push %0\n\t"
|
"push %0\n\t"
|
||||||
"popf\n\t"
|
"popf\n\t"
|
||||||
"pushf\n\t"
|
"pushf\n\t"
|
||||||
"pop %0\n\t"
|
"pop %0\n\t"
|
||||||
"popf"
|
"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"
|
__asm__("pushfq\n\t"
|
||||||
"pushq %0\n\t"
|
"pushq %0\n\t"
|
||||||
"popfq\n\t"
|
"popfq\n\t"
|
||||||
"pushfq\n\t"
|
"pushfq\n\t"
|
||||||
"popq %0\n\t"
|
"popq %0\n\t"
|
||||||
"popfq"
|
"popfq"
|
||||||
#endif
|
|
||||||
: "=r"(val)
|
: "=r"(val)
|
||||||
: "r"(i)
|
: "r"(i)
|
||||||
: "%0");
|
: "%0");
|
||||||
|
#endif
|
||||||
|
|
||||||
printf("Real system eflags: 0x%08"PRIX3264"\n", val);
|
printf("Real system eflags: 0x%08"PRIX3264"\n", val);
|
||||||
|
|
||||||
@ -51,7 +57,7 @@ uint32_t realEflags()
|
|||||||
|
|
||||||
static void VM_exec()
|
static void VM_exec()
|
||||||
{
|
{
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
uc_engine *uc;
|
uc_engine *uc;
|
||||||
uc_err err;
|
uc_err err;
|
||||||
unsigned int r_eax, eflags, r_esp, realflags = 0;
|
unsigned int r_eax, eflags, r_esp, realflags = 0;
|
||||||
@ -110,6 +116,7 @@ static void VM_exec()
|
|||||||
realflags = realEflags();
|
realflags = realEflags();
|
||||||
|
|
||||||
assert(r_eax == realflags);
|
assert(r_eax == realflags);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
2
uc.c
2
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);
|
return uc_reg_read_batch(uc, ®id, &value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value)
|
||||||
{
|
{
|
||||||
return uc_reg_write_batch(uc, ®id, (void *const *)&value, 1);
|
return uc_reg_write_batch(uc, ®id, (void *const *)&value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// check if a memory area is mapped
|
// check if a memory area is mapped
|
||||||
// this is complicated because an area can overlap adjacent blocks
|
// this is complicated because an area can overlap adjacent blocks
|
||||||
static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size)
|
static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size)
|
||||||
|
Reference in New Issue
Block a user