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 57 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
+27 −3 crucible-llvm/src/Lang/Crucible/LLVM/MemModel.hs
+38 −3 crucible-llvm/src/Lang/Crucible/LLVM/MemModel/Generic.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
66 changes: 53 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)
enforcePointerValidity cc 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,44 @@ refreshTerms sc ss =

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

-- | Generate assertions that all of the memory regions matched by an
-- override's precondition are allocated, and meet the appropriate
-- requirements for alignment and mutability.
enforcePointerValidity ::
(?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
LLVMCrucibleContext arch ->
W4.ProgramLoc ->
MS.StateSpec (LLVM arch) ->
OverrideMatcher (LLVM arch) md ()
enforcePointerValidity cc 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
let w = Crucible.PtrWidth
let memVar = Crucible.llvmMemVar (ccLLVMContext cc)
mem <- readGlobal memVar

sequence_
[ do psz' <-
liftIO $ W4.bvLit sym Crucible.PtrWidth $ Crucible.bytesToInteger psz
c <-
liftIO $
Crucible.isAllocatedAlignedPointer sym w alignment mut ptr (Just psz') mem
let msg =
"Pointer not valid:"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unfortunate that we can't have a more specific diagnosis here. The tradeoff for a better API on the Crucible side seems to be that we and more predicates together, losing some granularity in the assertions.

++ "\n base = " ++ show (Crucible.ppPtr ptr)
++ "\n size = " ++ show psz
++ "\n required alignment = " ++ show (Crucible.fromAlignment alignment) ++ "-byte"
++ "\n required mutability = " ++ show mut
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 +763,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 +1117,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 +1347,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 +1358,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 @@ -1807,6 +1807,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