mirror of
https://github.com/GaloisInc/macaw.git
synced 2024-12-25 07:02:59 +03:00
Implement conditional read.
This commit is contained in:
parent
3c2fdeafe4
commit
1c07b88ae7
@ -291,7 +291,7 @@ execMacawStmtExtension ::
|
|||||||
execMacawStmtExtension archStmtFn s0 st =
|
execMacawStmtExtension archStmtFn s0 st =
|
||||||
case s0 of
|
case s0 of
|
||||||
MacawReadMem mvar w mr x -> doReadMem st mvar w mr x
|
MacawReadMem mvar w mr x -> doReadMem st mvar w mr x
|
||||||
MacawCondReadMem{} -> undefined
|
MacawCondReadMem mvar w mr p x d -> doCondReadMem st mvar w mr p x d
|
||||||
MacawWriteMem{} -> undefined
|
MacawWriteMem{} -> undefined
|
||||||
MacawFreshSymbolic{} -> undefined
|
MacawFreshSymbolic{} -> undefined
|
||||||
MacawCall{} -> undefined
|
MacawCall{} -> undefined
|
||||||
|
BIN
symbolic/src/Data/Macaw/Symbolic/.CrucGen.hs.swp
Normal file
BIN
symbolic/src/Data/Macaw/Symbolic/.CrucGen.hs.swp
Normal file
Binary file not shown.
@ -7,6 +7,7 @@
|
|||||||
{-# Language RankNTypes #-}
|
{-# Language RankNTypes #-}
|
||||||
{-# Language PatternSynonyms #-}
|
{-# Language PatternSynonyms #-}
|
||||||
{-# Language TypeApplications #-}
|
{-# Language TypeApplications #-}
|
||||||
|
{-# Language PatternGuards #-}
|
||||||
module Data.Macaw.Symbolic.MemOps
|
module Data.Macaw.Symbolic.MemOps
|
||||||
( PtrOp
|
( PtrOp
|
||||||
, doPtrAdd
|
, doPtrAdd
|
||||||
@ -16,6 +17,7 @@ module Data.Macaw.Symbolic.MemOps
|
|||||||
, doPtrLt
|
, doPtrLt
|
||||||
, doPtrLeq
|
, doPtrLeq
|
||||||
, doReadMem
|
, doReadMem
|
||||||
|
, doCondReadMem
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Lens((^.))
|
import Control.Lens((^.))
|
||||||
@ -36,15 +38,17 @@ import Lang.Crucible.Types
|
|||||||
import Lang.Crucible.Solver.Interface
|
import Lang.Crucible.Solver.Interface
|
||||||
|
|
||||||
import Lang.Crucible.LLVM.MemModel
|
import Lang.Crucible.LLVM.MemModel
|
||||||
( Mem, LLVMPointerType, LLVMPtr, isValidPointer, memEndian
|
( Mem, MemImpl, LLVMPointerType, LLVMPtr, isValidPointer, memEndian
|
||||||
, coerceAny
|
, LLVMVal(LLVMValInt)
|
||||||
, doLoad)
|
, loadRaw
|
||||||
|
, loadRawWithCondition
|
||||||
|
)
|
||||||
import Lang.Crucible.LLVM.MemModel.Pointer
|
import Lang.Crucible.LLVM.MemModel.Pointer
|
||||||
( llvmPointerView, muxLLVMPtr, llvmPointer_bv, ptrAdd, ptrSub, ptrEq
|
( llvmPointerView, muxLLVMPtr, llvmPointer_bv, ptrAdd, ptrSub, ptrEq
|
||||||
, pattern LLVMPointerRepr
|
, pattern LLVMPointer
|
||||||
)
|
)
|
||||||
import Lang.Crucible.LLVM.MemModel.Type(bitvectorType)
|
import Lang.Crucible.LLVM.MemModel.Type(bitvectorType)
|
||||||
import Lang.Crucible.LLVM.DataLayout(toAlignment,EndianForm(..))
|
import Lang.Crucible.LLVM.DataLayout(EndianForm(..))
|
||||||
import Lang.Crucible.LLVM.Bytes(toBytes)
|
import Lang.Crucible.LLVM.Bytes(toBytes)
|
||||||
|
|
||||||
import Data.Macaw.Symbolic.CrucGen(lemma1_16)
|
import Data.Macaw.Symbolic.CrucGen(lemma1_16)
|
||||||
@ -162,30 +166,70 @@ doReadMem ::
|
|||||||
)
|
)
|
||||||
doReadMem st mvar w (BVMemRepr bytes endian) ptr =
|
doReadMem st mvar w (BVMemRepr bytes endian) ptr =
|
||||||
do mem <- getMem st mvar
|
do mem <- getMem st mvar
|
||||||
case (endian, memEndian mem) of
|
checkEndian mem endian
|
||||||
(M.BigEndian, BigEndian) -> return ()
|
|
||||||
(M.LittleEndian, LittleEndian) -> return ()
|
|
||||||
(need,have) -> fail $ unlines [ "[doReadMem] Endian mismatch:"
|
|
||||||
, " *** Model: " ++ show have
|
|
||||||
, " *** Read : " ++ show need ]
|
|
||||||
|
|
||||||
let sym = stateSymInterface st
|
let sym = stateSymInterface st
|
||||||
ty = bitvectorType (toBytes (widthVal bytes))
|
ty = bitvectorType (toBytes (widthVal bytes))
|
||||||
|
bitw = natMultiply (knownNat @8) bytes
|
||||||
{- XXX: The alginment requirements should be part of the spec.
|
|
||||||
For example, on X86, there are aligned reads and unlaigned reads,
|
|
||||||
which makes different assumptions about the alignment of the data -}
|
|
||||||
Just align = toAlignment (toBytes (1::Int))
|
|
||||||
|
|
||||||
LeqProof <- return (lemma1_16 w)
|
LeqProof <- return (lemma1_16 w)
|
||||||
LeqProof <- return (leqMulPos (knownNat @8) bytes)
|
LeqProof <- return (leqMulPos (knownNat @8) bytes)
|
||||||
|
|
||||||
anyval <- let ?ptrWidth = w in doLoad sym mem (regValue ptr) ty align
|
val <- let ?ptrWidth = w in loadRaw sym mem (regValue ptr) ty
|
||||||
let repr = LLVMPointerRepr (natMultiply (knownNat @8) bytes)
|
a <- case valToBits bitw val of
|
||||||
a <- coerceAny sym repr anyval
|
Just a -> return a
|
||||||
|
Nothing -> fail "[doReadMem] We read an unexpected value"
|
||||||
|
|
||||||
return (a,st)
|
return (a,st)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
doCondReadMem ::
|
||||||
|
(IsSymInterface sym, 16 <= ptrW) =>
|
||||||
|
CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} ->
|
||||||
|
GlobalVar Mem -> {- ^ Memory model -}
|
||||||
|
NatRepr ptrW {- ^ Width of ptr -} ->
|
||||||
|
MemRepr ty {- ^ What/how we are reading -} ->
|
||||||
|
RegEntry sym BoolType {- ^ Condition -} ->
|
||||||
|
RegEntry sym (LLVMPointerType ptrW) {- ^ Pointer -} ->
|
||||||
|
RegEntry sym (ToCrucibleType ty) {- ^ Default answer -} ->
|
||||||
|
IO ( RegValue sym (ToCrucibleType ty)
|
||||||
|
, CrucibleState s sym ext rtp blocks r ctx
|
||||||
|
)
|
||||||
|
doCondReadMem st mvar w (BVMemRepr bytes endian) cond0 ptr def0 =
|
||||||
|
do let cond = regValue cond0
|
||||||
|
def = regValue def0
|
||||||
|
mem <- getMem st mvar
|
||||||
|
checkEndian mem endian
|
||||||
|
let sym = stateSymInterface st
|
||||||
|
ty = bitvectorType (toBytes (widthVal bytes))
|
||||||
|
bitw = natMultiply (knownNat @8) bytes
|
||||||
|
|
||||||
|
LeqProof <- return (lemma1_16 w)
|
||||||
|
LeqProof <- return (leqMulPos (knownNat @8) bytes)
|
||||||
|
|
||||||
|
val <- let ?ptrWidth = w in loadRawWithCondition sym mem (regValue ptr) ty
|
||||||
|
|
||||||
|
let useDefault msg =
|
||||||
|
do notC <- notPred sym cond
|
||||||
|
addAssertion sym notC
|
||||||
|
(AssertFailureSimError ("[doCondReadMem] " ++ msg))
|
||||||
|
return def
|
||||||
|
|
||||||
|
a <- case val of
|
||||||
|
Right (p,r,v) | Just a <- valToBits bitw v ->
|
||||||
|
do grd <- impliesPred sym cond p
|
||||||
|
addAssertion sym grd r
|
||||||
|
muxLLVMPtr sym cond a def
|
||||||
|
Right _ -> useDefault "Unexpected value read from memory."
|
||||||
|
Left err -> useDefault err
|
||||||
|
|
||||||
|
return (a,st)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Utilities
|
-- Utilities
|
||||||
|
|
||||||
@ -281,3 +325,21 @@ cases sym name mux opts =
|
|||||||
check valid msg
|
check valid msg
|
||||||
|
|
||||||
|
|
||||||
|
valToBits :: (IsSymInterface sym, 1 <= w) =>
|
||||||
|
NatRepr w -> LLVMVal sym -> Maybe (LLVMPtr sym w)
|
||||||
|
valToBits w val =
|
||||||
|
case val of
|
||||||
|
LLVMValInt base off | Just Refl <- testEquality (bvWidth off) w ->
|
||||||
|
return (LLVMPointer base off)
|
||||||
|
_ -> Nothing
|
||||||
|
|
||||||
|
checkEndian :: MemImpl sym -> M.Endianness -> IO ()
|
||||||
|
checkEndian mem endian =
|
||||||
|
case (endian, memEndian mem) of
|
||||||
|
(M.BigEndian, BigEndian) -> return ()
|
||||||
|
(M.LittleEndian, LittleEndian) -> return ()
|
||||||
|
(need,have) -> fail $ unlines [ "[doReadMem] Endian mismatch:"
|
||||||
|
, " *** Model: " ++ show have
|
||||||
|
, " *** Read : " ++ show need ]
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user