Merge pull request #60 from GaloisInc/nonce_handle_deparameterize

Nonce handle deparameterize
This commit is contained in:
Kevin Quick 2019-07-21 22:53:58 -07:00 committed by GitHub
commit 1c25aa59b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 135 additions and 138 deletions

2
deps/crucible vendored

@ -1 +1 @@
Subproject commit 0a7c3afff84b3c34555c0812f15308bc5bf04c55
Subproject commit 847bd2d1cd792f9dfa21a6fa58b7be50d7e46c19

View File

@ -247,31 +247,31 @@ archUpdateReg regEntry reg val =
Nothing -> error $ "unexpected register: " ++ show (MC.prettyF reg)
ppcGenFn :: forall ids h s tp v ppc
ppcGenFn :: forall ids s tp v ppc
. ( ppc ~ MP.AnyPPC v )
=> MP.PPCPrimFn ppc (MC.Value ppc ids) tp
-> MSB.CrucGen ppc ids h s (C.Atom s (MS.ToCrucibleType tp))
-> MSB.CrucGen ppc ids s (C.Atom s (MS.ToCrucibleType tp))
ppcGenFn fn = do
let f :: MC.Value ppc ids a -> MSB.CrucGen ppc ids h s (A.AtomWrapper (C.Atom s) a)
let f :: MC.Value ppc ids a -> MSB.CrucGen ppc ids s (A.AtomWrapper (C.Atom s) a)
f x = A.AtomWrapper <$> MSB.valueToCrucible x
r <- FC.traverseFC f fn
MSB.evalArchStmt (PPCPrimFn r)
ppcGenStmt :: forall v ids h s ppc
ppcGenStmt :: forall v ids s ppc
. ( ppc ~ MP.AnyPPC v )
=> MP.PPCStmt ppc (MC.Value ppc ids)
-> MSB.CrucGen ppc ids h s ()
-> MSB.CrucGen ppc ids s ()
ppcGenStmt s = do
let f :: MC.Value ppc ids a -> MSB.CrucGen ppc ids h s (A.AtomWrapper (C.Atom s) a)
let f :: MC.Value ppc ids a -> MSB.CrucGen ppc ids s (A.AtomWrapper (C.Atom s) a)
f x = A.AtomWrapper <$> MSB.valueToCrucible x
s' <- TF.traverseF f s
void (MSB.evalArchStmt (PPCPrimStmt s'))
ppcGenTermStmt :: forall v ids h s ppc
ppcGenTermStmt :: forall v ids s ppc
. ( ppc ~ MP.AnyPPC v )
=> MP.PPCTermStmt ids
-> MC.RegState (MP.PPCReg ppc) (MC.Value ppc ids)
-> MSB.CrucGen ppc ids h s ()
-> MSB.CrucGen ppc ids s ()
ppcGenTermStmt ts _rs =
void (MSB.evalArchStmt (PPCPrimTerm ts))

View File

@ -111,13 +111,12 @@ import GHC.TypeLits
import Control.Lens ((^.))
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.ST (ST, RealWorld, stToIO)
import Data.Foldable
import qualified Data.Map.Strict as Map
import Data.Maybe
import Data.Parameterized.Context (EmptyCtx, (::>), pattern Empty, pattern (:>))
import qualified Data.Parameterized.Context as Ctx
import Data.Parameterized.Nonce ( NonceGenerator, newSTNonceGenerator )
import Data.Parameterized.Nonce ( NonceGenerator, newIONonceGenerator )
import Data.Parameterized.Some ( Some(Some) )
import qualified Data.Parameterized.TraversableFC as FC
import qualified Data.Vector as V
@ -225,22 +224,22 @@ type SymArchConstraints arch =
-- Useful as an alternative to 'mkCrucCFG' if post-processing is
-- desired (as this is easier to do with the registerized form); use
-- 'toCoreCFG' to finish.
mkCrucRegCFG :: forall h arch ids
mkCrucRegCFG :: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Crucible architecture-specific functions.
-> C.HandleAllocator h
-> C.HandleAllocator
-- ^ Handle allocator to make function handles
-> C.FunctionName
-- ^ Name of function for pretty print purposes.
-> (forall s. MacawMonad arch ids h s (CR.Label s, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)]))
-> (forall s. MacawMonad arch ids s (CR.Label s, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)]))
-- ^ Action to run
-> ST h (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkCrucRegCFG archFns halloc nm action = do
let crucRegTypes = crucArchRegTypes archFns
let macawStructRepr = C.StructRepr crucRegTypes
let argTypes = Empty :> macawStructRepr
h <- C.mkHandle' halloc nm argTypes macawStructRepr
Some (ng :: NonceGenerator (ST h) s) <- newSTNonceGenerator
Some (ng :: NonceGenerator IO s) <- newIONonceGenerator
let ps0 = initCrucPersistentState ng
blockRes <- runMacawMonad ps0 action
(entry, blks) <-
@ -257,7 +256,7 @@ mkCrucRegCFG archFns halloc nm action = do
pure $ CR.SomeCFG rg
-- | Create a Crucible CFG from a list of blocks
addBlocksCFG :: forall h s arch ids
addBlocksCFG :: forall s arch ids
. MacawSymbolicArchFunctions arch
-- ^ Crucible specific functions.
-> MemSegmentMap (M.ArchAddrWidth arch)
@ -268,7 +267,7 @@ addBlocksCFG :: forall h s arch ids
-- ^ Function that maps offsets from start of block to Crucible position.
-> M.Block arch ids
-- ^ Macaw block for this region.
-> MacawMonad arch ids h s (CR.Label s, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)])
-> MacawMonad arch ids s (CR.Label s, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)])
addBlocksCFG archFns baseAddrMap addr posFn macawBlock = do
crucGenArchConstraints archFns $ do
-- Map block map to Crucible CFG
@ -285,10 +284,10 @@ addBlocksCFG archFns baseAddrMap addr posFn macawBlock = do
--
-- Also note that any 'M.FetchAndExecute' terminators are turned into Crucible
-- return statements.
mkBlocksRegCFG :: forall s arch ids
mkBlocksRegCFG :: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Crucible specific functions.
-> C.HandleAllocator s
-> C.HandleAllocator
-- ^ Handle allocator to make the blocks
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Map from region indices to their address
@ -300,7 +299,7 @@ mkBlocksRegCFG :: forall s arch ids
-- ^ Function that maps offsets from start of block to Crucible position.
-> M.Block arch ids
-- ^ List of blocks for this region.
-> ST s (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkBlocksRegCFG archFns halloc memBaseVarMap nm addr posFn macawBlock = do
mkCrucRegCFG archFns halloc nm $ do
addBlocksCFG archFns memBaseVarMap addr posFn macawBlock
@ -314,10 +313,10 @@ mkBlocksRegCFG archFns halloc memBaseVarMap nm addr posFn macawBlock = do
--
-- Also note that any 'M.FetchAndExecute' terminators are turned into Crucible
-- return statements.
mkBlocksCFG :: forall s arch ids
mkBlocksCFG :: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Crucible specific functions.
-> C.HandleAllocator s
-> C.HandleAllocator
-- ^ Handle allocator to make the blocks
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Map from region indices to their address
@ -329,15 +328,15 @@ mkBlocksCFG :: forall s arch ids
-- ^ Function that maps offsets from start of block to Crucible position.
-> M.Block arch ids
-- ^ List of blocks for this region.
-> ST s (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkBlocksCFG archFns halloc memBaseVarMap nm addr posFn macawBlock =
toCoreCFG archFns <$>
mkBlocksRegCFG archFns halloc memBaseVarMap nm addr posFn macawBlock
-- | Create a map from Macaw @(address, index)@ pairs to Crucible labels
mkBlockLabelMap :: [M.ParsedBlock arch ids] -> MacawMonad arch ids h s (BlockLabelMap arch s)
mkBlockLabelMap :: [M.ParsedBlock arch ids] -> MacawMonad arch ids s (BlockLabelMap arch s)
mkBlockLabelMap blks = foldM insBlock Map.empty blks
where insBlock :: BlockLabelMap arch s -> M.ParsedBlock arch ids -> MacawMonad arch ids h s (BlockLabelMap arch s)
where insBlock :: BlockLabelMap arch s -> M.ParsedBlock arch ids -> MacawMonad arch ids s (BlockLabelMap arch s)
insBlock m b = do
let base = M.pblockAddr b
n <- mmFreshNonce
@ -388,10 +387,10 @@ termStmtToJump tm0 addr =
-- This is useful as an alternative to 'mkParsedBlockCFG' if post-processing is
-- desired (as this is easier on the registerized form). Use 'toCoreCFG' to
-- finish by translating the registerized CFG to SSA.
mkParsedBlockRegCFG :: forall h arch ids
mkParsedBlockRegCFG :: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Architecture specific functions.
-> C.HandleAllocator h
-> C.HandleAllocator
-- ^ Handle allocator to make the blocks
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Map from region indices to their address
@ -399,7 +398,7 @@ mkParsedBlockRegCFG :: forall h arch ids
-- ^ Function that maps function address to Crucible position
-> M.ParsedBlock arch ids
-- ^ Block to translate
-> ST h (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkParsedBlockRegCFG archFns halloc memBaseVarMap posFn b = crucGenArchConstraints archFns $ do
mkCrucRegCFG archFns halloc "" $ do
let strippedBlock = b { M.pblockTermStmt = termStmtToReturn (M.pblockTermStmt b) }
@ -454,10 +453,10 @@ mkParsedBlockRegCFG archFns halloc memBaseVarMap posFn b = crucGenArchConstraint
--
-- Note that this function takes 'M.ParsedBlock's, which are the blocks
-- available in the 'M.DiscoveryFunInfo'.
mkParsedBlockCFG :: forall s arch ids
mkParsedBlockCFG :: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Architecture specific functions.
-> C.HandleAllocator s
-> C.HandleAllocator
-- ^ Handle allocator to make the blocks
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Map from region indices to their address
@ -465,15 +464,15 @@ mkParsedBlockCFG :: forall s arch ids
-- ^ Function that maps function address to Crucible position
-> M.ParsedBlock arch ids
-- ^ Block to translate
-> ST s (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkParsedBlockCFG archFns halloc memBaseVarMap posFn b =
toCoreCFG archFns <$> mkParsedBlockRegCFG archFns halloc memBaseVarMap posFn b
mkBlockPathRegCFG
:: forall h arch ids
:: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Architecture specific functions.
-> C.HandleAllocator h
-> C.HandleAllocator
-- ^ Handle allocator to make the blocks
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Map from region indices to their address
@ -481,7 +480,7 @@ mkBlockPathRegCFG
-- ^ Function that maps function address to Crucible position
-> [M.ParsedBlock arch ids]
-- ^ Bloc path to translate
-> ST h (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkBlockPathRegCFG arch_fns halloc mem_base_var_map pos_fn blocks =
crucGenArchConstraints arch_fns $ mkCrucRegCFG arch_fns halloc "" $ do
let entry_addr = M.pblockAddr $ head blocks
@ -555,10 +554,10 @@ mkBlockPathRegCFG arch_fns halloc mem_base_var_map pos_fn blocks =
init_extra_crucible_blocks ++ concat crucible_blocks)
mkBlockPathCFG
:: forall s arch ids
:: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Architecture specific functions.
-> C.HandleAllocator s
-> C.HandleAllocator
-- ^ Handle allocator to make the blocks
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Map from region indices to their address
@ -566,7 +565,7 @@ mkBlockPathCFG
-- ^ Function that maps function address to Crucible position
-> [M.ParsedBlock arch ids]
-- ^ Block to translate
-> ST s (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkBlockPathCFG arch_fns halloc mem_base_var_map pos_fn blocks =
toCoreCFG arch_fns <$>
mkBlockPathRegCFG arch_fns halloc mem_base_var_map pos_fn blocks
@ -577,10 +576,10 @@ mkBlockPathCFG arch_fns halloc mem_base_var_map pos_fn blocks =
-- This is provided as an alternative to 'mkFunCFG' to allow for post-processing
-- of the CFG (e.g., instrumentation) prior to the SSA conversion (which can be
-- done using 'toCoreCFG').
mkFunRegCFG :: forall h arch ids
mkFunRegCFG :: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Architecture specific functions.
-> C.HandleAllocator h
-> C.HandleAllocator
-- ^ Handle allocator to make the blocks
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Map from region indices to their address
@ -590,7 +589,7 @@ mkFunRegCFG :: forall h arch ids
-- ^ Function that maps function address to Crucible position
-> M.DiscoveryFunInfo arch ids
-- ^ List of blocks for this region.
-> ST h (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkFunRegCFG archFns halloc memBaseVarMap nm posFn fn = crucGenArchConstraints archFns $ do
mkCrucRegCFG archFns halloc nm $ do
-- Get entry point address for function
@ -636,10 +635,10 @@ mkFunRegCFG archFns halloc memBaseVarMap nm posFn fn = crucGenArchConstraints ar
initExtraCrucibleBlocks ++ concat restCrucibleBlocks)
-- | Translate a macaw function (passed as a 'M.DiscoveryFunInfo') into a Crucible 'C.CFG' (in SSA form)
mkFunCFG :: forall s arch ids
mkFunCFG :: forall arch ids
. MacawSymbolicArchFunctions arch
-- ^ Architecture specific functions.
-> C.HandleAllocator s
-> C.HandleAllocator
-- ^ Handle allocator to make the blocks
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Map from region indices to their address
@ -649,7 +648,7 @@ mkFunCFG :: forall s arch ids
-- ^ Function that maps function address to Crucible position
-> M.DiscoveryFunInfo arch ids
-- ^ List of blocks for this region.
-> ST s (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
-> IO (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkFunCFG archFns halloc memBaseVarMap nm posFn fn =
toCoreCFG archFns <$> mkFunRegCFG archFns halloc memBaseVarMap nm posFn fn
@ -879,7 +878,7 @@ runCodeBlock
-> MacawSymbolicArchFunctions arch
-- ^ Translation functions
-> SB.MacawArchEvalFn sym arch
-> C.HandleAllocator RealWorld
-> C.HandleAllocator
-> (MM.MemImpl sym, GlobalMap sym (M.ArchAddrWidth arch))
-> LookupFunctionHandle sym arch
-> C.CFG (MacawExt arch) blocks (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch)
@ -892,7 +891,7 @@ runCodeBlock
(MacawExt arch)
(C.RegEntry sym (ArchRegStruct arch)))
runCodeBlock sym archFns archEval halloc (initMem,globs) lookupH g regStruct = do
mvar <- stToIO (MM.mkMemVar halloc)
mvar <- MM.mkMemVar halloc
let crucRegTypes = crucArchRegTypes archFns
let macawStructRepr = C.StructRepr crucRegTypes

View File

@ -80,7 +80,6 @@ module Data.Macaw.Symbolic.CrucGen
import Control.Lens hiding (Empty, (:>))
import Control.Monad ( foldM )
import Control.Monad.Except
import Control.Monad.ST
import Control.Monad.State.Strict
import Data.Bits
import qualified Data.Kind as K
@ -194,17 +193,17 @@ data MacawSymbolicArchFunctions arch
-- LOT of memory---TypeReprs were dominating the heap).
, crucGenArchRegName :: !(forall tp . M.ArchReg arch tp -> C.SolverSymbol)
-- ^ Provides a solver name to use for referring to register.
, crucGenArchFn :: !(forall ids h s tp
, crucGenArchFn :: !(forall ids s tp
. M.ArchFn arch (M.Value arch ids) tp
-> CrucGen arch ids h s (CR.Atom s (ToCrucibleType tp)))
-> CrucGen arch ids s (CR.Atom s (ToCrucibleType tp)))
-- ^ Generate crucible for architecture-specific function.
, crucGenArchStmt
:: !(forall ids h s . M.ArchStmt arch (M.Value arch ids) -> CrucGen arch ids h s ())
:: !(forall ids s . M.ArchStmt arch (M.Value arch ids) -> CrucGen arch ids s ())
-- ^ Generate crucible for architecture-specific statement.
, crucGenArchTermStmt :: !(forall ids h s
, crucGenArchTermStmt :: !(forall ids s
. M.ArchTermStmt arch ids
-> M.RegState (M.ArchReg arch) (M.Value arch ids)
-> CrucGen arch ids h s ())
-> CrucGen arch ids s ())
-- ^ Generate crucible for architecture-specific terminal statement.
}
@ -570,14 +569,14 @@ instance MacawArchConstraints arch
type MemSegmentMap w = Map M.RegionIndex (CR.GlobalVar (C.BVType w))
-- | State used for generating blocks
data CrucGenState arch ids h s
data CrucGenState arch ids s
= CrucGenState
{ translateFns :: !(MacawSymbolicArchFunctions arch)
, crucMemBaseAddrMap :: !(MemSegmentMap (M.ArchAddrWidth arch))
-- ^ Map from memory region to base address
, crucRegIndexMap :: !(RegIndexMap arch)
-- ^ Map from architecture register to Crucible/Macaw index pair.
, crucPState :: !(CrucPersistentState ids h s)
, crucPState :: !(CrucPersistentState ids s)
-- ^ State that persists across blocks.
, crucRegisterReg :: !(CR.Reg s (ArchRegStruct arch))
, macawPositionFn :: !(M.ArchAddrWord arch -> C.Position)
@ -623,43 +622,43 @@ instance OrdF (BVAtom s) where
GTF -> GTF
crucPStateLens ::
Simple Lens (CrucGenState arch ids h s) (CrucPersistentState ids h s)
Simple Lens (CrucGenState arch ids s) (CrucPersistentState ids s)
crucPStateLens = lens crucPState (\s v -> s { crucPState = v })
toBitsCacheLens ::
Simple Lens (CrucGenState arch ids h s) (MapF (PtrAtom s) (BVAtom s))
Simple Lens (CrucGenState arch ids s) (MapF (PtrAtom s) (BVAtom s))
toBitsCacheLens = lens toBitsCache (\s v -> s { toBitsCache = v })
fromBitsCacheLens ::
Simple Lens (CrucGenState arch ids h s) (MapF (BVAtom s) (PtrAtom s))
Simple Lens (CrucGenState arch ids s) (MapF (BVAtom s) (PtrAtom s))
fromBitsCacheLens = lens fromBitsCache (\s v -> s { fromBitsCache = v })
assignValueMapLens ::
Simple Lens (CrucPersistentState ids h s)
Simple Lens (CrucPersistentState ids s)
(MapF (M.AssignId ids) (MacawCrucibleValue (CR.Atom s)))
assignValueMapLens = lens assignValueMap (\s v -> s { assignValueMap = v })
type CrucGenRet arch ids h s = (CrucGenState arch ids h s, CR.TermStmt s (MacawFunctionResult arch))
type CrucGenRet arch ids s = (CrucGenState arch ids s, CR.TermStmt s (MacawFunctionResult arch))
-- | The Crucible generator monad
--
-- This monad provides an environment for constructing Crucible blocks from
-- Macaw blocks, including the translation of values while preserving sharing
-- and the construction of a control flow graph.
newtype CrucGen arch ids h s r
newtype CrucGen arch ids s r
= CrucGen { unCrucGen
:: CrucGenState arch ids h s
-> (CrucGenState arch ids h s
:: CrucGenState arch ids s
-> (CrucGenState arch ids s
-> r
-> ST h (CrucGenRet arch ids h s))
-> ST h (CrucGenRet arch ids h s)
-> IO (CrucGenRet arch ids s))
-> IO (CrucGenRet arch ids s)
}
instance Functor (CrucGen arch ids h s) where
instance Functor (CrucGen arch ids s) where
{-# INLINE fmap #-}
fmap f m = CrucGen $ \s0 cont -> unCrucGen m s0 $ \s1 v -> cont s1 (f v)
instance Applicative (CrucGen arch ids h s) where
instance Applicative (CrucGen arch ids s) where
{-# INLINE pure #-}
pure !r = CrucGen $ \s cont -> cont s r
{-# INLINE (<*>) #-}
@ -667,26 +666,26 @@ instance Applicative (CrucGen arch ids h s) where
$ \s1 f -> unCrucGen ma s1
$ \s2 a -> cont s2 (f a)
instance Monad (CrucGen arch ids h s) where
instance Monad (CrucGen arch ids s) where
{-# INLINE (>>=) #-}
m >>= h = CrucGen $ \s0 cont -> unCrucGen m s0 $ \s1 r -> unCrucGen (h r) s1 cont
instance MonadState (CrucGenState arch ids h s) (CrucGen arch ids h s) where
instance MonadState (CrucGenState arch ids s) (CrucGen arch ids s) where
get = CrucGen $ \s cont -> cont s s
put s = CrucGen $ \_ cont -> cont s ()
cgExecST :: ST h a -> CrucGen arch ids h s a
cgExecST :: IO a -> CrucGen arch ids s a
cgExecST m = CrucGen $ \s cont -> m >>= cont s
-- | A NatRepr corresponding to the architecture width.
archAddrWidth :: CrucGen arch ids h s (ArchAddrWidthRepr arch)
archAddrWidth :: CrucGen arch ids s (ArchAddrWidthRepr arch)
archAddrWidth = crucGenAddrWidth . translateFns <$> get
-- | Get current position
getPos :: CrucGen arch ids h s C.Position
getPos :: CrucGen arch ids s C.Position
getPos = gets codePos
addStmt :: CR.Stmt (MacawExt arch) s -> CrucGen arch ids h s ()
addStmt :: CR.Stmt (MacawExt arch) s -> CrucGen arch ids s ()
addStmt stmt = seq stmt $ do
p <- getPos
s <- get
@ -696,7 +695,7 @@ addStmt stmt = seq stmt $ do
put $! s { prevStmts = pstmt : prev }
addTermStmt :: CR.TermStmt s (MacawFunctionResult arch)
-> CrucGen arch ids h s a
-> CrucGen arch ids s a
addTermStmt tstmt = do
CrucGen $ \s _ -> pure (s, tstmt)
{-
@ -714,27 +713,27 @@ addTermStmt tstmt = do
-- Support a friendlier API such as that of Crucible's Generator
-- monad.)
addExtraBlock :: CR.Block (MacawExt arch) s (MacawFunctionResult arch)
-> CrucGen arch ids h s ()
-> CrucGen arch ids s ()
addExtraBlock blk =
modify' $ \s@(CrucGenState { extraBlocks = blks }) ->
s { extraBlocks = blk : blks }
freshValueIndex :: CrucGen arch ids h s (Nonce s tp)
freshValueIndex :: CrucGen arch ids s (Nonce s tp)
freshValueIndex = do
s <- get
let ps = crucPState s
let ng = nonceGen ps
cgExecST $ freshNonce ng
mmNonceGenerator :: MacawMonad arch ids h s (NonceGenerator (ST h) s)
mmNonceGenerator :: MacawMonad arch ids s (NonceGenerator IO s)
mmNonceGenerator = gets nonceGen
mmFreshNonce :: MacawMonad arch ids h s (Nonce s tp)
mmFreshNonce :: MacawMonad arch ids s (Nonce s tp)
mmFreshNonce = do
ng <- gets nonceGen
mmExecST $ freshNonce ng
mkAtom :: C.TypeRepr ctp -> CrucGen arch ids h s (CR.Atom s ctp)
mkAtom :: C.TypeRepr ctp -> CrucGen arch ids s (CR.Atom s ctp)
mkAtom tp = do
archFns <- gets translateFns
crucGenArchConstraints archFns $ do
@ -749,7 +748,7 @@ mkAtom tp = do
pure $! atom
-- | Evaluate the crucible app and return a reference to the result.
evalAtom :: CR.AtomValue (MacawExt arch) s ctp -> CrucGen arch ids h s (CR.Atom s ctp)
evalAtom :: CR.AtomValue (MacawExt arch) s ctp -> CrucGen arch ids s (CR.Atom s ctp)
evalAtom av = do
archFns <- gets translateFns
crucGenArchConstraints archFns $ do
@ -758,11 +757,11 @@ evalAtom av = do
pure atom
-- | Evaluate the crucible app and return a reference to the result.
crucibleValue :: C.App (MacawExt arch) (CR.Atom s) ctp -> CrucGen arch ids h s (CR.Atom s ctp)
crucibleValue :: C.App (MacawExt arch) (CR.Atom s) ctp -> CrucGen arch ids s (CR.Atom s ctp)
crucibleValue = evalAtom . CR.EvalApp
-- | Evaluate a Macaw expression extension
evalMacawExt :: MacawExprExtension arch (CR.Atom s) tp -> CrucGen arch ids h s (CR.Atom s tp)
evalMacawExt :: MacawExprExtension arch (CR.Atom s) tp -> CrucGen arch ids s (CR.Atom s tp)
evalMacawExt = crucibleValue . C.ExtensionApp
-- | Treat a register value as a bit-vector.
@ -770,7 +769,7 @@ toBits ::
(1 <= w) =>
NatRepr w ->
CR.Atom s (MM.LLVMPointerType w) ->
CrucGen arch ids h s (CR.Atom s (C.BVType w))
CrucGen arch ids s (CR.Atom s (C.BVType w))
toBits w x =
use (toBitsCacheLens . atF (PtrAtom x)) >>= \case
Just (BVAtom x') ->
@ -786,7 +785,7 @@ fromBits ::
(1 <= w) =>
NatRepr w ->
CR.Atom s (C.BVType w) ->
CrucGen arch ids h s (CR.Atom s (MM.LLVMPointerType w))
CrucGen arch ids s (CR.Atom s (MM.LLVMPointerType w))
fromBits w x =
use (fromBitsCacheLens . atF (BVAtom x)) >>= \case
Just (PtrAtom x') ->
@ -797,12 +796,12 @@ fromBits w x =
assign (toBitsCacheLens . atF (PtrAtom x')) (Just (BVAtom x))
return x'
getRegs :: CrucGen arch ids h s (CR.Atom s (ArchRegStruct arch))
getRegs :: CrucGen arch ids s (CR.Atom s (ArchRegStruct arch))
getRegs = gets crucRegisterReg >>= evalAtom . CR.ReadReg
-- | Return the value associated with the given register
getRegValue :: M.ArchReg arch tp
-> CrucGen arch ids h s (CR.Atom s (ToCrucibleType tp))
-> CrucGen arch ids s (CR.Atom s (ToCrucibleType tp))
getRegValue r = do
archFns <- gets translateFns
idxMap <- gets crucRegIndexMap
@ -816,25 +815,25 @@ getRegValue r = do
crucibleValue (C.GetStruct regStruct (crucibleIndex idx) tp)
v2c :: M.Value arch ids tp
-> CrucGen arch ids h s (CR.Atom s (ToCrucibleType tp))
-> CrucGen arch ids s (CR.Atom s (ToCrucibleType tp))
v2c = valueToCrucible
v2c' :: (1 <= w) =>
NatRepr w ->
M.Value arch ids (M.BVType w) ->
CrucGen arch ids h s (CR.Atom s (C.BVType w))
CrucGen arch ids s (CR.Atom s (C.BVType w))
v2c' w x = toBits w =<< valueToCrucible x
-- | Evaluate the crucible app and return a reference to the result.
appAtom :: C.App (MacawExt arch) (CR.Atom s) ctp ->
CrucGen arch ids h s (CR.Atom s ctp)
CrucGen arch ids s (CR.Atom s ctp)
appAtom app = evalAtom (CR.EvalApp app)
appBVAtom ::
(1 <= w) =>
NatRepr w ->
C.App (MacawExt arch) (CR.Atom s) (C.BVType w) ->
CrucGen arch ids h s (CR.Atom s (MM.LLVMPointerType w))
CrucGen arch ids s (CR.Atom s (MM.LLVMPointerType w))
appBVAtom w app = fromBits w =<< appAtom app
addLemma :: (1 <= x, x + 1 <= y) => NatRepr x -> q y -> LeqProof 1 y
@ -848,7 +847,7 @@ addLemma x y =
-- | Create a crucible value for a bitvector literal.
bvLit :: (1 <= w) => NatRepr w -> Integer -> CrucGen arch ids h s (CR.Atom s (C.BVType w))
bvLit :: (1 <= w) => NatRepr w -> Integer -> CrucGen arch ids s (CR.Atom s (C.BVType w))
bvLit w i = crucibleValue (C.BVLit w (i .&. maxUnsigned w))
bitOp2 :: (1 <= w)
@ -858,14 +857,14 @@ bitOp2 :: (1 <= w)
-> C.App (MacawExt arch) (CR.Atom s) (C.BVType w))
-> M.Value arch ids (M.BVType w)
-> M.Value arch ids (M.BVType w)
-> CrucGen arch ids h s (CR.Atom s (MM.LLVMPointerType w))
-> CrucGen arch ids s (CR.Atom s (MM.LLVMPointerType w))
bitOp2 w f x y = fromBits w =<< appAtom =<< f <$> v2c' w x <*> v2c' w y
appToCrucible
:: forall arch ids h s tp
:: forall arch ids s tp
. M.App (M.Value arch ids) tp
-> CrucGen arch ids h s (CR.Atom s (ToCrucibleType tp))
-> CrucGen arch ids s (CR.Atom s (ToCrucibleType tp))
appToCrucible app = do
archFns <- gets translateFns
crucGenArchConstraints archFns $ do
@ -1050,7 +1049,7 @@ appToCrucible app = do
let bvBit
:: (1 <= i, i <= n)
=> NatRepr i
-> CrucGen arch ids h s (CR.Atom s (C.BVType n))
-> CrucGen arch ids s (CR.Atom s (C.BVType n))
bvBit i | Refl <- minusPlusCancel i (knownNat @1) = do
b <- appAtom $
C.BVSelect (subNat i (knownNat @1)) (knownNat @1) w x'
@ -1094,7 +1093,7 @@ countZeros :: (1 <= w) =>
NatRepr w ->
(NatRepr w -> CR.Atom s (C.BVType w) -> CR.Atom s (C.BVType w) -> C.App (MacawExt arch) (CR.Atom s) (C.BVType w)) ->
M.Value arch ids (M.BVType w) ->
CrucGen arch ids h s (CR.Atom s (MM.LLVMPointerType w))
CrucGen arch ids s (CR.Atom s (MM.LLVMPointerType w))
countZeros w f vx = do
cx <- v2c vx >>= toBits w
isZeros <- forM [0..intValue w-1] $ \i -> do
@ -1111,7 +1110,7 @@ countZeros w f vx = do
--
-- This is in the 'CrucGen' monad so that it can preserve sharing in terms.
valueToCrucible :: M.Value arch ids tp
-> CrucGen arch ids h s (CR.Atom s (ToCrucibleType tp))
-> CrucGen arch ids s (CR.Atom s (ToCrucibleType tp))
valueToCrucible v = do
archFns <- gets translateFns
crucGenArchConstraints archFns $ do
@ -1138,21 +1137,21 @@ valueToCrucible v = do
-- | Create a fresh symbolic value of the given type.
freshSymbolic :: M.TypeRepr tp
-> CrucGen arch ids h s (CR.Atom s (ToCrucibleType tp))
-> CrucGen arch ids s (CR.Atom s (ToCrucibleType tp))
freshSymbolic repr = evalMacawStmt (MacawFreshSymbolic repr)
evalMacawStmt :: MacawStmtExtension arch (CR.Atom s) tp ->
CrucGen arch ids h s (CR.Atom s tp)
CrucGen arch ids s (CR.Atom s tp)
evalMacawStmt = evalAtom . CR.EvalExt
-- | Embed an architecture-specific Macaw statement into a Crucible program
--
-- All architecture-specific statements return values (which can be unit).
evalArchStmt :: MacawArchStmtExtension arch (CR.Atom s) tp -> CrucGen arch ids h s (CR.Atom s tp)
evalArchStmt :: MacawArchStmtExtension arch (CR.Atom s) tp -> CrucGen arch ids s (CR.Atom s tp)
evalArchStmt = evalMacawStmt . MacawArchStmtExtension
assignRhsToCrucible :: M.AssignRhs arch (M.Value arch ids) tp
-> CrucGen arch ids h s (CR.Atom s (ToCrucibleType tp))
-> CrucGen arch ids s (CR.Atom s (ToCrucibleType tp))
assignRhsToCrucible rhs =
gets translateFns >>= \archFns ->
crucGenArchConstraints archFns $
@ -1173,7 +1172,7 @@ assignRhsToCrucible rhs =
fns <- translateFns <$> get
crucGenArchFn fns f
addMacawStmt :: forall arch ids h s . M.ArchSegmentOff arch -> M.Stmt arch ids -> CrucGen arch ids h s ()
addMacawStmt :: forall arch ids s . M.ArchSegmentOff arch -> M.Stmt arch ids -> CrucGen arch ids s ()
addMacawStmt baddr stmt =
gets translateFns >>= \archFns ->
crucGenArchConstraints archFns $
@ -1213,9 +1212,9 @@ addMacawStmt baddr stmt =
void $ evalMacawStmt crucStmt
-- | Create a crucible struct for registers from a register state.
createRegStruct :: forall arch ids h s
createRegStruct :: forall arch ids s
. M.RegState (M.ArchReg arch) (M.Value arch ids)
-> CrucGen arch ids h s (CR.Atom s (ArchRegStruct arch))
-> CrucGen arch ids s (CR.Atom s (ArchRegStruct arch))
createRegStruct regs = do
archFns <- gets translateFns
@ -1233,9 +1232,9 @@ createRegStruct regs = do
updates <- createRegUpdates regs
foldM addUpdate startingVals updates
createRegUpdates :: forall arch ids h s
createRegUpdates :: forall arch ids s
. M.RegState (M.ArchReg arch) (M.Value arch ids)
-> CrucGen arch ids h s
-> CrucGen arch ids s
[Pair (Ctx.Index (MacawCrucibleRegTypes arch)) (CR.Atom s)]
createRegUpdates regs = do
archFns <- gets translateFns
@ -1249,7 +1248,7 @@ createRegUpdates regs = do
Just idx -> Just . Pair (crucibleIndex idx) <$> valueToCrucible val
addMacawTermStmt :: M.TermStmt arch ids
-> CrucGen arch ids h s ()
-> CrucGen arch ids s ()
addMacawTermStmt tstmt =
case tstmt of
M.FetchAndExecute regs -> do
@ -1265,24 +1264,24 @@ addMacawTermStmt tstmt =
-----------------
-- | Monad for adding new blocks to a state.
newtype MacawMonad arch ids h s a
= MacawMonad ( ExceptT String (StateT (CrucPersistentState ids h s) (ST h)) a)
newtype MacawMonad arch ids s a
= MacawMonad ( ExceptT String (StateT (CrucPersistentState ids s) IO) a)
deriving ( Functor
, Applicative
, Monad
, MonadError String
, MonadState (CrucPersistentState ids h s)
, MonadState (CrucPersistentState ids s)
)
runMacawMonad :: CrucPersistentState ids h s
-> MacawMonad arch ids h s a
-> ST h (Either String a, CrucPersistentState ids h s)
runMacawMonad :: CrucPersistentState ids s
-> MacawMonad arch ids s a
-> IO (Either String a, CrucPersistentState ids s)
runMacawMonad s (MacawMonad m) = runStateT (runExceptT m) s
mmExecST :: ST h a -> MacawMonad arch ids h s a
mmExecST :: IO a -> MacawMonad arch ids s a
mmExecST = MacawMonad . lift . lift
runCrucGen :: forall arch ids h s
runCrucGen :: forall arch ids s
. MacawSymbolicArchFunctions arch
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Base address map
@ -1292,8 +1291,8 @@ runCrucGen :: forall arch ids h s
-- ^ Label for this block
-> CR.Reg s (ArchRegStruct arch)
-- ^ Crucible register for struct containing all Macaw registers.
-> CrucGen arch ids h s ()
-> MacawMonad arch ids h s
-> CrucGen arch ids s ()
-> MacawMonad arch ids s
( CR.Block (MacawExt arch ) s (MacawFunctionResult arch)
-- Block created
, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)]
@ -1338,7 +1337,7 @@ addMacawBlock :: M.MemWidth (M.ArchAddrWidth arch)
-> (M.ArchAddrWord arch -> C.Position)
-- ^ Function for generating position from offset from start of this block.
-> M.Block arch ids
-> MacawMonad arch ids h s
-> MacawMonad arch ids s
( CR.Block (MacawExt arch) s (MacawFunctionResult arch)
, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)]
)
@ -1372,7 +1371,7 @@ parsedBlockLabel blockLabelMap addr =
-- | DO NOT CALL THIS FROM USER CODE. We count on the registers not
-- changing until the end of the block.
setMachineRegs :: CR.Atom s (ArchRegStruct arch) -> CrucGen arch ids h s ()
setMachineRegs :: CR.Atom s (ArchRegStruct arch) -> CrucGen arch ids s ()
setMachineRegs newRegs = do
regReg <- gets crucRegisterReg
addStmt $ CR.SetReg regReg newRegs
@ -1385,7 +1384,7 @@ addMacawParsedTermStmt :: BlockLabelMap arch s
-> M.ArchSegmentOff arch
-- ^ Address of this block
-> M.ParsedTermStmt arch ids
-> CrucGen arch ids h s ()
-> CrucGen arch ids s ()
addMacawParsedTermStmt blockLabelMap thisAddr tstmt = do
archFns <- translateFns <$> get
crucGenArchConstraints archFns $ do
@ -1435,11 +1434,11 @@ addMacawParsedTermStmt blockLabelMap thisAddr tstmt = do
msgVal <- crucibleValue $ C.TextLit $ Text.pack $ "Could not identify block at " ++ show thisAddr
addTermStmt $ CR.ErrorStmt msgVal
addSwitch :: forall arch s ids h
addSwitch :: forall arch s ids
. BlockLabelMap arch s
-> M.ArchAddrValue arch ids
-> Vec.Vector (M.ArchSegmentOff arch)
-> CrucGen arch ids h s ()
-> CrucGen arch ids s ()
addSwitch blockLabelMap idx possibleAddrs = do
archFns <- translateFns <$> get
crucGenArchConstraints archFns $ do
@ -1468,7 +1467,7 @@ addSwitch blockLabelMap idx possibleAddrs = do
, CR.TermStmt s (MacawFunctionResult arch) )
-> ( Int
, M.ArchSegmentOff arch )
-> CrucGen arch ids h s
-> CrucGen arch ids s
( [CR.Stmt (MacawExt arch) s]
, CR.TermStmt s (MacawFunctionResult arch) )
chain (elsStmts, elsTerm) (thnIdx, thnAddr) = do
@ -1524,7 +1523,7 @@ addSwitch blockLabelMap idx possibleAddrs = do
mapM_ addStmt stmts
addTermStmt termStmt
addParsedBlock :: forall arch ids h s
addParsedBlock :: forall arch ids s
. MacawSymbolicArchFunctions arch
-> MemSegmentMap (M.ArchAddrWidth arch)
-- ^ Base address map
@ -1535,7 +1534,7 @@ addParsedBlock :: forall arch ids h s
-> CR.Reg s (ArchRegStruct arch)
-- ^ Register that stores Macaw registers
-> M.ParsedBlock arch ids
-> MacawMonad arch ids h s [CR.Block (MacawExt arch) s (MacawFunctionResult arch)]
-> MacawMonad arch ids s [CR.Block (MacawExt arch) s (MacawFunctionResult arch)]
addParsedBlock archFns memSegMap blockLabelMap posFn regReg macawBlock = do
crucGenArchConstraints archFns $ do
let base = M.pblockAddr macawBlock

View File

@ -44,7 +44,6 @@ module Data.Macaw.Symbolic.PersistentState
) where
import Control.Monad.ST (ST)
import qualified Data.Kind as K
import qualified Data.Macaw.CFG as M
import qualified Data.Macaw.Types as M
@ -227,9 +226,9 @@ instance TraversableFC MacawCrucibleValue where
-- CrucPersistentState
-- | State that needs to be persisted across block translations
data CrucPersistentState ids h s
data CrucPersistentState ids s
= CrucPersistentState
{ nonceGen :: NonceGenerator (ST h) s
{ nonceGen :: NonceGenerator IO s
-- ^ Generator used to get fresh ids for Crucible atoms.
, assignValueMap ::
!(MapF (M.AssignId ids) (MacawCrucibleValue (CR.Atom s)))
@ -237,8 +236,8 @@ data CrucPersistentState ids h s
}
-- | Initial crucible persistent state
initCrucPersistentState :: NonceGenerator (ST h) s
-> CrucPersistentState ids h s
initCrucPersistentState :: NonceGenerator IO s
-> CrucPersistentState ids s
initCrucPersistentState ng =
CrucPersistentState
{ nonceGen = ng

View File

@ -276,27 +276,27 @@ instance TraversableFC X86StmtExtension where
type instance MacawArchStmtExtension M.X86_64 = X86StmtExtension
crucGenX86Fn :: forall ids h s tp. M.X86PrimFn (M.Value M.X86_64 ids) tp
-> CrucGen M.X86_64 ids h s (C.Atom s (ToCrucibleType tp))
crucGenX86Fn :: forall ids s tp. M.X86PrimFn (M.Value M.X86_64 ids) tp
-> CrucGen M.X86_64 ids s (C.Atom s (ToCrucibleType tp))
crucGenX86Fn fn = do
let f :: M.Value arch ids a -> CrucGen arch ids h s (AtomWrapper (C.Atom s) a)
let f :: M.Value arch ids a -> CrucGen arch ids s (AtomWrapper (C.Atom s) a)
f x = AtomWrapper <$> valueToCrucible x
r <- traverseFC f fn
evalArchStmt (X86PrimFn r)
crucGenX86Stmt :: forall ids h s
crucGenX86Stmt :: forall ids s
. M.X86Stmt (M.Value M.X86_64 ids)
-> CrucGen M.X86_64 ids h s ()
-> CrucGen M.X86_64 ids s ()
crucGenX86Stmt stmt = do
let f :: M.Value M.X86_64 ids a -> CrucGen M.X86_64 ids h s (AtomWrapper (C.Atom s) a)
let f :: M.Value M.X86_64 ids a -> CrucGen M.X86_64 ids s (AtomWrapper (C.Atom s) a)
f x = AtomWrapper <$> valueToCrucible x
stmt' <- traverseF f stmt
void (evalArchStmt (X86PrimStmt stmt'))
crucGenX86TermStmt :: M.X86TermStmt ids
-> M.RegState M.X86Reg (M.Value M.X86_64 ids)
-> CrucGen M.X86_64 ids h s ()
-> CrucGen M.X86_64 ids s ()
crucGenX86TermStmt tstmt _regs =
void (evalArchStmt (X86PrimTerm tstmt))

View File

@ -95,7 +95,7 @@ main = do
[] -> fail "Could not find add function"
_ -> fail "Found multiple add functions"
memBaseVar <- stToIO $ C.freshGlobalVar halloc "add_mem_base" C.knownRepr
memBaseVar <- C.freshGlobalVar halloc "add_mem_base" C.knownRepr
let memBaseVarMap :: MS.MemSegmentMap 64
memBaseVarMap = Map.singleton 1 memBaseVar
@ -113,7 +113,7 @@ main = do
putStrLn $ "Analyzing " ++ show addr
(_, Some funInfo) <- stToIO $ M.analyzeFunction logFn addAddr M.UserRequest ds0
C.SomeCFG g <- stToIO $ MS.mkFunCFG x86ArchFns halloc memBaseVarMap "add" posFn funInfo
C.SomeCFG g <- MS.mkFunCFG x86ArchFns halloc memBaseVarMap "add" posFn funInfo
regs <- MS.macawAssignToCrucM (mkReg x86ArchFns sym) (MS.crucGenRegAssignment x86ArchFns)