Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track and check alignment for memory regions in llvm overrides #637

Merged
merged 10 commits into from
Feb 5, 2020
2 changes: 1 addition & 1 deletion deps/crucible
Submodule crucible updated 56 files
+6 −1 crucible-jvm/src/Lang/Crucible/JVM/Simulate.hs
+1 −1 crucible-jvm/src/Lang/Crucible/JVM/Translation.hs
+1 −1 crucible-llvm/crucible-llvm.cabal
+13 −13 crucible-llvm/src/Lang/Crucible/LLVM/DataLayout.hs
+11 −3 crucible-llvm/src/Lang/Crucible/LLVM/MemModel.hs
+11 −11 crucible-llvm/src/Lang/Crucible/LLVM/Translation/Instruction.hs
+1 −1 crucible-saw/crucible-saw.cabal
+48 −20 crucible-saw/src/Lang/Crucible/Backend/SAWCore.hs
+1 −1 crucible-server/crucible-server.cabal
+8 −3 crucible-server/src/Lang/Crucible/Server/Encoding.hs
+6 −1 crucible-server/src/Lang/Crucible/Server/Requests.hs
+1 −1 crucible-server/src/Lang/Crucible/Server/SAWOverrides.hs
+8 −1 crucible-server/src/Lang/Crucible/Server/Translation.hs
+9 −5 crucible-server/src/Lang/Crucible/Server/TypeConv.hs
+8 −3 crucible-server/src/Lang/Crucible/Server/ValueConv.hs
+9 −4 crucible-server/src/Lang/Crucible/Server/Verification/Override.hs
+1 −1 crucible-syntax/crucible-syntax.cabal
+2 −2 crucible-syntax/test-data/simulator-tests/assume-merge2.out.good
+6 −6 crucible-syntax/test-data/simulator-tests/bool-expr.out.good
+5 −3 crucible-syntax/test-data/simulator-tests/override-test2.out.good
+1 −1 crucible/crucible.cabal
+1 −1 crucible/src/Lang/Crucible/Analysis/ForwardDataflow.hs
+9 −2 crucible/src/Lang/Crucible/CFG/Generator.hs
+6 −1 crucible/src/Lang/Crucible/Simulator/Evaluation.hs
+8 −1 crucible/src/Lang/Crucible/Utils/RegRewrite.hs
+8 −1 crucible/src/Lang/Crucible/Utils/StateContT.hs
+2 −2 crux-llvm/crux-llvm.cabal
+113 −0 crux-llvm/src/Crux/LLVM/Overrides.hs
+1 −1 crux-llvm/src/CruxLLVMMain.hs
+1 −1 dependencies/abcBridge
+1 −1 dependencies/cryptol-verifier
+1 −1 dependencies/hpb
+1 −1 dependencies/llvm-pretty-bc-parser
+1 −1 dependencies/saw-core
+1 −1 dependencies/saw-core-what4
+8 −13 what4-abc/src/What4/Solver/ABC.hs
+1 −1 what4-abc/what4-abc.cabal
+6 −9 what4-blt/src/What4/Solver/BLT.hs
+1 −1 what4-blt/what4-blt.cabal
+6 −1 what4/src/What4/Config.hs
+0 −1 what4/src/What4/Expr/AppTheory.hs
+47 −160 what4/src/What4/Expr/Builder.hs
+6 −11 what4/src/What4/Expr/GroundEval.hs
+6 −10 what4/src/What4/Expr/VarIdentification.hs
+2 −2 what4/src/What4/Expr/WeightedSum.hs
+10 −8 what4/src/What4/Interface.hs
+12 −1 what4/src/What4/Partial.hs
+1 −2 what4/src/What4/ProgramLoc.hs
+6 −1 what4/src/What4/Protocol/ReadDecimal.hs
+6 −1 what4/src/What4/Protocol/SExp.hs
+11 −6 what4/src/What4/Protocol/SMTLib2.hs
+11 −0 what4/src/What4/Protocol/SMTLib2/Parse.hs
+11 −21 what4/src/What4/Protocol/SMTWriter.hs
+9 −4 what4/src/What4/Solver/Boolector.hs
+8 −4 what4/src/What4/Solver/Yices.hs
+10 −4 what4/src/What4/Utils/Environment.hs
138 changes: 88 additions & 50 deletions src/SAWScript/Crucible/LLVM/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ module SAWScript.Crucible.LLVM.Builtins
, crucible_llvm_unsafe_assume_spec
, crucible_fresh_var
, crucible_alloc
, crucible_alloc_aligned
, crucible_alloc_readonly
, crucible_alloc_with_size
, crucible_alloc_global
Expand Down Expand Up @@ -676,15 +677,13 @@ assertEqualVals cc v1 v2 =

-- TODO(langston): combine with/move to executeAllocation
doAlloc ::
(?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
(Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
LLVMCrucibleContext arch ->
LLVMAllocSpec ->
StateT MemImpl IO (LLVMPtr (Crucible.ArchWidth arch))
doAlloc cc (LLVMAllocSpec mut _memTy sz loc) = StateT $ \mem ->
doAlloc cc (LLVMAllocSpec mut _memTy alignment sz loc) = StateT $ \mem ->
do let sym = cc^.ccBackend
let dl = Crucible.llvmDataLayout ?lc
sz' <- W4.bvLit sym Crucible.PtrWidth $ Crucible.bytesToInteger sz
let alignment = Crucible.maxAlignment dl -- Use the maximum alignment required for any primitive type (FIXME?)
let l = show (W4.plSourceLoc loc)
liftIO $
Crucible.doMalloc sym Crucible.HeapAlloc mut l mem sz' alignment
Expand Down Expand Up @@ -1452,53 +1451,89 @@ crucible_alloc_internal _bic _opt lty spec = do
crucible_alloc_with_mutability_and_size ::
Crucible.Mutability ->
Maybe (Crucible.Bytes) ->
Maybe Crucible.Alignment ->
BuiltinContext ->
Options ->
L.Type ->
LLVMCrucibleSetupM (AllLLVM SetupValue)
crucible_alloc_with_mutability_and_size mut sz bic opts lty = LLVMCrucibleSetupM $ do
cctx <- getLLVMCrucibleContext
loc <- getW4Position "crucible_alloc"
memTy <- memTypeForLLVMType bic lty

let memTySize =
let ?lc = ccTypeCtx cctx
?dl = Crucible.llvmDataLayout ?lc
in Crucible.memTypeSize ?dl memTy

sz' <-
case sz of
Just sz_ -> do
when (sz_ < memTySize) $ fail $ unlines
[ "User error: manually-specified allocation size was less than needed"
, "Needed for this type: " ++ show memTySize
, "Specified: " ++ show sz_
]
pure sz_
Nothing -> pure (Crucible.toBytes memTySize)

crucible_alloc_internal bic opts lty $
LLVMAllocSpec { _allocSpecMut = mut
, _allocSpecType = memTy
, _allocSpecBytes = sz'
, _allocSpecLoc = loc
}
crucible_alloc_with_mutability_and_size mut sz alignment bic opts lty =
LLVMCrucibleSetupM $
do cctx <- getLLVMCrucibleContext
loc <- getW4Position "crucible_alloc"
memTy <- memTypeForLLVMType bic lty

let lc = ccTypeCtx cctx
let dl = Crucible.llvmDataLayout lc
let memTySize = Crucible.memTypeSize dl memTy
let memTyAlign = Crucible.memTypeAlign dl memTy

sz' <-
case sz of
Just sz_ -> do
when (sz_ < memTySize) $ fail $ unlines
[ "User error: manually-specified allocation size was less than needed"
, "Needed for this type: " ++ show memTySize
, "Specified: " ++ show sz_
]
pure sz_
Nothing -> pure (Crucible.toBytes memTySize)

alignment' <-
case alignment of
Just a -> do
when (a < memTyAlign) $ fail $ unlines
[ "User error: manually-specified alignment was less than needed"
, "Allocation type: " ++ show memTy
, "Minimum alignment for type: " ++ show (Crucible.fromAlignment memTyAlign) ++ "-byte"
, "Specified alignment: " ++ show (Crucible.fromAlignment a) ++ "-byte"
]
pure a
Nothing -> pure memTyAlign

crucible_alloc_internal bic opts lty $
LLVMAllocSpec
{ _allocSpecMut = mut
, _allocSpecType = memTy
, _allocSpecAlign = alignment'
, _allocSpecBytes = sz'
, _allocSpecLoc = loc
}

crucible_alloc ::
BuiltinContext ->
Options ->
L.Type ->
LLVMCrucibleSetupM (AllLLVM SetupValue)
crucible_alloc =
crucible_alloc_with_mutability_and_size Crucible.Mutable Nothing
crucible_alloc_with_mutability_and_size Crucible.Mutable Nothing Nothing

crucible_alloc_aligned ::
BuiltinContext ->
Options ->
Int ->
L.Type ->
LLVMCrucibleSetupM (AllLLVM SetupValue)
crucible_alloc_aligned bic opts n lty =
case Crucible.toAlignment (Crucible.toBytes n) of
Nothing ->
LLVMCrucibleSetupM $ fail $
"crucible_alloc_aligned: invalid non-power-of-2 alignment: " ++ show n
Just alignment ->
crucible_alloc_with_mutability_and_size
Crucible.Mutable
Nothing
(Just alignment)
bic
opts
lty

crucible_alloc_readonly ::
BuiltinContext ->
Options ->
L.Type ->
LLVMCrucibleSetupM (AllLLVM SetupValue)
crucible_alloc_readonly =
crucible_alloc_with_mutability_and_size Crucible.Immutable Nothing
crucible_alloc_with_mutability_and_size Crucible.Immutable Nothing Nothing

crucible_alloc_with_size ::
BuiltinContext ->
Expand All @@ -1510,6 +1545,7 @@ crucible_alloc_with_size bic opts sz lty =
crucible_alloc_with_mutability_and_size
Crucible.Mutable
(Just (Crucible.toBytes sz))
Nothing
bic
opts
lty
Expand Down Expand Up @@ -1538,23 +1574,25 @@ constructFreshPointer ::
W4.ProgramLoc ->
Crucible.MemType ->
CrucibleSetup (LLVM arch) (AllLLVM SetupValue)
constructFreshPointer mid loc memTy = do
cctx <- getLLVMCrucibleContext
let ?lc = ccTypeCtx cctx
let ?dl = Crucible.llvmDataLayout ?lc
n <- Setup.csVarCounter <<%= nextAllocIndex
let sz = Crucible.memTypeSize ?dl memTy
Setup.currentState . MS.csFreshPointers . at n ?=
LLVMAllocSpec { _allocSpecMut = Crucible.Mutable
, _allocSpecType = memTy
, _allocSpecBytes = sz
, _allocSpecLoc = loc
}
-- TODO: refactor
case mid of
Just i -> Setup.currentState . MS.csVarTypeNames.at n ?= i
Nothing -> return ()
return (mkAllLLVM (SetupVar n))
constructFreshPointer mid loc memTy =
do cctx <- getLLVMCrucibleContext
let ?lc = ccTypeCtx cctx
let ?dl = Crucible.llvmDataLayout ?lc
n <- Setup.csVarCounter <<%= nextAllocIndex
let sz = Crucible.memTypeSize ?dl memTy
let alignment = Crucible.memTypeAlign ?dl memTy
Setup.currentState . MS.csFreshPointers . at n ?=
LLVMAllocSpec { _allocSpecMut = Crucible.Mutable
, _allocSpecType = memTy
, _allocSpecAlign = alignment
, _allocSpecBytes = sz
, _allocSpecLoc = loc
}
-- TODO: refactor
case mid of
Just i -> Setup.currentState . MS.csVarTypeNames.at n ?= i
Nothing -> return ()
return (mkAllLLVM (SetupVar n))

crucible_points_to ::
Bool {- ^ whether to check type compatibility -} ->
Expand Down
3 changes: 2 additions & 1 deletion src/SAWScript/Crucible/LLVM/CrucibleLLVM.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module SAWScript.Crucible.LLVM.CrucibleLLVM
, ptrBitwidth
, integerAlignment
, floatAlignment
, fromAlignment
, EndianForm(..)
-- * Re-exports from "Lang.Crucible.LLVM.Extension"
, ArchWidth
Expand Down Expand Up @@ -137,7 +138,7 @@ import Lang.Crucible.LLVM.Bytes

import Lang.Crucible.LLVM.DataLayout
(Alignment, noAlignment, padToAlignment, DataLayout, EndianForm(..),
integerAlignment, floatAlignment, intWidthSize, ptrBitwidth)
integerAlignment, floatAlignment, fromAlignment, intWidthSize, ptrBitwidth)

import Lang.Crucible.LLVM.Extension
(ArchWidth)
Expand Down
2 changes: 2 additions & 0 deletions src/SAWScript/Crucible/LLVM/MethodSpecIR.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ module SAWScript.Crucible.LLVM.MethodSpecIR
-- * LLVMAllocSpec
, LLVMAllocSpec(..)
, allocSpecType
, allocSpecAlign
, allocSpecMut
, allocSpecLoc
, allocSpecBytes
Expand Down Expand Up @@ -183,6 +184,7 @@ data LLVMAllocSpec =
LLVMAllocSpec
{ _allocSpecMut :: CL.Mutability
, _allocSpecType :: CL.MemType
, _allocSpecAlign :: CL.Alignment
, _allocSpecBytes :: CL.Bytes
, _allocSpecLoc :: ProgramLoc
}
Expand Down
55 changes: 42 additions & 13 deletions src/SAWScript/Crucible/LLVM/Override.hs
Original file line number Diff line number Diff line change
Expand Up @@ -612,12 +612,13 @@ learnCond :: (?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWi
-> PrePost
-> MS.StateSpec (LLVM arch)
-> OverrideMatcher (LLVM arch) md ()
learnCond opts sc cc cs prepost ss = do
let loc = cs ^. MS.csLoc
matchPointsTos opts sc cc cs prepost (ss ^. MS.csPointsTos)
traverse_ (learnSetupCondition opts sc cc cs prepost) (ss ^. MS.csConditions)
enforceDisjointness loc ss
enforceCompleteSubstitution loc ss
learnCond opts sc cc cs prepost ss =
do let loc = cs ^. MS.csLoc
matchPointsTos opts sc cc cs prepost (ss ^. MS.csPointsTos)
traverse_ (learnSetupCondition opts sc cc cs prepost) (ss ^. MS.csConditions)
enforceAlignment loc ss
enforceDisjointness loc ss
enforceCompleteSubstitution loc ss


-- | Verify that all of the fresh variables for the given
Expand Down Expand Up @@ -688,6 +689,33 @@ refreshTerms sc ss =

------------------------------------------------------------------------

-- | Generate assertions that all of the memory regions matched by an
-- override's precondition are properly aligned.
enforceAlignment ::
(?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
W4.ProgramLoc ->
MS.StateSpec (LLVM arch) ->
OverrideMatcher (LLVM arch) md ()
enforceAlignment loc ss =
do sym <- Ov.getSymInterface
sub <- OM (use setupValueSub) -- Map AllocIndex (LLVMPtr (Crucible.ArchWidth arch))
let allocs = view MS.csAllocs ss -- Map AllocIndex LLVMAllocSpec
let mems = Map.elems $ Map.intersectionWith (,) allocs sub

sequence_
[ do c <- liftIO $ Crucible.isAligned sym Crucible.PtrWidth ptr alignment
let msg =
"Memory region not aligned: "
++ "(base=" ++ show (Crucible.ppPtr ptr)
++ ", required alignment=" ++ show (Crucible.fromAlignment alignment) ++ "-byte)"
addAssert c $ Crucible.SimError loc $
Crucible.AssertFailureSimError msg ""

| (LLVMAllocSpec _mut _pty alignment _psz _ploc, ptr) <- mems
]

------------------------------------------------------------------------

-- | Generate assertions that all of the memory allocations matched by
-- an override's precondition are disjoint. Read-only allocations are
-- allowed to alias other read-only allocations, however.
Expand Down Expand Up @@ -724,8 +752,8 @@ enforceDisjointness loc ss =
addAssert c $ Crucible.SimError loc $
Crucible.AssertFailureSimError msg ""

| (LLVMAllocSpec _mut _pty psz ploc, p) : ps <- tails memsRW
, (LLVMAllocSpec _mut _qty qsz qloc, q) <- ps ++ memsRO
| (LLVMAllocSpec _mut _pty _align psz ploc, p) : ps <- tails memsRW
, (LLVMAllocSpec _mut _qty _align qsz qloc, q) <- ps ++ memsRO
]

------------------------------------------------------------------------
Expand Down Expand Up @@ -1078,9 +1106,11 @@ learnSetupCondition ::
PrePost ->
MS.SetupCondition (LLVM arch) ->
OverrideMatcher (LLVM arch) md ()
learnSetupCondition opts sc cc spec prepost (MS.SetupCond_Equal loc val1 val2) = learnEqual opts sc cc spec loc prepost val1 val2
learnSetupCondition _opts sc cc _ prepost (MS.SetupCond_Pred loc tm) = learnPred sc cc loc prepost (ttTerm tm)
learnSetupCondition _opts sc cc _ prepost (MS.SetupCond_Ghost () loc var val) = learnGhost sc cc loc prepost var val
learnSetupCondition opts sc cc spec prepost cond =
case cond of
MS.SetupCond_Equal loc val1 val2 -> learnEqual opts sc cc spec loc prepost val1 val2
MS.SetupCond_Pred loc tm -> learnPred sc cc loc prepost (ttTerm tm)
MS.SetupCond_Ghost () loc var val -> learnGhost sc cc loc prepost var val


------------------------------------------------------------------------
Expand Down Expand Up @@ -1306,7 +1336,7 @@ executeAllocation ::
LLVMCrucibleContext arch ->
(AllocIndex, LLVMAllocSpec) ->
OverrideMatcher (LLVM arch) RW ()
executeAllocation opts cc (var, LLVMAllocSpec mut memTy sz loc) =
executeAllocation opts cc (var, LLVMAllocSpec mut memTy alignment sz loc) =
do let sym = cc^.ccBackend
{-
memTy <- case Crucible.asMemType symTy of
Expand All @@ -1317,7 +1347,6 @@ executeAllocation opts cc (var, LLVMAllocSpec mut memTy sz loc) =
let memVar = Crucible.llvmMemVar (ccLLVMContext cc)
mem <- readGlobal memVar
sz' <- liftIO $ W4.bvLit sym Crucible.PtrWidth (Crucible.bytesToInteger sz)
let alignment = Crucible.noAlignment -- default to byte alignment (FIXME)
let l = show (W4.plSourceLoc loc) ++ " (Poststate)"
(ptr, mem') <- liftIO $
Crucible.doMalloc sym Crucible.HeapAlloc mut l mem sz' alignment
Expand Down
10 changes: 10 additions & 0 deletions src/SAWScript/Interpreter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,16 @@ primitives = Map.fromList
, "verified is expected to perform the allocation."
]

, prim "crucible_alloc_aligned" "Int -> LLVMType -> CrucibleSetup SetupValue"
(bicVal crucible_alloc_aligned)
Current
[ "Declare that a memory region of the given type should be allocated in"
, "a Crucible specification, and also specify that the start of the region"
, "should be aligned to a multiple of the specified number of bytes (which"
, "must be a power of 2). The specified alignment must be no less than the"
, "minimum required by the LLVM type."
]

, prim "crucible_alloc_readonly" "LLVMType -> CrucibleSetup SetupValue"
(bicVal crucible_alloc_readonly)
Current
Expand Down