mirror of
https://github.com/GaloisInc/macaw.git
synced 2024-11-24 00:42:28 +03:00
Merge pull request #54 from GaloisInc/jhx/absstate
Additional comments/refactoring on abstract state handling.
This commit is contained in:
commit
ad05aeb0d3
@ -8,11 +8,11 @@
|
|||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE StandaloneDeriving #-}
|
{-# LANGUAGE StandaloneDeriving #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
{-# LANGUAGE TypeSynonymInstances #-}
|
{-# LANGUAGE TypeSynonymInstances #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
{-# OPTIONS_GHC -Werror #-}
|
|
||||||
module Data.Macaw.AbsDomain.AbsState
|
module Data.Macaw.AbsDomain.AbsState
|
||||||
( AbsBlockState
|
( AbsBlockState
|
||||||
, setAbsIP
|
, setAbsIP
|
||||||
@ -154,6 +154,8 @@ data AbsValue w (tp :: Type)
|
|||||||
| (tp ~ BVType w) => SomeStackOffset !(MemAddr w)
|
| (tp ~ BVType w) => SomeStackOffset !(MemAddr w)
|
||||||
-- ^ An offset to the stack at some offset.
|
-- ^ An offset to the stack at some offset.
|
||||||
--
|
--
|
||||||
|
-- Note. We do nothing to guarantee that this is a legal stack offset.
|
||||||
|
--
|
||||||
-- To avoid conflating offsets that are relative to the begining of different
|
-- To avoid conflating offsets that are relative to the begining of different
|
||||||
-- blocks, we include the address of the block as the first argument.
|
-- blocks, we include the address of the block as the first argument.
|
||||||
| forall n . (tp ~ BVType n) => StridedInterval !(SI.StridedInterval n)
|
| forall n . (tp ~ BVType n) => StridedInterval !(SI.StridedInterval n)
|
||||||
@ -610,6 +612,31 @@ asBoolConst :: AbsValue w BoolType -> Maybe Bool
|
|||||||
asBoolConst (BoolConst b) = Just b
|
asBoolConst (BoolConst b) = Just b
|
||||||
asBoolConst TopV = Nothing
|
asBoolConst TopV = Nothing
|
||||||
|
|
||||||
|
-- | Add an integer to the abstract value.
|
||||||
|
bvinc :: forall w u
|
||||||
|
. NatRepr u
|
||||||
|
-> AbsValue w (BVType u)
|
||||||
|
-> Integer
|
||||||
|
-- ^ An integer value to add to the previous argument.
|
||||||
|
-> AbsValue w (BVType u)
|
||||||
|
bvinc w (FinSet s) o =
|
||||||
|
FinSet $ Set.map (toUnsigned w . (+o)) s
|
||||||
|
bvinc _ (CodePointers _ _) _ =
|
||||||
|
TopV
|
||||||
|
bvinc w (StackOffset a s) o =
|
||||||
|
StackOffset a $ Set.map (fromInteger . toUnsigned w . (+o) . toInteger) s
|
||||||
|
bvinc _ (SomeStackOffset a) _ =
|
||||||
|
SomeStackOffset a
|
||||||
|
-- Strided intervals
|
||||||
|
bvinc w (StridedInterval si) o =
|
||||||
|
stridedInterval $ SI.bvadd w si (SI.singleton w o)
|
||||||
|
bvinc _ (SubValue w' v) o =
|
||||||
|
case bvinc w' v o of
|
||||||
|
TopV -> TopV
|
||||||
|
v' -> SubValue w' v'
|
||||||
|
bvinc _ TopV _ = TopV
|
||||||
|
bvinc _ ReturnAddr _ = TopV
|
||||||
|
|
||||||
bvadc :: forall w u
|
bvadc :: forall w u
|
||||||
. MemWidth w
|
. MemWidth w
|
||||||
=> NatRepr u
|
=> NatRepr u
|
||||||
@ -632,11 +659,9 @@ bvadc w (FinSet t) (StackOffset a s) c
|
|||||||
bvadc w (FinSet l) (FinSet r) (BoolConst b)
|
bvadc w (FinSet l) (FinSet r) (BoolConst b)
|
||||||
| ls <- Set.toList l
|
| ls <- Set.toList l
|
||||||
, rs <- Set.toList r
|
, rs <- Set.toList r
|
||||||
= case Set.fromList [bottomBits $ lval+rval+if b then 1 else 0 | lval <- ls, rval <- rs] of
|
= case Set.fromList [toUnsigned w $ lval+rval+if b then 1 else 0 | lval <- ls, rval <- rs] of
|
||||||
s | Set.size s <= maxSetSize -> FinSet s
|
s | Set.size s <= maxSetSize -> FinSet s
|
||||||
_ -> TopV
|
_ -> TopV
|
||||||
where
|
|
||||||
bottomBits v = v .&. (bit (fromInteger (intValue w)) - 1)
|
|
||||||
-- Strided intervals
|
-- Strided intervals
|
||||||
bvadc w v v' c
|
bvadc w v v' c
|
||||||
| StridedInterval si1 <- v, StridedInterval si2 <- v' = go si1 si2
|
| StridedInterval si1 <- v, StridedInterval si2 <- v' = go si1 si2
|
||||||
@ -868,8 +893,8 @@ abstractSingleton mem w i
|
|||||||
, Just sa <- resolveAbsoluteAddr mem (fromInteger i)
|
, Just sa <- resolveAbsoluteAddr mem (fromInteger i)
|
||||||
, segmentFlags (segoffSegment sa) `Perm.hasPerm` Perm.execute =
|
, segmentFlags (segoffSegment sa) `Perm.hasPerm` Perm.execute =
|
||||||
concreteCodeAddr sa
|
concreteCodeAddr sa
|
||||||
| 0 <= i && i <= maxUnsigned w = FinSet (Set.singleton i)
|
| otherwise =
|
||||||
| otherwise = error $ "abstractSingleton given bad value: " ++ show i ++ " " ++ show w
|
FinSet (Set.singleton (toUnsigned w i))
|
||||||
|
|
||||||
-- | Create a concrete stack offset.
|
-- | Create a concrete stack offset.
|
||||||
concreteStackOffset :: MemAddr w -> Integer -> AbsValue w (BVType w)
|
concreteStackOffset :: MemAddr w -> Integer -> AbsValue w (BVType w)
|
||||||
@ -1227,7 +1252,7 @@ transferValue c v = do
|
|||||||
, segmentFlags (segoffSegment addr) `Perm.hasPerm` Perm.execute ->
|
, segmentFlags (segoffSegment addr) `Perm.hasPerm` Perm.execute ->
|
||||||
concreteCodeAddr addr
|
concreteCodeAddr addr
|
||||||
| Just addr <- asAbsoluteAddr i ->
|
| Just addr <- asAbsoluteAddr i ->
|
||||||
FinSet $ Set.singleton $ toInteger addr
|
FinSet $ Set.singleton $ toInteger addr
|
||||||
| otherwise ->
|
| otherwise ->
|
||||||
TopV
|
TopV
|
||||||
SymbolValue{} -> TopV
|
SymbolValue{} -> TopV
|
||||||
@ -1360,14 +1385,6 @@ transferApp r a = do
|
|||||||
BVShl w v s -> bitop (\x1 x2 -> shiftL x1 (fromInteger x2)) w (t v) (t s)
|
BVShl w v s -> bitop (\x1 x2 -> shiftL x1 (fromInteger x2)) w (t v) (t s)
|
||||||
_ -> TopV
|
_ -> TopV
|
||||||
|
|
||||||
-- | Minimal information needed to parse a function call/system call
|
|
||||||
data CallParams (r :: Type -> Kind.Type)
|
|
||||||
= CallParams { postCallStackDelta :: Integer
|
|
||||||
-- ^ Amount stack should shift by when going before/after call.
|
|
||||||
, preserveReg :: forall tp . r tp -> Bool
|
|
||||||
-- ^ Return true if a register value is preserved by a call.
|
|
||||||
}
|
|
||||||
|
|
||||||
-- | Update abstract state post call.
|
-- | Update abstract state post call.
|
||||||
absUpdateRegsPostCall :: RegisterInfo r
|
absUpdateRegsPostCall :: RegisterInfo r
|
||||||
=> (forall tp . r tp -> AbsValue (RegAddrWidth r) tp)
|
=> (forall tp . r tp -> AbsValue (RegAddrWidth r) tp)
|
||||||
@ -1380,7 +1397,19 @@ absUpdateRegsPostCall regFn ab0 =
|
|||||||
, _initIndexBounds = Jmp.arbitraryInitialBounds
|
, _initIndexBounds = Jmp.arbitraryInitialBounds
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Return state post call
|
-- | Minimal information needed to parse a function call/system call
|
||||||
|
data CallParams (r :: Type -> Kind.Type)
|
||||||
|
= CallParams { postCallStackDelta :: Integer
|
||||||
|
-- ^ Amount stack should shift by when going before/after call.
|
||||||
|
, preserveReg :: forall tp . r tp -> Bool
|
||||||
|
-- ^ Return true if a register value is preserved by
|
||||||
|
-- a call.
|
||||||
|
--
|
||||||
|
-- We assume stack pointer and instruction pointer
|
||||||
|
-- are preserved, so the return value for these does not matter.
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | This updates the registers after a call has been performed.
|
||||||
absEvalCall :: forall r
|
absEvalCall :: forall r
|
||||||
. ( RegisterInfo r
|
. ( RegisterInfo r
|
||||||
, HasRepr r TypeRepr
|
, HasRepr r TypeRepr
|
||||||
@ -1399,9 +1428,9 @@ absEvalCall params ab0 addr = absUpdateRegsPostCall regFn ab0
|
|||||||
| Just Refl <- testEquality r ip_reg =
|
| Just Refl <- testEquality r ip_reg =
|
||||||
concreteCodeAddr addr
|
concreteCodeAddr addr
|
||||||
| Just Refl <- testEquality r sp_reg =
|
| Just Refl <- testEquality r sp_reg =
|
||||||
bvadd (typeWidth r)
|
bvinc (typeWidth r)
|
||||||
(ab0^.absRegState^.boundValue r)
|
(ab0^.absRegState^.boundValue r)
|
||||||
(FinSet (Set.singleton (postCallStackDelta params)))
|
(postCallStackDelta params)
|
||||||
-- Copy callee saved registers
|
-- Copy callee saved registers
|
||||||
| preserveReg params r =
|
| preserveReg params r =
|
||||||
ab0^.absRegState^.boundValue r
|
ab0^.absRegState^.boundValue r
|
||||||
|
@ -314,14 +314,14 @@ class (1 <= w) => MemWidth w where
|
|||||||
-- The argument is ignored.
|
-- The argument is ignored.
|
||||||
addrWidthRepr :: p w -> AddrWidthRepr w
|
addrWidthRepr :: p w -> AddrWidthRepr w
|
||||||
|
|
||||||
-- | @addrWidthMask w@ returns @2^(8 * addrSize w) - 1@.
|
|
||||||
addrWidthMask :: p w -> Word64
|
|
||||||
|
|
||||||
-- | Returns number of bytes in addr.
|
-- | Returns number of bytes in addr.
|
||||||
--
|
--
|
||||||
-- The argument is not evaluated.
|
-- The argument is not evaluated.
|
||||||
addrSize :: p w -> Int
|
addrSize :: p w -> Int
|
||||||
|
|
||||||
|
-- | @addrWidthMask w@ returns @2^(8 * addrSize w) - 1@.
|
||||||
|
addrWidthMask :: p w -> Word64
|
||||||
|
|
||||||
-- | Rotates the value by the given index.
|
-- | Rotates the value by the given index.
|
||||||
addrRotate :: MemWord w -> Int -> MemWord w
|
addrRotate :: MemWord w -> Int -> MemWord w
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user