-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #428 from GaloisInc/dm/traceconstraints
support additional constraints when generating traces * add `--add-trace-constraints` flag that allows for generating additional traces with constraints for the final equivalence conditions - Defines a trace constraint datatype in Pate.TraceConstraint that is simply: expression, comparison, constant * add alternative what4 serializer that uses expression identifiers (based on what4 hashes/nonces) in lieu of serialized expressions * add deserialization infrastructure for expressions-containing types, using the expression environment from the identifier-based serializer
- Loading branch information
Showing
12 changed files
with
650 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
{-# LANGUAGE PolyKinds #-} | ||
{-# LANGUAGE DataKinds #-} | ||
{-# LANGUAGE OverloadedStrings #-} | ||
{-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
{-# LANGUAGE TypeApplications #-} | ||
{-# LANGUAGE ScopedTypeVariables #-} | ||
{-# LANGUAGE MultiParamTypeClasses #-} | ||
{-# LANGUAGE TypeFamilies #-} | ||
{-# LANGUAGE GADTs #-} | ||
|
||
{-# OPTIONS_GHC -fno-warn-orphans #-} | ||
{-# LANGUAGE LambdaCase #-} | ||
{-# LANGUAGE FlexibleContexts #-} | ||
{-# LANGUAGE AllowAmbiguousTypes #-} | ||
{-# LANGUAGE FlexibleInstances #-} | ||
{-# LANGUAGE RankNTypes #-} | ||
{-# LANGUAGE TypeOperators #-} | ||
|
||
module Pate.TraceConstraint | ||
( | ||
TraceConstraint | ||
, constraintToPred | ||
, TraceConstraintMap(..) | ||
, readConstraintMap | ||
) where | ||
|
||
import Prelude hiding (EQ) | ||
|
||
import qualified Control.Monad.IO.Unlift as IO | ||
import Control.Monad ( forM ) | ||
import Control.Monad.Except | ||
import Control.Monad.Trans | ||
import qualified Data.Aeson as JSON | ||
import qualified Data.Aeson.Types as JSON | ||
|
||
import qualified Data.Text.Lazy.Encoding as Text | ||
import qualified Data.Text.Encoding.Error as Text | ||
import qualified Data.Kind as DK | ||
import Data.String | ||
import Data.Map ( Map ) | ||
import qualified Data.Map as Map | ||
|
||
import qualified Prettyprinter as PP | ||
|
||
import qualified What4.Interface as W4 | ||
import qualified What4.Concrete as W4 | ||
|
||
import qualified Pate.Arch as PA | ||
import qualified Pate.PatchPair as PPa | ||
import Pate.Verification.PairGraph.Node | ||
import Pate.TraceTree | ||
import qualified What4.JSON as W4S | ||
import What4.JSON ( (.:) ) | ||
import Data.Parameterized.Some (Some(..)) | ||
import qualified Data.BitVector.Sized as BVS | ||
import qualified Numeric as Num | ||
|
||
newtype TraceIdentifier = TraceIdentifier String | ||
deriving (Eq, Ord, IsString) | ||
|
||
data ConstraintOp = LTs | LTu | GTs | GTu | LEs | LEu | GEs | GEu | NEQ | EQ | ||
deriving (Show, Read) | ||
|
||
data TraceConstraint sym = forall tp. TraceConstraint | ||
{ tcVar :: W4.SymExpr sym tp | ||
, tcOp :: ConstraintOp | ||
, tcConst :: W4.ConcreteVal tp | ||
} | ||
|
||
instance forall sym. W4S.W4Deserializable sym (TraceConstraint sym) where | ||
w4Deserialize_ v | W4S.SymDeserializable{} <- W4S.symDeserializable @sym = do | ||
JSON.Object o <- return v | ||
(Some (var :: W4.SymExpr sym tp)) <- o .: "var" | ||
(opJSON :: JSON.Value) <- o .: "op" | ||
(op :: ConstraintOp) <- W4S.readJSON opJSON | ||
case W4.exprType var of | ||
W4.BaseBVRepr w -> do | ||
(cS :: String) <- o .: "const" | ||
((c :: Integer),""):_ <- return $ Num.readDec cS | ||
case (BVS.mkBVUnsigned w c) of | ||
Just bv -> return $ TraceConstraint var op (W4.ConcreteBV w bv) | ||
Nothing -> fail "Unexpected integer size" | ||
_ -> fail ("Unsupported expression type:" ++ show (W4.exprType var)) | ||
|
||
constraintToPred :: | ||
forall sym. | ||
W4.IsExprBuilder sym => | ||
sym -> | ||
TraceConstraint sym -> | ||
IO (W4.Pred sym) | ||
constraintToPred sym (TraceConstraint var op c) = case W4.exprType var of | ||
W4.BaseBVRepr w -> do | ||
let W4.ConcreteBV _ bv = c | ||
bvSym <- W4.bvLit sym w bv | ||
let go :: (forall w. 1 W4.<= w => sym -> W4.SymBV sym w -> W4.SymBV sym w -> IO (W4.Pred sym)) -> IO (W4.Pred sym) | ||
go f = f sym var bvSym | ||
let goNot :: (forall w. 1 W4.<= w => sym -> W4.SymBV sym w -> W4.SymBV sym w -> IO (W4.Pred sym)) -> IO (W4.Pred sym) | ||
goNot f = f sym var bvSym >>= W4.notPred sym | ||
case op of | ||
LTs -> go W4.bvSlt | ||
LTu -> go W4.bvUlt | ||
LEs -> go W4.bvSle | ||
LEu -> go W4.bvUle | ||
EQ -> go W4.isEq | ||
GTs -> goNot W4.bvSle | ||
GTu -> goNot W4.bvUle | ||
GEs -> goNot W4.bvSlt | ||
GEu -> goNot W4.bvUlt | ||
NEQ -> goNot W4.isEq | ||
_ -> fail "Unexpected constraint " | ||
|
||
|
||
|
||
newtype TraceConstraintMap sym arch = | ||
TraceConstraintMap (Map (GraphNode arch) (TraceConstraint sym)) | ||
|
||
|
||
instance forall sym arch. IsTraceNode '(sym :: DK.Type,arch :: DK.Type) "trace_constraint_map" where | ||
type TraceNodeType '(sym,arch) "trace_constraint_map" = TraceConstraintMap sym arch | ||
prettyNode _ _ = PP.pretty ("TODO" :: String) | ||
nodeTags = [] | ||
|
||
readConstraintMap :: | ||
W4.IsExprBuilder sym => | ||
IsTreeBuilder '(sym,arch) e m => | ||
IO.MonadUnliftIO m => | ||
PA.ValidArch arch => | ||
sym -> | ||
String {- ^ input prompt -} -> | ||
[(GraphNode arch,W4S.ExprEnv sym)] -> | ||
m (TraceConstraintMap sym arch) | ||
readConstraintMap sym msg ndEnvs = do | ||
let parse s = case JSON.eitherDecode (fromString s) of | ||
Left err -> return $ Left $ InputChoiceError "Failed to decode JSON" [err] | ||
Right (v :: JSON.Value) -> runExceptT $ do | ||
(nodes :: [[JSON.Value]]) <- runJSON $ JSON.parseJSON v | ||
let nds = zip ndEnvs nodes | ||
fmap (TraceConstraintMap . Map.fromList . concat) $ | ||
forM nds $ \((nd, env), constraints_json) -> forM constraints_json $ \constraint_json -> | ||
(lift $ W4S.jsonToW4 sym env constraint_json) >>= \case | ||
Left err -> throwError $ InputChoiceError "Failed to parse value" [err] | ||
Right a -> return (nd, a) | ||
chooseInput_ @"trace_constraint_map" msg parse >>= \case | ||
Nothing -> IO.liftIO $ fail "Unexpected trace map read" | ||
Just a -> return a | ||
|
||
|
||
runJSON :: JSON.Parser a -> ExceptT InputChoiceError IO a | ||
runJSON p = ExceptT $ case JSON.parse (\() -> p) () of | ||
JSON.Success a -> return $ Right a | ||
JSON.Error err -> return $ Left $ InputChoiceError "Failed to parse value" [err] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.