Updates to Haskell bindings (#667)
* [haskell] Added uc_context_* support
As per issue #662
* [haskell] Updated bindings for commit 4083b87032
Updated for introduction of UC_HOOK_MEM_READ_AFTER.
* [haskell] Style fixes
This commit is contained in:
parent
4d5738eeb5
commit
19028f41f6
|
@ -9,41 +9,47 @@ framework based on QEMU.
|
||||||
|
|
||||||
Further information is available at <http://www.unicorn-engine.org>.
|
Further information is available at <http://www.unicorn-engine.org>.
|
||||||
-}
|
-}
|
||||||
module Unicorn (
|
module Unicorn
|
||||||
-- * Emulator control
|
( -- * Emulator control
|
||||||
Emulator,
|
Emulator
|
||||||
Engine,
|
, Engine
|
||||||
Architecture(..),
|
, Architecture(..)
|
||||||
Mode(..),
|
, Mode(..)
|
||||||
QueryType(..),
|
, QueryType(..)
|
||||||
runEmulator,
|
, runEmulator
|
||||||
open,
|
, open
|
||||||
query,
|
, query
|
||||||
start,
|
, start
|
||||||
stop,
|
, stop
|
||||||
|
|
||||||
-- * Register operations
|
-- * Register operations
|
||||||
regWrite,
|
, regWrite
|
||||||
regRead,
|
, regRead
|
||||||
|
|
||||||
-- * Memory operations
|
-- * Memory operations
|
||||||
MemoryPermission(..),
|
, MemoryPermission(..)
|
||||||
MemoryRegion(..),
|
, MemoryRegion(..)
|
||||||
memWrite,
|
, memWrite
|
||||||
memRead,
|
, memRead
|
||||||
memMap,
|
, memMap
|
||||||
memUnmap,
|
, memUnmap
|
||||||
memProtect,
|
, memProtect
|
||||||
memRegions,
|
, memRegions
|
||||||
|
|
||||||
-- * Error handling
|
-- * Context operations
|
||||||
Error(..),
|
, Context
|
||||||
errno,
|
, contextAlloc
|
||||||
strerror,
|
, contextSave
|
||||||
|
, contextRestore
|
||||||
|
|
||||||
-- * Misc.
|
-- * Error handling
|
||||||
version,
|
, Error(..)
|
||||||
) where
|
, errno
|
||||||
|
, strerror
|
||||||
|
|
||||||
|
-- * Misc.
|
||||||
|
, version
|
||||||
|
) where
|
||||||
|
|
||||||
import Control.Monad (liftM)
|
import Control.Monad (liftM)
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
|
@ -132,8 +138,8 @@ 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 ID 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
|
||||||
|
@ -147,8 +153,8 @@ regWrite uc regId value = do
|
||||||
left err
|
left err
|
||||||
|
|
||||||
-- | 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 ID 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
|
||||||
|
@ -259,6 +265,46 @@ memRegions uc = do
|
||||||
else
|
else
|
||||||
left err
|
left err
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Context operations
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- | Allocate a region that can be used to perform quick save/rollback of the
|
||||||
|
-- CPU context, which includes registers and some internal metadata. Contexts
|
||||||
|
-- may not be shared across engine instances with differing architectures or
|
||||||
|
-- modes.
|
||||||
|
contextAlloc :: Engine -- ^ 'Unicon' engine handle
|
||||||
|
-> Emulator Context -- ^ A CPU context
|
||||||
|
contextAlloc uc = do
|
||||||
|
(err, contextPtr) <- lift $ ucContextAlloc uc
|
||||||
|
if err == ErrOk then
|
||||||
|
-- Return a CPU context if ucContextAlloc completed successfully
|
||||||
|
lift $ mkContext contextPtr
|
||||||
|
else
|
||||||
|
left err
|
||||||
|
|
||||||
|
-- | Save a copy of the internal CPU context.
|
||||||
|
contextSave :: Engine -- ^ 'Unicorn' engine handle
|
||||||
|
-> Context -- ^ A CPU context
|
||||||
|
-> Emulator () -- ^ An error on failure
|
||||||
|
contextSave uc context = do
|
||||||
|
err <- lift $ ucContextSave uc context
|
||||||
|
if err == ErrOk then
|
||||||
|
right ()
|
||||||
|
else
|
||||||
|
left err
|
||||||
|
|
||||||
|
-- | Restore the current CPU context from a saved copy.
|
||||||
|
contextRestore :: Engine -- ^ 'Unicorn' engine handle
|
||||||
|
-> Context -- ^ A CPU context
|
||||||
|
-> Emulator () -- ^ An error on failure
|
||||||
|
contextRestore uc context = do
|
||||||
|
err <- lift $ ucContextRestore uc context
|
||||||
|
if err == ErrOk then
|
||||||
|
right ()
|
||||||
|
else
|
||||||
|
left err
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Misc.
|
-- Misc.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
|
@ -8,22 +8,25 @@ License : GPL-2
|
||||||
|
|
||||||
Definitions for the ARM architecture.
|
Definitions for the ARM architecture.
|
||||||
-}
|
-}
|
||||||
module Unicorn.CPU.Arm (
|
module Unicorn.CPU.Arm
|
||||||
Register(..),
|
(
|
||||||
) where
|
Register(..)
|
||||||
|
) where
|
||||||
|
|
||||||
import Unicorn.Internal.Core (Reg)
|
import Unicorn.Internal.Core (Reg)
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/arm.h>
|
#include <unicorn/arm.h>
|
||||||
|
|
||||||
-- | ARM registers.
|
-- | ARM registers.
|
||||||
{# enum uc_arm_reg as Register
|
{# enum uc_arm_reg as Register
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_ARM_REG_INVALID,
|
omit ( UC_ARM_REG_INVALID
|
||||||
UC_ARM_REG_ENDING)
|
, UC_ARM_REG_ENDING
|
||||||
with prefix="UC_ARM_REG_"
|
)
|
||||||
deriving (Show, Eq, Bounded) #}
|
with prefix = "UC_ARM_REG_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
instance Reg Register
|
instance Reg Register
|
||||||
|
|
|
@ -8,22 +8,25 @@ License : GPL-2
|
||||||
|
|
||||||
Definitions for the ARM64 (ARMv8) architecture.
|
Definitions for the ARM64 (ARMv8) architecture.
|
||||||
-}
|
-}
|
||||||
module Unicorn.CPU.Arm64 (
|
module Unicorn.CPU.Arm64
|
||||||
Register(..),
|
(
|
||||||
) where
|
Register(..)
|
||||||
|
) where
|
||||||
|
|
||||||
import Unicorn.Internal.Core (Reg)
|
import Unicorn.Internal.Core (Reg)
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/arm64.h>
|
#include <unicorn/arm64.h>
|
||||||
|
|
||||||
-- | ARM64 registers.
|
-- | ARM64 registers.
|
||||||
{# enum uc_arm64_reg as Register
|
{# enum uc_arm64_reg as Register
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_ARM64_REG_INVALID,
|
omit ( UC_ARM64_REG_INVALID
|
||||||
UC_ARM64_REG_ENDING)
|
, UC_ARM64_REG_ENDING
|
||||||
with prefix="UC_ARM64_REG_"
|
)
|
||||||
deriving (Show, Eq, Bounded) #}
|
with prefix = "UC_ARM64_REG_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
instance Reg Register
|
instance Reg Register
|
||||||
|
|
|
@ -8,22 +8,25 @@ License : GPL-2
|
||||||
|
|
||||||
Definitions for the MK68K architecture.
|
Definitions for the MK68K architecture.
|
||||||
-}
|
-}
|
||||||
module Unicorn.CPU.M68k (
|
module Unicorn.CPU.M68k
|
||||||
Register(..),
|
(
|
||||||
) where
|
Register(..)
|
||||||
|
) where
|
||||||
|
|
||||||
import Unicorn.Internal.Core (Reg)
|
import Unicorn.Internal.Core (Reg)
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/m68k.h>
|
#include <unicorn/m68k.h>
|
||||||
|
|
||||||
-- | M68K registers.
|
-- | M68K registers.
|
||||||
{# enum uc_m68k_reg as Register
|
{# enum uc_m68k_reg as Register
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_M68K_REG_INVALID,
|
omit ( UC_M68K_REG_INVALID
|
||||||
UC_M68K_REG_ENDING)
|
, UC_M68K_REG_ENDING
|
||||||
with prefix="UC_M68K_REG_"
|
)
|
||||||
deriving (Show, Eq, Bounded) #}
|
with prefix = "UC_M68K_REG_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
instance Reg Register
|
instance Reg Register
|
||||||
|
|
|
@ -8,54 +8,58 @@ License : GPL-2
|
||||||
|
|
||||||
Definitions for the MIPS architecture.
|
Definitions for the MIPS architecture.
|
||||||
-}
|
-}
|
||||||
module Unicorn.CPU.Mips (
|
module Unicorn.CPU.Mips
|
||||||
Register(..),
|
(
|
||||||
) where
|
Register(..)
|
||||||
|
) where
|
||||||
|
|
||||||
import Unicorn.Internal.Core (Reg)
|
import Unicorn.Internal.Core (Reg)
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/mips.h>
|
#include <unicorn/mips.h>
|
||||||
|
|
||||||
-- | MIPS registers.
|
-- | MIPS registers.
|
||||||
{# enum UC_MIPS_REG as Register
|
{# enum UC_MIPS_REG as Register
|
||||||
{underscoreToCase,
|
{ underscoreToCase
|
||||||
UC_MIPS_REG_0 as Reg0,
|
, UC_MIPS_REG_0 as Reg0g
|
||||||
UC_MIPS_REG_1 as Reg1,
|
, UC_MIPS_REG_1 as Reg1g
|
||||||
UC_MIPS_REG_2 as Reg2,
|
, UC_MIPS_REG_2 as Reg2g
|
||||||
UC_MIPS_REG_3 as Reg3,
|
, UC_MIPS_REG_3 as Reg3g
|
||||||
UC_MIPS_REG_4 as Reg4,
|
, UC_MIPS_REG_4 as Reg4g
|
||||||
UC_MIPS_REG_5 as Reg5,
|
, UC_MIPS_REG_5 as Reg5g
|
||||||
UC_MIPS_REG_6 as Reg6,
|
, UC_MIPS_REG_6 as Reg6g
|
||||||
UC_MIPS_REG_7 as Reg7,
|
, UC_MIPS_REG_7 as Reg7g
|
||||||
UC_MIPS_REG_8 as Reg8,
|
, UC_MIPS_REG_8 as Reg8g
|
||||||
UC_MIPS_REG_9 as Reg9,
|
, UC_MIPS_REG_9 as Reg9g
|
||||||
UC_MIPS_REG_10 as Reg10,
|
, UC_MIPS_REG_10 as Reg10g
|
||||||
UC_MIPS_REG_11 as Reg11,
|
, UC_MIPS_REG_11 as Reg11g
|
||||||
UC_MIPS_REG_12 as Reg12,
|
, UC_MIPS_REG_12 as Reg12g
|
||||||
UC_MIPS_REG_13 as Reg13,
|
, UC_MIPS_REG_13 as Reg13g
|
||||||
UC_MIPS_REG_14 as Reg14,
|
, UC_MIPS_REG_14 as Reg14g
|
||||||
UC_MIPS_REG_15 as Reg15,
|
, UC_MIPS_REG_15 as Reg15g
|
||||||
UC_MIPS_REG_16 as Reg16,
|
, UC_MIPS_REG_16 as Reg16g
|
||||||
UC_MIPS_REG_17 as Reg17,
|
, UC_MIPS_REG_17 as Reg17g
|
||||||
UC_MIPS_REG_18 as Reg18,
|
, UC_MIPS_REG_18 as Reg18g
|
||||||
UC_MIPS_REG_19 as Reg19,
|
, UC_MIPS_REG_19 as Reg19g
|
||||||
UC_MIPS_REG_20 as Reg20,
|
, UC_MIPS_REG_20 as Reg20g
|
||||||
UC_MIPS_REG_21 as Reg21,
|
, UC_MIPS_REG_21 as Reg21g
|
||||||
UC_MIPS_REG_22 as Reg22,
|
, UC_MIPS_REG_22 as Reg22g
|
||||||
UC_MIPS_REG_23 as Reg23,
|
, UC_MIPS_REG_23 as Reg23g
|
||||||
UC_MIPS_REG_24 as Reg24,
|
, UC_MIPS_REG_24 as Reg24g
|
||||||
UC_MIPS_REG_25 as Reg25,
|
, UC_MIPS_REG_25 as Reg25g
|
||||||
UC_MIPS_REG_26 as Reg26,
|
, UC_MIPS_REG_26 as Reg26g
|
||||||
UC_MIPS_REG_27 as Reg27,
|
, UC_MIPS_REG_27 as Reg27g
|
||||||
UC_MIPS_REG_28 as Reg28,
|
, UC_MIPS_REG_28 as Reg28g
|
||||||
UC_MIPS_REG_29 as Reg29,
|
, UC_MIPS_REG_29 as Reg29g
|
||||||
UC_MIPS_REG_30 as Reg30,
|
, UC_MIPS_REG_30 as Reg30g
|
||||||
UC_MIPS_REG_31 as Reg31}
|
, UC_MIPS_REG_31 as Reg31
|
||||||
omit (UC_MIPS_REG_INVALID,
|
}
|
||||||
UC_MIPS_REG_ENDING)
|
omit ( UC_MIPS_REG_INVALID
|
||||||
with prefix="UC_MIPS_REG_"
|
, UC_MIPS_REG_ENDING
|
||||||
deriving (Show, Eq, Bounded) #}
|
)
|
||||||
|
with prefix = "UC_MIPS_REG_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
instance Reg Register
|
instance Reg Register
|
||||||
|
|
|
@ -8,22 +8,25 @@ License : GPL-2
|
||||||
|
|
||||||
Definitions for the SPARC architecture.
|
Definitions for the SPARC architecture.
|
||||||
-}
|
-}
|
||||||
module Unicorn.CPU.Sparc (
|
module Unicorn.CPU.Sparc
|
||||||
Register(..),
|
(
|
||||||
) where
|
Register(..)
|
||||||
|
) where
|
||||||
|
|
||||||
import Unicorn.Internal.Core (Reg)
|
import Unicorn.Internal.Core (Reg)
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/sparc.h>
|
#include <unicorn/sparc.h>
|
||||||
|
|
||||||
-- | SPARC registers.
|
-- | SPARC registers.
|
||||||
{# enum uc_sparc_reg as Register
|
{# enum uc_sparc_reg as Register
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_SPARC_REG_INVALID,
|
omit (UC_SPARC_REG_INVALID
|
||||||
UC_SPARC_REG_ENDING)
|
, UC_SPARC_REG_ENDING
|
||||||
with prefix="UC_SPARC_REG_"
|
)
|
||||||
deriving (Show, Eq, Bounded) #}
|
with prefix = "UC_SPARC_REG_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
instance Reg Register
|
instance Reg Register
|
||||||
|
|
|
@ -8,11 +8,12 @@ License : GPL-2
|
||||||
|
|
||||||
Definitions for the X86 architecture.
|
Definitions for the X86 architecture.
|
||||||
-}
|
-}
|
||||||
module Unicorn.CPU.X86 (
|
module Unicorn.CPU.X86
|
||||||
Mmr(..),
|
(
|
||||||
Register(..),
|
Mmr(..)
|
||||||
Instruction(..),
|
, Register(..)
|
||||||
) where
|
, Instruction(..)
|
||||||
|
) where
|
||||||
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Data.Word
|
import Data.Word
|
||||||
|
@ -20,18 +21,18 @@ import Foreign
|
||||||
|
|
||||||
import Unicorn.Internal.Core (Reg)
|
import Unicorn.Internal.Core (Reg)
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/x86.h>
|
#include <unicorn/x86.h>
|
||||||
|
|
||||||
-- | Memory-managemen Register for instructions IDTR, GDTR, LDTR, TR.
|
-- | Memory-managemen Register for instructions IDTR, GDTR, LDTR, TR.
|
||||||
-- Borrow from SegmentCache in qemu/target-i386/cpu.h
|
-- Borrow from SegmentCache in qemu/target-i386/cpu.h
|
||||||
data Mmr = Mmr {
|
data Mmr = Mmr
|
||||||
mmrSelector :: Word16, -- ^ Not used by GDTR and IDTR
|
{ mmrSelector :: Word16 -- ^ Not used by GDTR and IDTR
|
||||||
mmrBase :: Word64, -- ^ Handle 32 or 64 bit CPUs
|
, mmrBase :: Word64 -- ^ Handle 32 or 64 bit CPUs
|
||||||
mmrLimit :: Word32,
|
, mmrLimit :: Word32
|
||||||
mmrFlags :: Word32 -- ^ Not used by GDTR and IDTR
|
, mmrFlags :: Word32 -- ^ Not used by GDTR and IDTR
|
||||||
}
|
}
|
||||||
|
|
||||||
instance Storable Mmr where
|
instance Storable Mmr where
|
||||||
sizeOf _ = {# sizeof uc_x86_mmr #}
|
sizeOf _ = {# sizeof uc_x86_mmr #}
|
||||||
|
@ -48,18 +49,22 @@ instance Storable Mmr where
|
||||||
|
|
||||||
-- | X86 registers.
|
-- | X86 registers.
|
||||||
{# enum uc_x86_reg as Register
|
{# enum uc_x86_reg as Register
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_X86_REG_INVALID,
|
omit ( UC_X86_REG_INVALID
|
||||||
UC_X86_REG_ENDING)
|
, UC_X86_REG_ENDING
|
||||||
with prefix="UC_X86_REG_"
|
)
|
||||||
deriving (Show, Eq, Bounded) #}
|
with prefix = "UC_X86_REG_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
instance Reg Register
|
instance Reg Register
|
||||||
|
|
||||||
-- | X86 instructions.
|
-- | X86 instructions.
|
||||||
{# enum uc_x86_insn as Instruction
|
{# enum uc_x86_insn as Instruction
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_X86_INS_INVALID,
|
omit ( UC_X86_INS_INVALID
|
||||||
UC_X86_INS_ENDING)
|
, UC_X86_INS_ENDING
|
||||||
with prefix="UC_X86_INS_"
|
)
|
||||||
deriving (Show, Eq, Bounded) #}
|
with prefix = "UC_X86_INS_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
|
@ -6,36 +6,36 @@ License : GPL-2
|
||||||
|
|
||||||
Insert hook points into the Unicorn emulator engine.
|
Insert hook points into the Unicorn emulator engine.
|
||||||
-}
|
-}
|
||||||
module Unicorn.Hook (
|
module Unicorn.Hook
|
||||||
-- * Hook types
|
( -- * Hook types
|
||||||
Hook,
|
Hook
|
||||||
MemoryHookType(..),
|
, MemoryHookType(..)
|
||||||
MemoryEventHookType(..),
|
, MemoryEventHookType(..)
|
||||||
MemoryAccess(..),
|
, MemoryAccess(..)
|
||||||
|
|
||||||
-- * Hook callbacks
|
-- * Hook callbacks
|
||||||
CodeHook,
|
, CodeHook
|
||||||
InterruptHook,
|
, InterruptHook
|
||||||
BlockHook,
|
, BlockHook
|
||||||
InHook,
|
, InHook
|
||||||
OutHook,
|
, OutHook
|
||||||
SyscallHook,
|
, SyscallHook
|
||||||
MemoryHook,
|
, MemoryHook
|
||||||
MemoryReadHook,
|
, MemoryReadHook
|
||||||
MemoryWriteHook,
|
, MemoryWriteHook
|
||||||
MemoryEventHook,
|
, MemoryEventHook
|
||||||
|
|
||||||
-- * Hook callback management
|
-- * Hook callback management
|
||||||
codeHookAdd,
|
, codeHookAdd
|
||||||
interruptHookAdd,
|
, interruptHookAdd
|
||||||
blockHookAdd,
|
, blockHookAdd
|
||||||
inHookAdd,
|
, inHookAdd
|
||||||
outHookAdd,
|
, outHookAdd
|
||||||
syscallHookAdd,
|
, syscallHookAdd
|
||||||
memoryHookAdd,
|
, memoryHookAdd
|
||||||
memoryEventHookAdd,
|
, memoryEventHookAdd
|
||||||
hookDel,
|
, hookDel
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Control.Monad.Trans.Class
|
import Control.Monad.Trans.Class
|
||||||
|
@ -213,7 +213,8 @@ hookDel uc hook = do
|
||||||
-- Takes the tuple returned by `ucHookAdd`, an IO (Error, Hook), and
|
-- Takes the tuple returned by `ucHookAdd`, an IO (Error, Hook), and
|
||||||
-- returns either a `Right Hook` if no error occurred or a `Left Error` if an
|
-- returns either a `Right Hook` if no error occurred or a `Left Error` if an
|
||||||
-- error occurred
|
-- error occurred
|
||||||
getResult :: IO (Error, Hook) -> IO (Either Error Hook)
|
getResult :: IO (Error, Hook)
|
||||||
|
-> IO (Either Error Hook)
|
||||||
getResult =
|
getResult =
|
||||||
liftM (uncurry checkResult)
|
liftM (uncurry checkResult)
|
||||||
where checkResult err hook =
|
where checkResult err hook =
|
||||||
|
|
|
@ -17,31 +17,34 @@ import Control.Monad
|
||||||
import Control.Monad.Trans.Either (EitherT)
|
import Control.Monad.Trans.Either (EitherT)
|
||||||
import Foreign
|
import Foreign
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
#include "unicorn_wrapper.h"
|
#include "unicorn_wrapper.h"
|
||||||
|
|
||||||
-- | The Unicorn engine.
|
-- | The Unicorn engine.
|
||||||
{# pointer *uc_engine as Engine
|
{# pointer *uc_engine as Engine
|
||||||
foreign finalizer uc_close_wrapper as close
|
foreign finalizer uc_close_wrapper as close
|
||||||
newtype #}
|
newtype
|
||||||
|
#}
|
||||||
|
|
||||||
-- | A pointer to a Unicorn engine.
|
-- | A pointer to a Unicorn engine.
|
||||||
{# pointer *uc_engine as EnginePtr -> Engine #}
|
{# pointer *uc_engine as EnginePtr -> Engine #}
|
||||||
|
|
||||||
-- | Make a new Unicorn engine out of an engine pointer. The returned Unicorn
|
-- | Make a new Unicorn engine out of an engine pointer. The returned Unicorn
|
||||||
-- engine will automatically call 'uc_close_wrapper' when it goes out of scope.
|
-- engine will automatically call 'uc_close_wrapper' when it goes out of scope.
|
||||||
mkEngine :: EnginePtr -> IO Engine
|
mkEngine :: EnginePtr
|
||||||
|
-> IO Engine
|
||||||
mkEngine ptr =
|
mkEngine ptr =
|
||||||
liftM Engine (newForeignPtr close ptr)
|
liftM Engine (newForeignPtr close ptr)
|
||||||
|
|
||||||
-- | Errors encountered by the Unicorn API. These values are returned by
|
-- | Errors encountered by the Unicorn API. These values are returned by
|
||||||
-- 'errno'.
|
-- 'errno'.
|
||||||
{# enum uc_err as Error
|
{# enum uc_err as Error
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
with prefix="UC_"
|
with prefix = "UC_"
|
||||||
deriving (Show, Eq, Bounded) #}
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
-- | The emulator runs in the IO monad and allows for the handling of errors
|
-- | The emulator runs in the IO monad and allows for the handling of errors
|
||||||
-- "under the hood".
|
-- "under the hood".
|
||||||
|
|
|
@ -11,54 +11,54 @@ Low-level bindings for inserting hook points into the Unicorn emulator engine.
|
||||||
This module should not be directly imported; it is only exposed because of the
|
This module should not be directly imported; it is only exposed because of the
|
||||||
way cabal handles ordering of chs files.
|
way cabal handles ordering of chs files.
|
||||||
-}
|
-}
|
||||||
module Unicorn.Internal.Hook (
|
module Unicorn.Internal.Hook
|
||||||
-- * Types
|
( -- * Types
|
||||||
Hook,
|
Hook
|
||||||
HookType(..),
|
, HookType(..)
|
||||||
MemoryHookType(..),
|
, MemoryHookType(..)
|
||||||
MemoryEventHookType(..),
|
, MemoryEventHookType(..)
|
||||||
MemoryAccess(..),
|
, MemoryAccess(..)
|
||||||
|
|
||||||
-- * Hook callback bindings
|
-- * Hook callback bindings
|
||||||
CodeHook,
|
, CodeHook
|
||||||
InterruptHook,
|
, InterruptHook
|
||||||
BlockHook,
|
, BlockHook
|
||||||
InHook,
|
, InHook
|
||||||
OutHook,
|
, OutHook
|
||||||
SyscallHook,
|
, SyscallHook
|
||||||
MemoryHook,
|
, MemoryHook
|
||||||
MemoryReadHook,
|
, MemoryReadHook
|
||||||
MemoryWriteHook,
|
, MemoryWriteHook
|
||||||
MemoryEventHook,
|
, MemoryEventHook
|
||||||
|
|
||||||
-- * Hook marshalling
|
-- * Hook marshallin
|
||||||
marshalCodeHook,
|
, marshalCodeHook
|
||||||
marshalInterruptHook,
|
, marshalInterruptHook
|
||||||
marshalBlockHook,
|
, marshalBlockHook
|
||||||
marshalInHook,
|
, marshalInHook
|
||||||
marshalOutHook,
|
, marshalOutHook
|
||||||
marshalSyscallHook,
|
, marshalSyscallHook
|
||||||
marshalMemoryHook,
|
, marshalMemoryHook
|
||||||
marshalMemoryReadHook,
|
, marshalMemoryReadHook
|
||||||
marshalMemoryWriteHook,
|
, marshalMemoryWriteHook
|
||||||
marshalMemoryEventHook,
|
, marshalMemoryEventHook
|
||||||
|
|
||||||
-- * Hook registration and deletion bindings
|
-- * Hook registration and deletion bindings
|
||||||
ucHookAdd,
|
, ucHookAdd
|
||||||
ucInsnHookAdd,
|
, ucInsnHookAdd
|
||||||
ucHookDel,
|
, ucHookDel
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Foreign
|
import Foreign
|
||||||
|
|
||||||
import Unicorn.Internal.Util
|
import Unicorn.Internal.Util
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
|
||||||
|
|
||||||
{# import Unicorn.Internal.Core #}
|
{# import Unicorn.Internal.Core #}
|
||||||
{# import Unicorn.CPU.X86 #}
|
{# import Unicorn.CPU.X86 #}
|
||||||
|
|
||||||
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
#include "unicorn_wrapper.h"
|
#include "unicorn_wrapper.h"
|
||||||
|
|
||||||
|
@ -79,7 +79,8 @@ import Unicorn.Internal.Util
|
||||||
foreign import ccall "&uc_close_dummy"
|
foreign import ccall "&uc_close_dummy"
|
||||||
closeDummy :: FunPtr (EnginePtr -> IO ())
|
closeDummy :: FunPtr (EnginePtr -> IO ())
|
||||||
|
|
||||||
mkEngineNC :: EnginePtr -> IO Engine
|
mkEngineNC :: EnginePtr
|
||||||
|
-> IO Engine
|
||||||
mkEngineNC ptr =
|
mkEngineNC ptr =
|
||||||
liftM Engine (newForeignPtr closeDummy ptr)
|
liftM Engine (newForeignPtr closeDummy ptr)
|
||||||
|
|
||||||
|
@ -92,47 +93,55 @@ type Hook = {# type uc_hook #}
|
||||||
-- Note that the both valid and invalid memory access hooks are omitted from
|
-- Note that the both valid and invalid memory access hooks are omitted from
|
||||||
-- this enum (and are exposed to the user).
|
-- this enum (and are exposed to the user).
|
||||||
{# enum uc_hook_type as HookType
|
{# enum uc_hook_type as HookType
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_HOOK_MEM_READ_UNMAPPED,
|
omit ( UC_HOOK_MEM_READ_UNMAPPED
|
||||||
UC_HOOK_MEM_WRITE_UNMAPPED,
|
, UC_HOOK_MEM_WRITE_UNMAPPED
|
||||||
UC_HOOK_MEM_FETCH_UNMAPPED,
|
, UC_HOOK_MEM_FETCH_UNMAPPED
|
||||||
UC_HOOK_MEM_READ_PROT,
|
, UC_HOOK_MEM_READ_PROT
|
||||||
UC_HOOK_MEM_WRITE_PROT,
|
, UC_HOOK_MEM_WRITE_PROT
|
||||||
UC_HOOK_MEM_FETCH_PROT,
|
, UC_HOOK_MEM_FETCH_PROT
|
||||||
UC_HOOK_MEM_READ,
|
, UC_HOOK_MEM_READ
|
||||||
UC_HOOK_MEM_WRITE,
|
, UC_HOOK_MEM_WRITE
|
||||||
UC_HOOK_MEM_FETCH)
|
, UC_HOOK_MEM_FETCH
|
||||||
with prefix="UC_"
|
, UC_HOOK_MEM_READ_AFTER
|
||||||
deriving (Show, Eq, Bounded) #}
|
)
|
||||||
|
with prefix = "UC_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
-- | Memory hook types (for valid memory accesses).
|
-- | Memory hook types (for valid memory accesses).
|
||||||
{# enum uc_hook_type as MemoryHookType
|
{# enum uc_hook_type as MemoryHookType
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_HOOK_INTR,
|
omit ( UC_HOOK_INTR
|
||||||
UC_HOOK_INSN,
|
, UC_HOOK_INSN
|
||||||
UC_HOOK_CODE,
|
, UC_HOOK_CODE
|
||||||
UC_HOOK_BLOCK,
|
, UC_HOOK_BLOCK
|
||||||
UC_HOOK_MEM_READ_UNMAPPED,
|
, UC_HOOK_MEM_READ_UNMAPPED
|
||||||
UC_HOOK_MEM_WRITE_UNMAPPED,
|
, UC_HOOK_MEM_WRITE_UNMAPPED
|
||||||
UC_HOOK_MEM_FETCH_UNMAPPED,
|
, UC_HOOK_MEM_FETCH_UNMAPPED
|
||||||
UC_HOOK_MEM_READ_PROT,
|
, UC_HOOK_MEM_READ_PROT
|
||||||
UC_HOOK_MEM_WRITE_PROT,
|
, UC_HOOK_MEM_WRITE_PROT
|
||||||
UC_HOOK_MEM_FETCH_PROT)
|
, UC_HOOK_MEM_FETCH_PROT
|
||||||
with prefix="UC_"
|
)
|
||||||
deriving (Show, Eq, Bounded) #}
|
with prefix = "UC_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
-- | Memory event hook types (for invalid memory accesses).
|
-- | Memory event hook types (for invalid memory accesses).
|
||||||
{# enum uc_hook_type as MemoryEventHookType
|
{# enum uc_hook_type as MemoryEventHookType
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
omit (UC_HOOK_INTR,
|
omit ( UC_HOOK_INTR
|
||||||
UC_HOOK_INSN,
|
, UC_HOOK_INSN
|
||||||
UC_HOOK_CODE,
|
, UC_HOOK_CODE
|
||||||
UC_HOOK_BLOCK,
|
, UC_HOOK_BLOCK
|
||||||
UC_HOOK_MEM_READ,
|
, UC_HOOK_MEM_READ
|
||||||
UC_HOOK_MEM_WRITE,
|
, UC_HOOK_MEM_WRITE
|
||||||
UC_HOOK_MEM_FETCH)
|
, UC_HOOK_MEM_FETCH
|
||||||
with prefix="UC_"
|
, UC_HOOK_MEM_READ_AFTER
|
||||||
deriving (Show, Eq, Bounded) #}
|
)
|
||||||
|
with prefix = "UC_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
-- | Unify the hook types with a type class
|
-- | Unify the hook types with a type class
|
||||||
class Enum a => HookTypeC a
|
class Enum a => HookTypeC a
|
||||||
|
@ -143,9 +152,10 @@ instance HookTypeC MemoryEventHookType
|
||||||
|
|
||||||
-- | Memory access.
|
-- | Memory access.
|
||||||
{# enum uc_mem_type as MemoryAccess
|
{# enum uc_mem_type as MemoryAccess
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
with prefix="UC_"
|
with prefix = "UC_"
|
||||||
deriving (Show, Eq, Bounded) #}
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Hook callbacks
|
-- Hook callbacks
|
||||||
|
@ -159,16 +169,18 @@ type CodeHook a = Engine -- ^ 'Unicorn' engine handle
|
||||||
-> a -- ^ User data passed to tracing APIs
|
-> a -- ^ User data passed to tracing APIs
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
type CCodeHook = EnginePtr -> Word64 -> Word32 -> Ptr () -> IO ()
|
type CCodeHook = EnginePtr -> Word64 -> Word32 -> Ptr () -> IO ()
|
||||||
|
|
||||||
foreign import ccall "wrapper"
|
foreign import ccall "wrapper"
|
||||||
mkCodeHook :: CCodeHook -> IO {# type uc_cb_hookcode_t #}
|
mkCodeHook :: CCodeHook
|
||||||
|
-> IO {# type uc_cb_hookcode_t #}
|
||||||
|
|
||||||
marshalCodeHook :: Storable a
|
marshalCodeHook :: Storable a
|
||||||
=> CodeHook a -> IO {# type uc_cb_hookcode_t #}
|
=> CodeHook a
|
||||||
|
-> IO {# type uc_cb_hookcode_t #}
|
||||||
marshalCodeHook codeHook =
|
marshalCodeHook codeHook =
|
||||||
mkCodeHook $ \ucPtr address size userDataPtr -> do
|
mkCodeHook $ \ucPtr address size userDataPtr -> do
|
||||||
uc <- mkEngineNC ucPtr
|
uc <- mkEngineNC ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
let maybeSize = if size == 0 then Nothing
|
let maybeSize = if size == 0 then Nothing
|
||||||
else Just $ fromIntegral size
|
else Just $ fromIntegral size
|
||||||
|
@ -186,10 +198,11 @@ foreign import ccall "wrapper"
|
||||||
mkInterruptHook :: CInterruptHook -> IO {# type uc_cb_hookintr_t #}
|
mkInterruptHook :: CInterruptHook -> IO {# type uc_cb_hookintr_t #}
|
||||||
|
|
||||||
marshalInterruptHook :: Storable a
|
marshalInterruptHook :: Storable a
|
||||||
=> InterruptHook a -> IO {# type uc_cb_hookintr_t #}
|
=> InterruptHook a
|
||||||
|
-> IO {# type uc_cb_hookintr_t #}
|
||||||
marshalInterruptHook interruptHook =
|
marshalInterruptHook interruptHook =
|
||||||
mkInterruptHook $ \ucPtr intNo userDataPtr -> do
|
mkInterruptHook $ \ucPtr intNo userDataPtr -> do
|
||||||
uc <- mkEngineNC ucPtr
|
uc <- mkEngineNC ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
interruptHook uc (fromIntegral intNo) userData
|
interruptHook uc (fromIntegral intNo) userData
|
||||||
|
|
||||||
|
@ -197,7 +210,8 @@ marshalInterruptHook interruptHook =
|
||||||
type BlockHook a = CodeHook a
|
type BlockHook a = CodeHook a
|
||||||
|
|
||||||
marshalBlockHook :: Storable a
|
marshalBlockHook :: Storable a
|
||||||
=> BlockHook a -> IO {# type uc_cb_hookcode_t #}
|
=> BlockHook a
|
||||||
|
-> IO {# type uc_cb_hookcode_t #}
|
||||||
marshalBlockHook =
|
marshalBlockHook =
|
||||||
marshalCodeHook
|
marshalCodeHook
|
||||||
|
|
||||||
|
@ -214,10 +228,11 @@ foreign import ccall "wrapper"
|
||||||
mkInHook :: CInHook -> IO {# type uc_cb_insn_in_t #}
|
mkInHook :: CInHook -> IO {# type uc_cb_insn_in_t #}
|
||||||
|
|
||||||
marshalInHook :: Storable a
|
marshalInHook :: Storable a
|
||||||
=> InHook a -> IO {# type uc_cb_insn_in_t #}
|
=> InHook a
|
||||||
|
-> IO {# type uc_cb_insn_in_t #}
|
||||||
marshalInHook inHook =
|
marshalInHook inHook =
|
||||||
mkInHook $ \ucPtr port size userDataPtr -> do
|
mkInHook $ \ucPtr port size userDataPtr -> do
|
||||||
uc <- mkEngineNC ucPtr
|
uc <- mkEngineNC ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
inHook uc (fromIntegral port) (fromIntegral size) userData
|
inHook uc (fromIntegral port) (fromIntegral size) userData
|
||||||
|
|
||||||
|
@ -232,13 +247,15 @@ type OutHook a = Engine -- ^ 'Unicorn' engine handle
|
||||||
type COutHook = EnginePtr -> Word32 -> Int32 -> Word32 -> Ptr () -> IO ()
|
type COutHook = EnginePtr -> Word32 -> Int32 -> Word32 -> Ptr () -> IO ()
|
||||||
|
|
||||||
foreign import ccall "wrapper"
|
foreign import ccall "wrapper"
|
||||||
mkOutHook :: COutHook -> IO {# type uc_cb_insn_out_t #}
|
mkOutHook :: COutHook
|
||||||
|
-> IO {# type uc_cb_insn_out_t #}
|
||||||
|
|
||||||
marshalOutHook :: Storable a
|
marshalOutHook :: Storable a
|
||||||
=> OutHook a -> IO {# type uc_cb_insn_out_t #}
|
=> OutHook a
|
||||||
|
-> IO {# type uc_cb_insn_out_t #}
|
||||||
marshalOutHook outHook =
|
marshalOutHook outHook =
|
||||||
mkOutHook $ \ucPtr port size value userDataPtr -> do
|
mkOutHook $ \ucPtr port size value userDataPtr -> do
|
||||||
uc <- mkEngineNC ucPtr
|
uc <- mkEngineNC ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
outHook uc (fromIntegral port) (fromIntegral size) (fromIntegral value)
|
outHook uc (fromIntegral port) (fromIntegral size) (fromIntegral value)
|
||||||
userData
|
userData
|
||||||
|
@ -251,13 +268,15 @@ type SyscallHook a = Engine -- ^ 'Unicorn' engine handle
|
||||||
type CSyscallHook = Ptr () -> Ptr () -> IO ()
|
type CSyscallHook = Ptr () -> Ptr () -> IO ()
|
||||||
|
|
||||||
foreign import ccall "wrapper"
|
foreign import ccall "wrapper"
|
||||||
mkSyscallHook :: CSyscallHook -> IO {# type uc_cb_insn_syscall_t #}
|
mkSyscallHook :: CSyscallHook
|
||||||
|
-> IO {# type uc_cb_insn_syscall_t #}
|
||||||
|
|
||||||
marshalSyscallHook :: Storable a
|
marshalSyscallHook :: Storable a
|
||||||
=> SyscallHook a -> IO {# type uc_cb_insn_syscall_t #}
|
=> SyscallHook a
|
||||||
|
-> IO {# type uc_cb_insn_syscall_t #}
|
||||||
marshalSyscallHook syscallHook =
|
marshalSyscallHook syscallHook =
|
||||||
mkSyscallHook $ \ucPtr userDataPtr -> do
|
mkSyscallHook $ \ucPtr userDataPtr -> do
|
||||||
uc <- mkEngineNC $ castPtr ucPtr
|
uc <- mkEngineNC $ castPtr ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
syscallHook uc userData
|
syscallHook uc userData
|
||||||
|
|
||||||
|
@ -281,13 +300,15 @@ type CMemoryHook = EnginePtr
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "wrapper"
|
foreign import ccall "wrapper"
|
||||||
mkMemoryHook :: CMemoryHook -> IO {# type uc_cb_hookmem_t #}
|
mkMemoryHook :: CMemoryHook
|
||||||
|
-> IO {# type uc_cb_hookmem_t #}
|
||||||
|
|
||||||
marshalMemoryHook :: Storable a
|
marshalMemoryHook :: Storable a
|
||||||
=> MemoryHook a -> IO {# type uc_cb_hookmem_t #}
|
=> MemoryHook a
|
||||||
|
-> IO {# type uc_cb_hookmem_t #}
|
||||||
marshalMemoryHook memoryHook =
|
marshalMemoryHook memoryHook =
|
||||||
mkMemoryHook $ \ucPtr memAccessI address size value userDataPtr -> do
|
mkMemoryHook $ \ucPtr memAccessI address size value userDataPtr -> do
|
||||||
uc <- mkEngineNC ucPtr
|
uc <- mkEngineNC ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
let memAccess = toMemAccess memAccessI
|
let memAccess = toMemAccess memAccessI
|
||||||
maybeValue = case memAccess of
|
maybeValue = case memAccess of
|
||||||
|
@ -304,10 +325,11 @@ type MemoryReadHook a = Engine -- ^ 'Unicorn' engine handle
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
marshalMemoryReadHook :: Storable a
|
marshalMemoryReadHook :: Storable a
|
||||||
=> MemoryReadHook a -> IO {# type uc_cb_hookmem_t #}
|
=> MemoryReadHook a
|
||||||
|
-> IO {# type uc_cb_hookmem_t #}
|
||||||
marshalMemoryReadHook memoryReadHook =
|
marshalMemoryReadHook memoryReadHook =
|
||||||
mkMemoryHook $ \ucPtr _ address size _ userDataPtr -> do
|
mkMemoryHook $ \ucPtr _ address size _ userDataPtr -> do
|
||||||
uc <- mkEngineNC ucPtr
|
uc <- mkEngineNC ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
memoryReadHook uc address (fromIntegral size) userData
|
memoryReadHook uc address (fromIntegral size) userData
|
||||||
|
|
||||||
|
@ -321,10 +343,11 @@ type MemoryWriteHook a = Engine -- ^ 'Unicorn' engine handle
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
marshalMemoryWriteHook :: Storable a
|
marshalMemoryWriteHook :: Storable a
|
||||||
=> MemoryWriteHook a -> IO {# type uc_cb_hookmem_t #}
|
=> MemoryWriteHook a
|
||||||
|
-> IO {# type uc_cb_hookmem_t #}
|
||||||
marshalMemoryWriteHook memoryWriteHook =
|
marshalMemoryWriteHook memoryWriteHook =
|
||||||
mkMemoryHook $ \ucPtr _ address size value userDataPtr -> do
|
mkMemoryHook $ \ucPtr _ address size value userDataPtr -> do
|
||||||
uc <- mkEngineNC ucPtr
|
uc <- mkEngineNC ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
memoryWriteHook uc address (fromIntegral size) (fromIntegral value)
|
memoryWriteHook uc address (fromIntegral size) (fromIntegral value)
|
||||||
userData
|
userData
|
||||||
|
@ -351,15 +374,17 @@ type CMemoryEventHook = EnginePtr
|
||||||
-> IO Int32
|
-> IO Int32
|
||||||
|
|
||||||
foreign import ccall "wrapper"
|
foreign import ccall "wrapper"
|
||||||
mkMemoryEventHook :: CMemoryEventHook -> IO {# type uc_cb_eventmem_t #}
|
mkMemoryEventHook :: CMemoryEventHook
|
||||||
|
-> IO {# type uc_cb_eventmem_t #}
|
||||||
|
|
||||||
marshalMemoryEventHook :: Storable a
|
marshalMemoryEventHook :: Storable a
|
||||||
=> MemoryEventHook a -> IO {# type uc_cb_eventmem_t #}
|
=> MemoryEventHook a
|
||||||
|
-> IO {# type uc_cb_eventmem_t #}
|
||||||
marshalMemoryEventHook eventMemoryHook =
|
marshalMemoryEventHook eventMemoryHook =
|
||||||
mkMemoryEventHook $ \ucPtr memAccessI address size value userDataPtr -> do
|
mkMemoryEventHook $ \ucPtr memAccessI address size value userDataPtr -> do
|
||||||
uc <- mkEngineNC ucPtr
|
uc <- mkEngineNC ucPtr
|
||||||
userData <- castPtrAndPeek userDataPtr
|
userData <- castPtrAndPeek userDataPtr
|
||||||
let memAccess = toMemAccess memAccessI
|
let memAccess = toMemAccess memAccessI
|
||||||
maybeValue = case memAccess of
|
maybeValue = case memAccess of
|
||||||
MemReadUnmapped -> Nothing
|
MemReadUnmapped -> Nothing
|
||||||
MemReadProt -> Nothing
|
MemReadProt -> Nothing
|
||||||
|
@ -369,7 +394,7 @@ marshalMemoryEventHook eventMemoryHook =
|
||||||
res <- eventMemoryHook uc memAccess address (fromIntegral size)
|
res <- eventMemoryHook uc memAccess address (fromIntegral size)
|
||||||
maybeValue userData
|
maybeValue userData
|
||||||
return $ boolToInt res
|
return $ boolToInt res
|
||||||
where boolToInt True = 1
|
where boolToInt True = 1
|
||||||
boolToInt False = 0
|
boolToInt False = 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -378,38 +403,43 @@ marshalMemoryEventHook eventMemoryHook =
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
{# fun variadic uc_hook_add as ucHookAdd
|
{# fun variadic uc_hook_add as ucHookAdd
|
||||||
`(Storable a, HookTypeC h)' =>
|
`HookTypeC h' =>
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
alloca- `Hook' peek*,
|
, alloca- `Hook' peek*
|
||||||
enumToNum `h',
|
, enumToNum `h'
|
||||||
castFunPtrToPtr `FunPtr b',
|
, castFunPtrToPtr `FunPtr b'
|
||||||
castPtr `Ptr a',
|
, castPtr `Ptr a'
|
||||||
`Word64',
|
, `Word64'
|
||||||
`Word64'}
|
, `Word64'
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun variadic uc_hook_add[int] as ucInsnHookAdd
|
{# fun variadic uc_hook_add[int] as ucInsnHookAdd
|
||||||
`(Storable a, HookTypeC h)' =>
|
`HookTypeC h' =>
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
alloca- `Hook' peek*,
|
, alloca- `Hook' peek*
|
||||||
enumToNum `h',
|
, enumToNum `h'
|
||||||
castFunPtrToPtr `FunPtr b',
|
, castFunPtrToPtr `FunPtr b'
|
||||||
castPtr `Ptr a',
|
, castPtr `Ptr a'
|
||||||
`Word64',
|
, `Word64'
|
||||||
`Word64',
|
, `Word64'
|
||||||
enumToNum `Instruction'}
|
, enumToNum `Instruction'
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
-- | Unregister (remove) a hook callback.
|
-- | Unregister (remove) a hook callback.
|
||||||
{# fun uc_hook_del as ^
|
{# fun uc_hook_del as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
fromIntegral `Hook'}
|
, fromIntegral `Hook'
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Helper functions
|
-- Helper functions
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
toMemAccess :: Integral a => a -> MemoryAccess
|
toMemAccess :: Integral a
|
||||||
|
=> a
|
||||||
|
-> MemoryAccess
|
||||||
toMemAccess =
|
toMemAccess =
|
||||||
toEnum . fromIntegral
|
toEnum . fromIntegral
|
||||||
|
|
|
@ -12,33 +12,39 @@ Low-level bindings for the Unicorn CPU emulator framework.
|
||||||
This module should not be directly imported; it is only exposed because of the
|
This module should not be directly imported; it is only exposed because of the
|
||||||
way cabal handles ordering of chs files.
|
way cabal handles ordering of chs files.
|
||||||
-}
|
-}
|
||||||
module Unicorn.Internal.Unicorn (
|
module Unicorn.Internal.Unicorn
|
||||||
-- * Types
|
( -- * Types
|
||||||
Architecture(..),
|
Architecture(..)
|
||||||
Mode(..),
|
, Mode(..)
|
||||||
MemoryPermission(..),
|
, MemoryPermission(..)
|
||||||
MemoryRegion(..),
|
, MemoryRegion(..)
|
||||||
QueryType(..),
|
, QueryType(..)
|
||||||
|
, Context
|
||||||
|
|
||||||
-- * Function bindings
|
-- * Function bindings
|
||||||
ucOpen,
|
, ucOpen
|
||||||
ucQuery,
|
, ucQuery
|
||||||
ucEmuStart,
|
, ucEmuStart
|
||||||
ucEmuStop,
|
, ucEmuStop
|
||||||
ucRegWrite,
|
, ucRegWrite
|
||||||
ucRegRead,
|
, ucRegRead
|
||||||
ucMemWrite,
|
, ucMemWrite
|
||||||
ucMemRead,
|
, ucMemRead
|
||||||
ucMemMap,
|
, ucMemMap
|
||||||
ucMemUnmap,
|
, ucMemUnmap
|
||||||
ucMemProtect,
|
, ucMemProtect
|
||||||
ucMemRegions,
|
, ucMemRegions
|
||||||
ucVersion,
|
, mkContext
|
||||||
ucErrno,
|
, ucContextAlloc
|
||||||
ucStrerror,
|
, ucContextSave
|
||||||
) where
|
, ucContextRestore
|
||||||
|
, ucVersion
|
||||||
|
, ucErrno
|
||||||
|
, ucStrerror
|
||||||
|
) where
|
||||||
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
|
import Control.Monad
|
||||||
import Data.ByteString (ByteString, useAsCStringLen)
|
import Data.ByteString (ByteString, useAsCStringLen)
|
||||||
import Foreign
|
import Foreign
|
||||||
import Foreign.C
|
import Foreign.C
|
||||||
|
@ -46,11 +52,12 @@ import Prelude hiding (until)
|
||||||
|
|
||||||
import Unicorn.Internal.Util
|
import Unicorn.Internal.Util
|
||||||
|
|
||||||
{# context lib="unicorn" #}
|
|
||||||
|
|
||||||
{# import Unicorn.Internal.Core #}
|
{# import Unicorn.Internal.Core #}
|
||||||
|
|
||||||
|
{# context lib = "unicorn" #}
|
||||||
|
|
||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
|
#include "unicorn_wrapper.h"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Types
|
-- Types
|
||||||
|
@ -58,29 +65,33 @@ import Unicorn.Internal.Util
|
||||||
|
|
||||||
-- | CPU architecture.
|
-- | CPU architecture.
|
||||||
{# enum uc_arch as Architecture
|
{# enum uc_arch as Architecture
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
with prefix="UC_"
|
with prefix = "UC_"
|
||||||
deriving (Show, Eq, Bounded) #}
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
-- | CPU hardware mode.
|
-- | CPU hardware mode.
|
||||||
{# enum uc_mode as Mode
|
{# enum uc_mode as Mode
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
with prefix="UC_"
|
with prefix = "UC_"
|
||||||
deriving (Show, Eq, Bounded) #}
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
-- | Memory permissions.
|
-- | Memory permissions.
|
||||||
{# enum uc_prot as MemoryPermission
|
{# enum uc_prot as MemoryPermission
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
with prefix="UC_"
|
with prefix = "UC_"
|
||||||
deriving (Show, Eq, Bounded) #}
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
-- | Memory region mapped by 'memMap'. Retrieve the list of memory regions with
|
-- | Memory region mapped by 'memMap'. Retrieve the list of memory regions with
|
||||||
-- 'memRegions'.
|
-- 'memRegions'.
|
||||||
data MemoryRegion = MemoryRegion {
|
data MemoryRegion = MemoryRegion
|
||||||
mrBegin :: Word64, -- ^ Begin address of the region (inclusive)
|
{
|
||||||
mrEnd :: Word64, -- ^ End address of the region (inclusive)
|
mrBegin :: Word64 -- ^ Begin address of the region (inclusive)
|
||||||
mrPerms :: [MemoryPermission] -- ^ Memory permissions of the region
|
, mrEnd :: Word64 -- ^ End address of the region (inclusive)
|
||||||
}
|
, mrPerms :: [MemoryPermission] -- ^ Memory permissions of the region
|
||||||
|
}
|
||||||
|
|
||||||
instance Storable MemoryRegion where
|
instance Storable MemoryRegion where
|
||||||
sizeOf _ = {# sizeof uc_mem_region #}
|
sizeOf _ = {# sizeof uc_mem_region #}
|
||||||
|
@ -99,121 +110,174 @@ instance Storable MemoryRegion where
|
||||||
|
|
||||||
-- | Query types for the 'query' API.
|
-- | Query types for the 'query' API.
|
||||||
{# enum uc_query_type as QueryType
|
{# enum uc_query_type as QueryType
|
||||||
{underscoreToCase}
|
{ underscoreToCase }
|
||||||
with prefix="UC_"
|
with prefix = "UC_"
|
||||||
deriving (Show, Eq, Bounded) #}
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
|
-- | Opaque storage for CPU context, used with the context functions.
|
||||||
|
{# pointer *uc_context as Context
|
||||||
|
foreign finalizer uc_context_free_wrapper as contextFree
|
||||||
|
newtype
|
||||||
|
#}
|
||||||
|
|
||||||
|
-- | A pointer to a CPU context.
|
||||||
|
{# pointer *uc_context as ContextPtr -> Context #}
|
||||||
|
|
||||||
|
-- | Make a CPU context out of a context pointer. The returned CPU context will
|
||||||
|
-- automatically call 'uc_context_free' when it goes out of scope.
|
||||||
|
mkContext :: ContextPtr
|
||||||
|
-> IO Context
|
||||||
|
mkContext ptr =
|
||||||
|
liftM Context (newForeignPtr contextFree ptr)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Emulator control
|
-- Emulator control
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
{# fun uc_open as ^
|
{# fun uc_open as ^
|
||||||
{`Architecture',
|
{ `Architecture'
|
||||||
combineEnums `[Mode]',
|
, combineEnums `[Mode]'
|
||||||
alloca- `EnginePtr' peek*}
|
, alloca- `EnginePtr' peek*
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun uc_query as ^
|
{# fun uc_query as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
`QueryType',
|
, `QueryType'
|
||||||
alloca- `Int' castPtrAndPeek*}
|
, alloca- `Int' castPtrAndPeek*
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun uc_emu_start as ^
|
{# fun uc_emu_start as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
`Word64',
|
, `Word64'
|
||||||
`Word64',
|
, `Word64'
|
||||||
`Int',
|
, `Int'
|
||||||
`Int'}
|
, `Int'} -> `Error'
|
||||||
-> `Error' #}
|
#}
|
||||||
|
|
||||||
{# fun uc_emu_stop as ^
|
{# fun uc_emu_stop as ^
|
||||||
{`Engine'}
|
{ `Engine'
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Register operations
|
-- Register operations
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
{# fun uc_reg_write as ^
|
{# fun uc_reg_write as ^
|
||||||
`Reg r' =>
|
`Reg r' =>
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
enumToNum `r',
|
, enumToNum `r'
|
||||||
castPtr `Ptr Int64'}
|
, castPtr `Ptr Int64'
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun uc_reg_read as ^
|
{# fun uc_reg_read as ^
|
||||||
`Reg r' =>
|
`Reg r' =>
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
enumToNum `r',
|
, enumToNum `r'
|
||||||
allocaInt64ToVoid- `Int64' castPtrAndPeek*}
|
, allocaInt64ToVoid- `Int64' castPtrAndPeek*
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Memory operations
|
-- Memory operations
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
{# fun uc_mem_write as ^
|
{# fun uc_mem_write as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
`Word64',
|
, `Word64'
|
||||||
withByteStringLen* `ByteString'&}
|
, withByteStringLen* `ByteString'&
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun uc_mem_read as ^
|
{# fun uc_mem_read as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
`Word64',
|
, `Word64'
|
||||||
castPtr `Ptr Word8',
|
, castPtr `Ptr Word8'
|
||||||
`Int'}
|
, `Int'} -> `Error'
|
||||||
-> `Error' #}
|
#}
|
||||||
|
|
||||||
{# fun uc_mem_map as ^
|
{# fun uc_mem_map as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
`Word64',
|
, `Word64'
|
||||||
`Int',
|
, `Int'
|
||||||
combineEnums `[MemoryPermission]'}
|
, combineEnums `[MemoryPermission]'
|
||||||
-> `Error' #}
|
} -> `Error' #}
|
||||||
|
|
||||||
{# fun uc_mem_unmap as ^
|
{# fun uc_mem_unmap as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
`Word64',
|
, `Word64'
|
||||||
`Int'}
|
, `Int'
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun uc_mem_protect as ^
|
{# fun uc_mem_protect as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
`Word64',
|
, `Word64'
|
||||||
`Int',
|
, `Int'
|
||||||
combineEnums `[MemoryPermission]'}
|
, combineEnums `[MemoryPermission]'
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun uc_mem_regions as ^
|
{# fun uc_mem_regions as ^
|
||||||
{`Engine',
|
{ `Engine'
|
||||||
alloca- `MemoryRegionPtr' peek*,
|
, alloca- `MemoryRegionPtr' peek*
|
||||||
alloca- `Int' castPtrAndPeek*}
|
, alloca- `Int' castPtrAndPeek*
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Context
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{# fun uc_context_alloc as ^
|
||||||
|
{ `Engine'
|
||||||
|
, alloca- `ContextPtr' peek*
|
||||||
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun uc_context_save as ^
|
||||||
|
{ `Engine'
|
||||||
|
, `Context'
|
||||||
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun uc_context_restore as ^
|
||||||
|
{ `Engine'
|
||||||
|
, `Context'
|
||||||
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Misc.
|
-- Misc.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
{# fun pure unsafe uc_version as ^
|
{# fun pure unsafe uc_version as ^
|
||||||
{id `Ptr CUInt',
|
{ id `Ptr CUInt'
|
||||||
id `Ptr CUInt'}
|
, id `Ptr CUInt'
|
||||||
-> `Int' #}
|
} -> `Int'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun unsafe uc_errno as ^
|
{# fun unsafe uc_errno as ^
|
||||||
{`Engine'}
|
{ `Engine'
|
||||||
-> `Error' #}
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun pure unsafe uc_strerror as ^
|
{# fun pure unsafe uc_strerror as ^
|
||||||
{`Error'}
|
{ `Error'
|
||||||
-> `String' #}
|
} -> `String'
|
||||||
|
#}
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Helper functions
|
-- Helper functions
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
expandMemPerms :: (Integral a, Bits a) => a -> [MemoryPermission]
|
expandMemPerms :: (Integral a, Bits a)
|
||||||
|
=> a
|
||||||
|
-> [MemoryPermission]
|
||||||
expandMemPerms perms =
|
expandMemPerms perms =
|
||||||
-- Only interested in the 3 least-significant bits
|
-- Only interested in the 3 least-significant bits
|
||||||
let maskedPerms = fromIntegral $ perms .&. 0x7 in
|
let maskedPerms = fromIntegral $ perms .&. 0x7 in
|
||||||
|
@ -232,10 +296,13 @@ expandMemPerms perms =
|
||||||
checkRWE _ [] =
|
checkRWE _ [] =
|
||||||
[]
|
[]
|
||||||
|
|
||||||
allocaInt64ToVoid :: (Ptr () -> IO b) -> IO b
|
allocaInt64ToVoid :: (Ptr () -> IO b)
|
||||||
|
-> IO b
|
||||||
allocaInt64ToVoid f =
|
allocaInt64ToVoid f =
|
||||||
alloca $ \(ptr :: Ptr Int64) -> poke ptr 0 >> f (castPtr ptr)
|
alloca $ \(ptr :: Ptr Int64) -> poke ptr 0 >> f (castPtr ptr)
|
||||||
|
|
||||||
withByteStringLen :: ByteString -> ((Ptr (), CULong) -> IO a) -> IO a
|
withByteStringLen :: ByteString
|
||||||
|
-> ((Ptr (), CULong) -> IO a)
|
||||||
|
-> IO a
|
||||||
withByteStringLen bs f =
|
withByteStringLen bs f =
|
||||||
useAsCStringLen bs $ \(ptr, len) -> f (castPtr ptr, fromIntegral len)
|
useAsCStringLen bs $ \(ptr, len) -> f (castPtr ptr, fromIntegral len)
|
||||||
|
|
|
@ -10,16 +10,22 @@ import Data.Bits
|
||||||
import Foreign
|
import Foreign
|
||||||
|
|
||||||
-- | Combine a list of Enums by performing a bitwise-OR.
|
-- | Combine a list of Enums by performing a bitwise-OR.
|
||||||
combineEnums :: (Enum a, Num b, Bits b) => [a] -> b
|
combineEnums :: (Enum a, Num b, Bits b)
|
||||||
|
=> [a]
|
||||||
|
-> b
|
||||||
combineEnums =
|
combineEnums =
|
||||||
foldr ((.|.) <$> enumToNum) 0
|
foldr ((.|.) <$> enumToNum) 0
|
||||||
|
|
||||||
-- | Cast a pointer and then peek inside it.
|
-- | Cast a pointer and then peek inside it.
|
||||||
castPtrAndPeek :: Storable a => Ptr b -> IO a
|
castPtrAndPeek :: Storable a
|
||||||
|
=> Ptr b
|
||||||
|
-> IO a
|
||||||
castPtrAndPeek =
|
castPtrAndPeek =
|
||||||
peek . castPtr
|
peek . castPtr
|
||||||
|
|
||||||
-- | Convert an 'Eum' to a 'Num'.
|
-- | Convert an 'Eum' to a 'Num'.
|
||||||
enumToNum :: (Enum a, Num b) => a -> b
|
enumToNum :: (Enum a, Num b)
|
||||||
|
=> a
|
||||||
|
-> b
|
||||||
enumToNum =
|
enumToNum =
|
||||||
fromIntegral . fromEnum
|
fromIntegral . fromEnum
|
||||||
|
|
|
@ -6,3 +6,7 @@ void uc_close_wrapper(uc_engine *uc) {
|
||||||
|
|
||||||
void uc_close_dummy(uc_engine *uc) {
|
void uc_close_dummy(uc_engine *uc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uc_context_free_wrapper(uc_context *context) {
|
||||||
|
uc_context_free(context);
|
||||||
|
}
|
||||||
|
|
|
@ -13,4 +13,9 @@ void uc_close_wrapper(uc_engine *uc);
|
||||||
*/
|
*/
|
||||||
void uc_close_dummy(uc_engine *uc);
|
void uc_close_dummy(uc_engine *uc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrap Unicorn's uc_context_free function and ignore the returned error code.
|
||||||
|
*/
|
||||||
|
void uc_context_free_wrapper(uc_context *context);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,8 +13,9 @@ copyright: (c) 2016, Adrian Herrera
|
||||||
category: System
|
category: System
|
||||||
build-type: Simple
|
build-type: Simple
|
||||||
stability: experimental
|
stability: experimental
|
||||||
cabal-version: >=1.10
|
cabal-version: >= 1.10
|
||||||
extra-source-files: cbits/, include/
|
extra-source-files: cbits/
|
||||||
|
, include/
|
||||||
|
|
||||||
library
|
library
|
||||||
exposed-modules: Unicorn.Internal.Core
|
exposed-modules: Unicorn.Internal.Core
|
||||||
|
@ -29,10 +30,10 @@ library
|
||||||
Unicorn.Hook
|
Unicorn.Hook
|
||||||
Unicorn
|
Unicorn
|
||||||
other-modules: Unicorn.Internal.Util
|
other-modules: Unicorn.Internal.Util
|
||||||
build-depends: base >=4 && <5,
|
build-depends: base >=4 && <5
|
||||||
bytestring >= 0.9.1,
|
, bytestring >= 0.9.1
|
||||||
transformers < 0.6,
|
, transformers < 0.6
|
||||||
either >= 4.4
|
, either >= 4.4
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
c-sources: src/cbits/unicorn_wrapper.c
|
c-sources: src/cbits/unicorn_wrapper.c
|
||||||
include-dirs: src/include
|
include-dirs: src/include
|
||||||
|
|
Loading…
Reference in New Issue