Drop support for branches within blocks.

This commit is contained in:
Joe Hendrix 2019-04-28 13:19:20 -07:00
parent f8c43540c1
commit 3331a19571
No known key found for this signature in database
GPG Key ID: 8DFA5FF784098C4F
10 changed files with 98 additions and 242 deletions

View File

@ -28,8 +28,7 @@ install:
# Here starts the actual work to be performed for the package under test; # Here starts the actual work to be performed for the package under test;
# any command which exits with a non-zero exit code causes the build to fail. # any command which exits with a non-zero exit code causes the build to fail.
script: # Build packages that we do not want to check warnings on.
# Build crucible with no -Werror
- stack build crucible - stack build crucible
# Build packages # Build packages
- stack build --ghc-options="-Wall -Werror" - stack build --ghc-options="-Wall -Werror"

View File

@ -1,5 +1,5 @@
name: macaw-base name: macaw-base
version: 0.3.5 version: 0.3.6
author: Galois, Inc. author: Galois, Inc.
maintainer: jhendrix@galois.com maintainer: jhendrix@galois.com
build-type: Simple build-type: Simple

View File

@ -1,7 +1,4 @@
{-| {-|
Copyright : (c) Galois, Inc 2016
Maintainer : jhendrix@galois.com
This defines the architecture-specific information needed for code discovery. This defines the architecture-specific information needed for code discovery.
-} -}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
@ -19,11 +16,9 @@ module Data.Macaw.Architecture.Info
import Control.Monad.ST import Control.Monad.ST
import Data.Parameterized.Nonce import Data.Parameterized.Nonce
import Data.Parameterized.TraversableF import Data.Parameterized.TraversableF
import Data.Semigroup ( (<>) )
import Data.Sequence (Seq) import Data.Sequence (Seq)
import Data.Macaw.AbsDomain.AbsState as AbsState import Data.Macaw.AbsDomain.AbsState as AbsState
import Data.Macaw.CFG.App
import Data.Macaw.CFG.Block import Data.Macaw.CFG.Block
import Data.Macaw.CFG.Core import Data.Macaw.CFG.Core
import Data.Macaw.CFG.DemandSet import Data.Macaw.CFG.DemandSet
@ -51,7 +46,7 @@ type DisassembleFn arch
-- ^ Initial values to use for registers. -- ^ Initial values to use for registers.
-> Int -> Int
-- ^ Maximum offset for this to read from. -- ^ Maximum offset for this to read from.
-> ST s ([Block arch ids], Int, Maybe String) -> ST s (Block arch ids, Int)
-- | This records architecture specific functions for analysis. -- | This records architecture specific functions for analysis.
data ArchitectureInfo arch data ArchitectureInfo arch
@ -174,13 +169,6 @@ rewriteTermStmt info tstmt = do
case tstmt of case tstmt of
FetchAndExecute regs -> FetchAndExecute regs ->
FetchAndExecute <$> traverseF rewriteValue regs FetchAndExecute <$> traverseF rewriteValue regs
Branch c t f -> do
tgtCond <- rewriteValue c
case () of
_ | Just (NotApp cn) <- valueAsApp tgtCond -> do
pure $ Branch cn f t
| otherwise ->
pure $ Branch tgtCond t f
TranslateError regs msg -> TranslateError regs msg ->
TranslateError <$> traverseF rewriteValue regs TranslateError <$> traverseF rewriteValue regs
<*> pure msg <*> pure msg
@ -190,16 +178,15 @@ rewriteTermStmt info tstmt = do
-- | Apply optimizations to code in the block -- | Apply optimizations to code in the block
rewriteBlock :: ArchitectureInfo arch rewriteBlock :: ArchitectureInfo arch
-> (RewriteContext arch s src tgt, [Block arch tgt]) -> RewriteContext arch s src tgt
-> Block arch src -> Block arch src
-> ST s (RewriteContext arch s src tgt, [Block arch tgt]) -> ST s (RewriteContext arch s src tgt, Block arch tgt)
rewriteBlock info (rwctx,blks) b = do rewriteBlock info rwctx b = do
(rwctx', newBlks, tgtStmts, tgtTermStmt) <- runRewriter rwctx $ do (rwctx', tgtStmts, tgtTermStmt) <- runRewriter rwctx $ do
mapM_ rewriteStmt (blockStmts b) mapM_ rewriteStmt (blockStmts b)
rewriteTermStmt info (blockTerm b) rewriteTermStmt info (blockTerm b)
-- Return rewritten block and any new blocks -- Return rewritten block and any new blocks
let rwBlock = Block { blockLabel = blockLabel b let rwBlock = Block { blockStmts = tgtStmts
, blockStmts = tgtStmts
, blockTerm = tgtTermStmt , blockTerm = tgtTermStmt
} }
in pure (rwctx', rwBlock : (newBlks <> blks)) pure (rwctx', rwBlock)

View File

@ -9,18 +9,16 @@ types.
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
module Data.Macaw.CFG.Block module Data.Macaw.CFG.Block
( Block(..), BlockLabel ( Block(..)
, ppBlock , ppBlock
, TermStmt(..) , TermStmt(..)
) where ) where
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as Text import qualified Data.Text as Text
import Data.Word
import Text.PrettyPrint.ANSI.Leijen as PP hiding ((<$>)) import Text.PrettyPrint.ANSI.Leijen as PP hiding ((<$>))
import Data.Macaw.CFG.Core import Data.Macaw.CFG.Core
import Data.Macaw.Types
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- TermStmt -- TermStmt
@ -32,8 +30,6 @@ import Data.Macaw.Types
data TermStmt arch ids data TermStmt arch ids
-- | Fetch and execute the next instruction from the given processor state. -- | Fetch and execute the next instruction from the given processor state.
= FetchAndExecute !(RegState (ArchReg arch) (Value arch ids)) = FetchAndExecute !(RegState (ArchReg arch) (Value arch ids))
-- | Branch and execute one block or another.
| Branch !(Value arch ids BoolType) !BlockLabel !BlockLabel
-- | The block ended prematurely due to an error in instruction -- | The block ended prematurely due to an error in instruction
-- decoding or translation. -- decoding or translation.
-- --
@ -52,8 +48,6 @@ instance ArchConstraints arch
pretty (FetchAndExecute s) = pretty (FetchAndExecute s) =
text "fetch_and_execute" <$$> text "fetch_and_execute" <$$>
indent 2 (pretty s) indent 2 (pretty s)
pretty (Branch c x y) =
text "branch" <+> ppValue 0 c <+> text (show x) <+> text (show y)
pretty (TranslateError s msg) = pretty (TranslateError s msg) =
text "ERROR: " <+> text (Text.unpack msg) <$$> text "ERROR: " <+> text (Text.unpack msg) <$$>
indent 2 (pretty s) indent 2 (pretty s)
@ -63,22 +57,15 @@ instance ArchConstraints arch
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- Block -- Block
-- | The type of labels for each block
type BlockLabel = Word64
-- | The type for code blocks returned by the disassembler. -- | The type for code blocks returned by the disassembler.
-- --
-- The discovery process will attempt to map each block to a suitable ParsedBlock. -- The discovery process will attempt to map each block to a suitable ParsedBlock.
data Block arch ids data Block arch ids
= Block { blockLabel :: !BlockLabel = Block { blockStmts :: !([Stmt arch ids])
-- ^ Index of this block
, blockStmts :: !([Stmt arch ids])
-- ^ List of statements in the block. -- ^ List of statements in the block.
, blockTerm :: !(TermStmt arch ids) , blockTerm :: !(TermStmt arch ids)
-- ^ The last statement in the block. -- ^ The last statement in the block.
} }
ppBlock :: ArchConstraints arch => Block arch ids -> Doc ppBlock :: ArchConstraints arch => Block arch ids -> Doc
ppBlock b = ppBlock b = vcat (ppStmt (text . show) <$> blockStmts b) <$$> pretty (blockTerm b)
text (show (blockLabel b)) PP.<> text ":" <$$>
indent 2 (vcat (ppStmt (text . show) <$> blockStmts b) <$$> pretty (blockTerm b))

View File

@ -31,7 +31,6 @@ module Data.Macaw.CFG.Rewriter
, rewriteApp , rewriteApp
, evalRewrittenArchFn , evalRewrittenArchFn
, appendRewrittenArchStmt , appendRewrittenArchStmt
, addNewBlockFromRewrite
) where ) where
import Control.Lens import Control.Lens
@ -51,7 +50,7 @@ import Data.STRef
import Data.Macaw.CFG import Data.Macaw.CFG
import Data.Macaw.Types import Data.Macaw.Types
import Data.Macaw.CFG.Block ( TermStmt, Block(..), BlockLabel ) import Data.Macaw.CFG.Block (TermStmt)
-- | Information needed for rewriting. -- | Information needed for rewriting.
data RewriteContext arch s src tgt data RewriteContext arch s src tgt
@ -90,11 +89,6 @@ data RewriteContext arch s src tgt
-- of the assignments can be eliminated this -- of the assignments can be eliminated this
-- should be done via a dead code elimination step -- should be done via a dead code elimination step
-- rather than during rewriting. -- rather than during rewriting.
, rwctxBlockLabel :: BlockLabel
-- ^ The next assignable BlockLabel (used for
-- rewrites that create new blocks, as would be
-- needed for Branch TermStmts.
} }
mkRewriteContext :: RegisterInfo (ArchReg arch) mkRewriteContext :: RegisterInfo (ArchReg arch)
@ -112,10 +106,8 @@ mkRewriteContext :: RegisterInfo (ArchReg arch)
-- Discovery.hs. -- Discovery.hs.
-> Map SectionIndex (ArchSegmentOff arch) -> Map SectionIndex (ArchSegmentOff arch)
-- ^ Map from loaded section indices to their address. -- ^ Map from loaded section indices to their address.
-> BlockLabel
-- ^ next BlockLabel (useable for creating new Block entries)
-> ST s (RewriteContext arch s src tgt) -> ST s (RewriteContext arch s src tgt)
mkRewriteContext nonceGen archFn archStmt termStmt secAddrMap nextBlockLabel = do mkRewriteContext nonceGen archFn archStmt termStmt secAddrMap = do
ref <- newSTRef MapF.empty ref <- newSTRef MapF.empty
pure $! RewriteContext { rwctxNonceGen = nonceGen pure $! RewriteContext { rwctxNonceGen = nonceGen
, rwctxArchFn = archFn , rwctxArchFn = archFn
@ -124,7 +116,6 @@ mkRewriteContext nonceGen archFn archStmt termStmt secAddrMap nextBlockLabel = d
, rwctxConstraints = \a -> a , rwctxConstraints = \a -> a
, rwctxSectionAddrMap = secAddrMap , rwctxSectionAddrMap = secAddrMap
, rwctxCache = ref , rwctxCache = ref
, rwctxBlockLabel = nextBlockLabel
} }
-- | State used by rewriter for tracking states -- | State used by rewriter for tracking states
@ -132,21 +123,12 @@ data RewriteState arch s src tgt
= RewriteState { -- | Access to the context for the rewriter = RewriteState { -- | Access to the context for the rewriter
rwContext :: !(RewriteContext arch s src tgt) rwContext :: !(RewriteContext arch s src tgt)
, _rwRevStmts :: ![Stmt arch tgt] , _rwRevStmts :: ![Stmt arch tgt]
, _rwNewBlocks :: ![Block arch tgt]
} }
-- | A list of statements in the current block in reverse order. -- | A list of statements in the current block in reverse order.
rwRevStmts :: Simple Lens (RewriteState arch s src tgt) [Stmt arch tgt] rwRevStmts :: Simple Lens (RewriteState arch s src tgt) [Stmt arch tgt]
rwRevStmts = lens _rwRevStmts (\s v -> s { _rwRevStmts = v }) rwRevStmts = lens _rwRevStmts (\s v -> s { _rwRevStmts = v })
-- | A list of newly created Blocks generated during the rewrite operation.
rwNewBlocks :: Simple Lens (RewriteState arch s src tgt) [Block arch tgt]
rwNewBlocks = lens _rwNewBlocks (\s v -> s { _rwNewBlocks = v })
-- | The next BlockLabel to use for newly created Blocks generated during the rewrite.
rwBlockLabel :: Simple Lens (RewriteState arch s src tgt) BlockLabel
rwBlockLabel = lens (rwctxBlockLabel . rwContext) (\s v -> s { rwContext = (rwContext s) { rwctxBlockLabel = v }})
-- | Monad for constant propagation within a block. -- | Monad for constant propagation within a block.
newtype Rewriter arch s src tgt a = Rewriter { unRewriter :: StateT (RewriteState arch s src tgt) (ST s) a } newtype Rewriter arch s src tgt a = Rewriter { unRewriter :: StateT (RewriteState arch s src tgt) (ST s) a }
deriving (Functor, Applicative, Monad) deriving (Functor, Applicative, Monad)
@ -156,17 +138,15 @@ newtype Rewriter arch s src tgt a = Rewriter { unRewriter :: StateT (RewriteStat
runRewriter :: RewriteContext arch s src tgt runRewriter :: RewriteContext arch s src tgt
-> Rewriter arch s src tgt (TermStmt arch tgt) -> Rewriter arch s src tgt (TermStmt arch tgt)
-> ST s ( RewriteContext arch s src tgt -> ST s ( RewriteContext arch s src tgt
, [Block arch tgt]
, [Stmt arch tgt] , [Stmt arch tgt]
, (TermStmt arch tgt)) , (TermStmt arch tgt))
runRewriter ctx m = do runRewriter ctx m = do
let s = RewriteState { rwContext = ctx let s = RewriteState { rwContext = ctx
, _rwRevStmts = [] , _rwRevStmts = []
, _rwNewBlocks = []
} }
m' = rwctxTermStmt ctx =<< m m' = rwctxTermStmt ctx =<< m
(r, s') <- runStateT (unRewriter m') s (r, s') <- runStateT (unRewriter m') s
pure (rwContext s', _rwNewBlocks s', reverse (_rwRevStmts s'), r) pure (rwContext s', reverse (_rwRevStmts s'), r)
-- | Add a statement to the list -- | Add a statement to the list
appendRewrittenStmt :: Stmt arch tgt -> Rewriter arch s src tgt () appendRewrittenStmt :: Stmt arch tgt -> Rewriter arch s src tgt ()
@ -180,23 +160,6 @@ appendRewrittenStmt stmt = Rewriter $ do
appendRewrittenArchStmt :: ArchStmt arch (Value arch tgt) -> Rewriter arch s src tgt () appendRewrittenArchStmt :: ArchStmt arch (Value arch tgt) -> Rewriter arch s src tgt ()
appendRewrittenArchStmt = appendRewrittenStmt . ExecArchStmt appendRewrittenArchStmt = appendRewrittenStmt . ExecArchStmt
-- | If the rewriting needs to add a new 'Block' (e.g. for a 'Branch'
-- target) it does so by calling this function with that 'Block'.
addNewBlockFromRewrite :: [Stmt arch tgt]
-> TermStmt arch tgt
-> Rewriter arch s src tgt (BlockLabel)
addNewBlockFromRewrite stmts termstmt = Rewriter $ do
blkLabel <- use rwBlockLabel
let blk = Block { blockLabel = blkLabel
, blockStmts = stmts
, blockTerm = termstmt
}
rwNewBlocks %= (:) blk
rwBlockLabel += 1
return blkLabel
-- | Add an assignment statement that evaluates the right hand side and return the resulting value. -- | Add an assignment statement that evaluates the right hand side and return the resulting value.
evalRewrittenRhs :: AssignRhs arch (Value arch tgt) tp -> Rewriter arch s src tgt (Value arch tgt tp) evalRewrittenRhs :: AssignRhs arch (Value arch tgt) tp -> Rewriter arch s src tgt (Value arch tgt tp)
evalRewrittenRhs rhs = Rewriter $ do evalRewrittenRhs rhs = Rewriter $ do

View File

@ -169,8 +169,6 @@ addTermDemands t = do
case t of case t of
FetchAndExecute regs -> do FetchAndExecute regs -> do
traverseF_ addValueDemands regs traverseF_ addValueDemands regs
Branch v _ _ -> do
addValueDemands v
TranslateError regs _ -> do TranslateError regs _ -> do
traverseF_ addValueDemands regs traverseF_ addValueDemands regs
ArchTermStmt _ regs -> do ArchTermStmt _ regs -> do
@ -812,8 +810,6 @@ data ParseContext arch ids =
-- ^ Address of function this block is being parsed as -- ^ Address of function this block is being parsed as
, pctxAddr :: !(ArchSegmentOff arch) , pctxAddr :: !(ArchSegmentOff arch)
-- ^ Address of the current block -- ^ Address of the current block
, pctxBlockMap :: !(Map BlockLabel (Block arch ids))
-- ^ Map from block indices to block code at address.
} }
-- | Get the memory representation associated with pointers in the -- | Get the memory representation associated with pointers in the
@ -1142,30 +1138,6 @@ parseBlock ctx idx initRegs b absProcState = do
let ainfo = pctxArchInfo ctx let ainfo = pctxArchInfo ctx
withArchConstraints ainfo $ do withArchConstraints ainfo $ do
case blockTerm b of case blockTerm b of
Branch c lb rb -> do
let blockMap = pctxBlockMap ctx
-- FIXME: we should propagate c back to the initial block, not just b
let absProcState' = absEvalStmts ainfo absProcState (blockStmts b)
mapM_ (recordWriteStmt ainfo mem absProcState') (blockStmts b)
let Just l = Map.lookup lb blockMap
let l_regs = refineProcStateBounds c True $ refineProcState c absTrue absProcState'
let Just r = Map.lookup rb blockMap
let r_regs = refineProcStateBounds c False $ refineProcState c absFalse absProcState'
let l_regs' = absEvalStmts ainfo l_regs (blockStmts b)
let r_regs' = absEvalStmts ainfo r_regs (blockStmts b)
(parsedTrueBlock,trueIdx) <- parseBlock ctx (idx+1) initRegs l l_regs'
(parsedFalseBlock,falseIdx) <- parseBlock ctx trueIdx initRegs r r_regs'
let ret = StatementList { stmtsIdent = idx
, stmtsNonterm = blockStmts b
, stmtsTerm = ParsedIte c parsedTrueBlock parsedFalseBlock
, stmtsAbsState = absProcState'
}
pure (ret, falseIdx)
FetchAndExecute finalRegs -> do FetchAndExecute finalRegs -> do
parseFetchAndExecute ctx idx initRegs (Seq.fromList (blockStmts b)) absProcState finalRegs parseFetchAndExecute ctx idx initRegs (Seq.fromList (blockStmts b)) absProcState finalRegs
@ -1200,32 +1172,27 @@ parseBlock ctx idx initRegs b absProcState = do
-- | This evaluates the statements in a block to expand the information known -- | This evaluates the statements in a block to expand the information known
-- about control flow targets of this block. -- about control flow targets of this block.
addBlocks :: ArchSegmentOff arch addBlock :: ArchSegmentOff arch
-- ^ Address of these blocks -- ^ Address of these blocks
-> FoundAddr arch -> FoundAddr arch
-- ^ State leading to explore block -- ^ State leading to explore block
-> RegState (ArchReg arch) (Value arch ids) -> RegState (ArchReg arch) (Value arch ids)
-> Int -> Int
-- ^ Number of blocks covered -- ^ Number of bytes in block
-> Map BlockLabel (Block arch ids) -> Block arch ids
-- ^ Map from labelIndex to associated block -- ^ Map from labelIndex to associated block
-> FunM arch s ids () -> FunM arch s ids ()
addBlocks src finfo initRegs sz blockMap = addBlock src finfo initRegs sz b = do
case Map.lookup 0 blockMap of s <- use curFunCtx
Nothing -> do let mem = memory s
error $ "addBlocks given empty blockRegion."
Just b -> do
mem <- uses curFunCtx memory
let regs = initAbsProcessorState mem (foundAbstractState finfo) let regs = initAbsProcessorState mem (foundAbstractState finfo)
funAddr <- gets curFunAddr funAddr <- gets curFunAddr
s <- use curFunCtx
let ctx = ParseContext { pctxMemory = memory s let ctx = ParseContext { pctxMemory = memory s
, pctxArchInfo = archInfo s , pctxArchInfo = archInfo s
, pctxKnownFnEntries = s^.trustedFunctionEntryPoints , pctxKnownFnEntries = s^.trustedFunctionEntryPoints
, pctxFunAddr = funAddr , pctxFunAddr = funAddr
, pctxAddr = src , pctxAddr = src
, pctxBlockMap = blockMap
} }
let ps0 = ParseState { _writtenCodeAddrs = [] let ps0 = ParseState { _writtenCodeAddrs = []
, _intraJumpTargets = [] , _intraJumpTargets = []
@ -1286,30 +1253,22 @@ transfer addr = do
Left msg -> do Left msg -> do
recordErrorBlock addr finfo (Just msg) recordErrorBlock addr finfo (Just msg)
Right initRegs -> do Right initRegs -> do
(bs0, sz, maybeError) <- liftST $ disassembleFn ainfo nonceGen addr initRegs maxSize (b0, sz) <- liftST $ disassembleFn ainfo nonceGen addr initRegs maxSize
-- If no blocks are returned, then we just add an empty parsed block. -- If no blocks are returned, then we just add an empty parsed block.
if null bs0 then do
recordErrorBlock addr finfo maybeError
else do
-- Rewrite returned blocks to simplify expressions -- Rewrite returned blocks to simplify expressions
#ifdef USE_REWRITER #ifdef USE_REWRITER
bs1 <- snd <$> do (_,b) <- do
let archStmt = rewriteArchStmt ainfo let archStmt = rewriteArchStmt ainfo
let secAddrMap = memSectionIndexMap mem let secAddrMap = memSectionIndexMap mem
termStmt <- gets termStmtRewriter <*> pure addr termStmt <- gets termStmtRewriter <*> pure addr
let maxBlockLabel = maximum $ map blockLabel bs0
liftST $ do liftST $ do
ctx <- mkRewriteContext nonceGen (rewriteArchFn ainfo) ctx <- mkRewriteContext nonceGen (rewriteArchFn ainfo) archStmt termStmt secAddrMap
archStmt termStmt secAddrMap (maxBlockLabel + 1) rewriteBlock ainfo ctx b0
foldM (rewriteBlock ainfo) (ctx, []) bs0
#else #else
bs1 <- pure bs0 b <- pure b0
#endif #endif
-- Compute demand set
let bs = bs1 -- eliminateDeadStmts ainfo bs1
-- Call transfer blocks to calculate parsedblocks -- Call transfer blocks to calculate parsedblocks
let blockMap = Map.fromList [ (blockLabel b, b) | b <- bs ] addBlock addr finfo initRegs sz b
addBlocks addr finfo initRegs sz blockMap
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- Main loop -- Main loop

View File

@ -264,22 +264,15 @@ addBlocksCFG :: forall h s arch ids
-- ^ Address of start of block -- ^ Address of start of block
-> (M.ArchAddrWord arch -> C.Position) -> (M.ArchAddrWord arch -> C.Position)
-- ^ Function that maps offsets from start of block to Crucible position. -- ^ Function that maps offsets from start of block to Crucible position.
-> [M.Block arch ids] -> M.Block arch ids
-- ^ List of blocks for this region. -- ^ Macaw block for this region.
-> MacawMonad arch ids h s (CR.Label s, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)]) -> MacawMonad arch ids h s (CR.Label s, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)])
addBlocksCFG archFns baseAddrMap addr posFn macawBlocks = do addBlocksCFG archFns baseAddrMap addr posFn macawBlock = do
crucGenArchConstraints archFns $ do crucGenArchConstraints archFns $ do
-- Map block map to Crucible CFG -- Map block map to Crucible CFG
blockLabelMap <- fmap Map.fromList $ sequence $ entry <- CR.Label <$> mmFreshNonce
[ mmFreshNonce >>= \n -> return (w, CR.Label n) (blk,blks) <- addMacawBlock archFns baseAddrMap addr entry posFn macawBlock
| w <- M.blockLabel <$> macawBlocks ] return (entry, blk:blks)
entry <-
case Map.lookup 0 blockLabelMap of
Just lbl -> return lbl
Nothing -> fail "Unable to find initial block"
blks <- forM macawBlocks $ \b -> do
addMacawBlock archFns baseAddrMap addr blockLabelMap posFn b
return (entry, concatMap (uncurry (:)) blks)
-- | Create a registerized Crucible CFG from an arbitrary list of macaw blocks -- | Create a registerized Crucible CFG from an arbitrary list of macaw blocks
-- --
@ -303,12 +296,12 @@ mkBlocksRegCFG :: forall s arch ids
-- ^ Address for start of block. -- ^ Address for start of block.
-> (M.ArchAddrWord arch -> C.Position) -> (M.ArchAddrWord arch -> C.Position)
-- ^ Function that maps offsets from start of block to Crucible position. -- ^ Function that maps offsets from start of block to Crucible position.
-> [M.Block arch ids] -> M.Block arch ids
-- ^ List of blocks for this region. -- ^ List of blocks for this region.
-> ST s (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch)) -> ST s (CR.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkBlocksRegCFG archFns halloc memBaseVarMap nm addr posFn macawBlocks = do mkBlocksRegCFG archFns halloc memBaseVarMap nm addr posFn macawBlock = do
mkCrucRegCFG archFns halloc nm $ do mkCrucRegCFG archFns halloc nm $ do
addBlocksCFG archFns memBaseVarMap addr posFn macawBlocks addBlocksCFG archFns memBaseVarMap addr posFn macawBlock
-- | Create a Crucible CFG from an arbitrary list of macaw blocks -- | Create a Crucible CFG from an arbitrary list of macaw blocks
-- --
@ -332,12 +325,12 @@ mkBlocksCFG :: forall s arch ids
-- ^ Address for start of block. -- ^ Address for start of block.
-> (M.ArchAddrWord arch -> C.Position) -> (M.ArchAddrWord arch -> C.Position)
-- ^ Function that maps offsets from start of block to Crucible position. -- ^ Function that maps offsets from start of block to Crucible position.
-> [M.Block arch ids] -> M.Block arch ids
-- ^ List of blocks for this region. -- ^ List of blocks for this region.
-> ST s (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch)) -> ST s (C.SomeCFG (MacawExt arch) (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch))
mkBlocksCFG archFns halloc memBaseVarMap nm addr posFn macawBlocks = mkBlocksCFG archFns halloc memBaseVarMap nm addr posFn macawBlock =
toCoreCFG archFns <$> toCoreCFG archFns <$>
mkBlocksRegCFG archFns halloc memBaseVarMap nm addr posFn macawBlocks mkBlocksRegCFG archFns halloc memBaseVarMap nm addr posFn macawBlock
-- | Create a map from Macaw @(address, index)@ pairs to Crucible labels -- | 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 h s (BlockLabelMap arch s)

View File

@ -1215,16 +1215,6 @@ addMacawStmt baddr stmt =
crucStmt = MacawArchStateUpdate addr m crucStmt = MacawArchStateUpdate addr m
void $ evalMacawStmt crucStmt void $ evalMacawStmt crucStmt
lookupCrucibleLabel :: Map Word64 (CR.Label s)
-- ^ Map from block index to Crucible label
-> Word64
-- ^ Index of crucible block
-> CrucGen arch ids h s (CR.Label s)
lookupCrucibleLabel m idx = do
case Map.lookup idx m of
Nothing -> fail $ "Could not find label for block " ++ show idx
Just l -> pure l
-- | Create a crucible struct for registers from a register state. -- | Create a crucible struct for registers from a register state.
createRegStruct :: forall arch ids h s createRegStruct :: forall arch ids h s
. M.RegState (M.ArchReg arch) (M.Value arch ids) . M.RegState (M.ArchReg arch) (M.Value arch ids)
@ -1261,20 +1251,13 @@ createRegUpdates regs = do
Nothing -> fail "internal: Register is not bound." Nothing -> fail "internal: Register is not bound."
Just idx -> Just . Pair (crucibleIndex idx) <$> valueToCrucible val Just idx -> Just . Pair (crucibleIndex idx) <$> valueToCrucible val
addMacawTermStmt :: Map Word64 (CR.Label s) addMacawTermStmt :: M.TermStmt arch ids
-- ^ Map from block index to Crucible label
-> M.TermStmt arch ids
-> CrucGen arch ids h s () -> CrucGen arch ids h s ()
addMacawTermStmt blockLabelMap tstmt = addMacawTermStmt tstmt =
case tstmt of case tstmt of
M.FetchAndExecute regs -> do M.FetchAndExecute regs -> do
s <- createRegStruct regs s <- createRegStruct regs
addTermStmt (CR.Return s) addTermStmt (CR.Return s)
M.Branch macawPred macawTrueLbl macawFalseLbl -> do
p <- valueToCrucible macawPred
t <- lookupCrucibleLabel blockLabelMap macawTrueLbl
f <- lookupCrucibleLabel blockLabelMap macawFalseLbl
addTermStmt (CR.Br p t f)
M.ArchTermStmt ts regs -> do M.ArchTermStmt ts regs -> do
fns <- translateFns <$> get fns <- translateFns <$> get
crucGenArchTermStmt fns ts regs crucGenArchTermStmt fns ts regs
@ -1356,8 +1339,8 @@ addMacawBlock :: M.MemWidth (M.ArchAddrWidth arch)
-- ^ Base address map -- ^ Base address map
-> M.ArchSegmentOff arch -> M.ArchSegmentOff arch
-- ^ Address of start of block -- ^ Address of start of block
-> Map Word64 (CR.Label s) -> CR.Label s
-- ^ Map from block index to Crucible label -- ^ Crucible label for this bloclk.
-> (M.ArchAddrWord arch -> C.Position) -> (M.ArchAddrWord arch -> C.Position)
-- ^ Function for generating position from offset from start of this block. -- ^ Function for generating position from offset from start of this block.
-> M.Block arch ids -> M.Block arch ids
@ -1365,14 +1348,7 @@ addMacawBlock :: M.MemWidth (M.ArchAddrWidth arch)
( CR.Block (MacawExt arch) s (MacawFunctionResult arch) ( CR.Block (MacawExt arch) s (MacawFunctionResult arch)
, [CR.Block (MacawExt arch) s (MacawFunctionResult arch)] , [CR.Block (MacawExt arch) s (MacawFunctionResult arch)]
) )
addMacawBlock archFns baseAddrMap addr blockLabelMap posFn b = do addMacawBlock archFns baseAddrMap addr lbl posFn b = do
let idx = M.blockLabel b
lbl <-
case Map.lookup idx blockLabelMap of
Just lbl ->
pure lbl
Nothing ->
throwError $ "Internal: Could not find block with index " ++ show idx
let archRegStructRepr = C.StructRepr (crucArchRegTypes archFns) let archRegStructRepr = C.StructRepr (crucArchRegTypes archFns)
ng <- gets nonceGen ng <- gets nonceGen
regRegId <- mmExecST $ freshNonce ng regRegId <- mmExecST $ freshNonce ng
@ -1389,7 +1365,7 @@ addMacawBlock archFns baseAddrMap addr blockLabelMap posFn b = do
fmap (\(b', bs, _) -> (b', bs)) $ runCrucGen archFns baseAddrMap posFn 0 lbl regReg $ do fmap (\(b', bs, _) -> (b', bs)) $ runCrucGen archFns baseAddrMap posFn 0 lbl regReg $ do
addStmt $ CR.SetReg regReg regStruct addStmt $ CR.SetReg regReg regStruct
mapM_ (addMacawStmt addr) (M.blockStmts b) mapM_ (addMacawStmt addr) (M.blockStmts b)
addMacawTermStmt blockLabelMap (M.blockTerm b) addMacawTermStmt (M.blockTerm b)
parsedBlockLabel :: (Ord addr, Show addr) parsedBlockLabel :: (Ord addr, Show addr)
=> Map (addr, Word64) (CR.Label s) => Map (addr, Word64) (CR.Label s)

View File

@ -171,13 +171,12 @@ instance MemWidth w => Show (X86TranslateError w) where
initError :: MemSegmentOff 64 -- ^ Location to explore from. initError :: MemSegmentOff 64 -- ^ Location to explore from.
-> RegState X86Reg (Value X86_64 ids) -> RegState X86Reg (Value X86_64 ids)
-> X86TranslateError 64 -> X86TranslateError 64
-> ST st_s (Block X86_64 ids, MemWord 64, Maybe (X86TranslateError 64)) -> ST st_s (Block X86_64 ids, MemWord 64)
initError addr s err = do initError addr s err = do
let b = Block { blockLabel = 0 let b = Block { blockStmts = []
, blockStmts = []
, blockTerm = TranslateError s (Text.pack (show err)) , blockTerm = TranslateError s (Text.pack (show err))
} }
return (b, segoffOffset addr, Just err) return (b, segoffOffset addr)
-- | Disassemble memory contents using flexdis. -- | Disassemble memory contents using flexdis.
disassembleInstruction :: MemSegmentOff 64 disassembleInstruction :: MemSegmentOff 64
@ -312,17 +311,15 @@ translateBlockImpl :: forall st_s ids
-- ^ List of contents to read next. -- ^ List of contents to read next.
-> ST st_s ( Block X86_64 ids -> ST st_s ( Block X86_64 ids
, MemWord 64 , MemWord 64
, Maybe (X86TranslateError 64)
) )
translateBlockImpl gen pblock curIPAddr blockOff maxSize contents = do translateBlockImpl gen pblock curIPAddr blockOff maxSize contents = do
r <- runExceptT $ translateStep gen pblock blockOff curIPAddr contents r <- runExceptT $ translateStep gen pblock blockOff curIPAddr contents
case r of case r of
Left err -> do Left err -> do
let b = Block { blockLabel = pBlockIndex pblock let b = Block { blockStmts = toList (pblock^.pBlockStmts)
, blockStmts = toList (pblock^.pBlockStmts)
, blockTerm = TranslateError (pblock^.pBlockState) (Text.pack (show err)) , blockTerm = TranslateError (pblock^.pBlockState) (Text.pack (show err))
} }
pure (b, blockOff, Just err) pure (b, blockOff)
Right (_, res, instSize, nextIP, nextContents) -> do Right (_, res, instSize, nextIP, nextContents) -> do
let blockOff' = blockOff + fromIntegral instSize let blockOff' = blockOff + fromIntegral instSize
case unfinishedAtAddr res nextIP of case unfinishedAtAddr res nextIP of
@ -331,7 +328,7 @@ translateBlockImpl gen pblock curIPAddr blockOff maxSize contents = do
, Just nextIPSegOff <- incSegmentOff curIPAddr (toInteger instSize) -> do , Just nextIPSegOff <- incSegmentOff curIPAddr (toInteger instSize) -> do
translateBlockImpl gen pblock' nextIPSegOff blockOff' maxSize nextContents translateBlockImpl gen pblock' nextIPSegOff blockOff' maxSize nextContents
_ -> _ ->
pure (finishPartialBlock res, blockOff', Nothing) pure (finishPartialBlock res, blockOff')
{-# DEPRECATED disassembleBlock "Planned for removal." #-} {-# DEPRECATED disassembleBlock "Planned for removal." #-}
@ -342,7 +339,7 @@ disassembleBlock :: forall s
-> ExploreLoc -> ExploreLoc
-> MemWord 64 -> MemWord 64
-- ^ Maximum number of bytes in ths block. -- ^ Maximum number of bytes in ths block.
-> ST s (Block X86_64 s, MemWord 64, Maybe (X86TranslateError 64)) -> ST s (Block X86_64 s, MemWord 64)
disassembleBlock gen loc maxSize = do disassembleBlock gen loc maxSize = do
let addr = loc_ip loc let addr = loc_ip loc
let regs = initX86State loc let regs = initX86State loc
@ -469,13 +466,13 @@ tryDisassembleBlock :: forall s ids
-- ^ Maximum size of this block -- ^ Maximum size of this block
-> ExceptT String (ST s) (Block X86_64 ids, Int, Maybe String) -> ExceptT String (ST s) (Block X86_64 ids, Int, Maybe String)
tryDisassembleBlock gen addr initRegs maxSize = lift $ do tryDisassembleBlock gen addr initRegs maxSize = lift $ do
(b, sz, maybeError) <- (b, sz) <-
case segoffContentsAfter addr of case segoffContentsAfter addr of
Left msg -> do Left msg -> do
initError addr initRegs (FlexdisMemoryError msg) initError addr initRegs (FlexdisMemoryError msg)
Right contents -> do Right contents -> do
translateBlockImpl gen (emptyPreBlock addr initRegs) addr 0 (fromIntegral maxSize) contents translateBlockImpl gen (emptyPreBlock addr initRegs) addr 0 (fromIntegral maxSize) contents
pure $! (b, fromIntegral sz, show <$> maybeError) pure $! (b, fromIntegral sz, Nothing)
-- | Disassemble block, returning either an error, or a list of blocks -- | Disassemble block, returning either an error, or a list of blocks
-- and ending PC. -- and ending PC.
@ -488,15 +485,15 @@ translateBlockWithRegs :: forall s ids
-> Int -> Int
-- ^ Maximum size of this block -- ^ Maximum size of this block
-- ^ Abstract state of processor for defining state. -- ^ Abstract state of processor for defining state.
-> ST s ([Block X86_64 ids], Int, Maybe String) -> ST s (Block X86_64 ids, Int)
translateBlockWithRegs gen addr initRegs maxSize = do translateBlockWithRegs gen addr initRegs maxSize = do
(b, sz, maybeError) <- (b, sz) <-
case segoffContentsAfter addr of case segoffContentsAfter addr of
Left msg -> do Left msg -> do
initError addr initRegs (FlexdisMemoryError msg) initError addr initRegs (FlexdisMemoryError msg)
Right contents -> do Right contents -> do
translateBlockImpl gen (emptyPreBlock addr initRegs) addr 0 (fromIntegral maxSize) contents translateBlockImpl gen (emptyPreBlock addr initRegs) addr 0 (fromIntegral maxSize) contents
pure $! ([b], fromIntegral sz, show <$> maybeError) pure $! (b, fromIntegral sz)
-- | Attempt to identify the write to a stack return address, returning -- | Attempt to identify the write to a stack return address, returning
-- instructions prior to that write and return values. -- instructions prior to that write and return values.

View File

@ -36,7 +36,6 @@ module Data.Macaw.X86.Generator
-- * PreBlock -- * PreBlock
, PreBlock , PreBlock
, emptyPreBlock , emptyPreBlock
, pBlockIndex
, pBlockState , pBlockState
, pBlockStmts , pBlockStmts
, pBlockApps , pBlockApps
@ -87,7 +86,6 @@ import Data.Sequence (Seq)
import qualified Data.Sequence as Seq import qualified Data.Sequence as Seq
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as Text import qualified Data.Text as Text
import Data.Word
import Data.Macaw.X86.ArchTypes import Data.Macaw.X86.ArchTypes
import Data.Macaw.X86.X86Reg import Data.Macaw.X86.X86Reg
@ -153,8 +151,7 @@ asSignedBVLit _ = Nothing
-- PreBlock -- PreBlock
-- | A block that we have not yet finished. -- | A block that we have not yet finished.
data PreBlock ids = PreBlock { pBlockIndex :: !Word64 data PreBlock ids = PreBlock { _pBlockStmts :: !(Seq (Stmt X86_64 ids))
, _pBlockStmts :: !(Seq (Stmt X86_64 ids))
, _pBlockState :: !(RegState X86Reg (Value X86_64 ids)) , _pBlockState :: !(RegState X86Reg (Value X86_64 ids))
, _pBlockApps :: !(MapF (App (Value X86_64 ids)) (Assignment X86_64 ids)) , _pBlockApps :: !(MapF (App (Value X86_64 ids)) (Assignment X86_64 ids))
, pBlockStart :: !(ArchSegmentOff X86_64) , pBlockStart :: !(ArchSegmentOff X86_64)
@ -165,8 +162,7 @@ emptyPreBlock :: ArchSegmentOff X86_64
-> RegState X86Reg (Value X86_64 ids) -> RegState X86Reg (Value X86_64 ids)
-> PreBlock ids -> PreBlock ids
emptyPreBlock startAddr s = emptyPreBlock startAddr s =
PreBlock { pBlockIndex = 0 PreBlock { _pBlockStmts = Seq.empty
, _pBlockStmts = Seq.empty
, _pBlockApps = MapF.empty , _pBlockApps = MapF.empty
, _pBlockState = s , _pBlockState = s
, pBlockStart = startAddr , pBlockStart = startAddr
@ -186,8 +182,7 @@ finishBlock :: PreBlock ids
-> (RegState X86Reg (Value X86_64 ids) -> TermStmt X86_64 ids) -> (RegState X86Reg (Value X86_64 ids) -> TermStmt X86_64 ids)
-> Block X86_64 ids -> Block X86_64 ids
finishBlock preBlock term = finishBlock preBlock term =
Block { blockLabel = pBlockIndex preBlock Block { blockStmts = toList (preBlock^.pBlockStmts)
, blockStmts = toList (preBlock^.pBlockStmts)
, blockTerm = term (preBlock^.pBlockState) , blockTerm = term (preBlock^.pBlockState)
} }