Merge remote-tracking branch 'origin/feature/asl' into feature/asl

This commit is contained in:
Daniel Matichuk 2020-04-06 20:48:34 -07:00
commit a2ee426714
8 changed files with 83 additions and 38 deletions

View File

@ -30,6 +30,7 @@ library
, ansi-wl-pprint , ansi-wl-pprint
, asl-translator , asl-translator
, bytestring , bytestring
, bv-sized
, cereal , cereal
, containers , containers
, crucible , crucible

View File

@ -76,7 +76,6 @@ import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy as LBS
import Data.Macaw.ARM.ARMReg import Data.Macaw.ARM.ARMReg
import Data.Macaw.ARM.Arch() import Data.Macaw.ARM.Arch()
import Data.Macaw.AbsDomain.AbsState as MA
import Data.Macaw.CFG import Data.Macaw.CFG
import Data.Macaw.CFG.Block import Data.Macaw.CFG.Block
import qualified Data.Macaw.CFG.Core as MC import qualified Data.Macaw.CFG.Core as MC
@ -93,7 +92,6 @@ import qualified Dismantle.ARM.T32 as ThumbD
import Text.Printf ( printf ) import Text.Printf ( printf )
import qualified SemMC.Architecture.AArch32 as ARM import qualified SemMC.Architecture.AArch32 as ARM
import Debug.Trace
data InstructionSet = A32I ARMD.Instruction | T32I ThumbD.Instruction data InstructionSet = A32I ARMD.Instruction | T32I ThumbD.Instruction
deriving (Eq, Show) deriving (Eq, Show)
@ -185,8 +183,8 @@ disassembleBlock lookupSemantics gs curPCAddr blockOff maxOffset = do
Right (i, bytesRead) -> do Right (i, bytesRead) -> do
-- FIXME: Set PSTATE.T based on whether instruction is A32I or T32I -- FIXME: Set PSTATE.T based on whether instruction is A32I or T32I
-- traceM ("II: " ++ show i) -- traceM ("II: " ++ show i)
let curPC = MM.segmentOffAddr seg off -- let curPC = MM.segmentOffAddr seg off
nextPCOffset = off + bytesRead let nextPCOffset = off + bytesRead
nextPC = MM.segmentOffAddr seg nextPCOffset nextPC = MM.segmentOffAddr seg nextPCOffset
nextPCVal :: Value ARM.AArch32 ids (BVType 32) = MC.RelocatableValue (MM.addrWidthRepr curPCAddr) nextPC nextPCVal :: Value ARM.AArch32 ids (BVType 32) = MC.RelocatableValue (MM.addrWidthRepr curPCAddr) nextPC
-- curPCVal :: Value ARM.AArch32 ids (BVType 32) = MC.RelocatableValue (MM.addrWidthRepr curPCAddr) curPC -- curPCVal :: Value ARM.AArch32 ids (BVType 32) = MC.RelocatableValue (MM.addrWidthRepr curPCAddr) curPC
@ -241,18 +239,17 @@ readInstruction :: (MM.MemWidth w)
-> Either (ARMMemoryError w) (InstructionSet, MM.MemWord w) -> Either (ARMMemoryError w) (InstructionSet, MM.MemWord w)
readInstruction addr = do readInstruction addr = do
let seg = MM.segoffSegment addr let seg = MM.segoffSegment addr
segRelAddrRaw = MM.segoffAddr addr let segRelAddr = MM.segoffAddr addr
-- Addresses specified in ARM instructions have the low bit -- Addresses specified in ARM instructions have the low bit
-- clear, but Thumb (T32) target addresses have the low bit sit. -- clear, but Thumb (T32) target addresses have the low bit sit.
-- This is only manifested in the instruction addresses: the -- This is only manifested in the instruction addresses: the
-- actual PC for fetching instructions clears the low bit to -- actual PC for fetching instructions clears the low bit to
-- generate aligned memory accesses. -- generate aligned memory accesses.
loBit = MM.addrOffset segRelAddrRaw .&. 1 let alignedMsegOff = MM.clearSegmentOffLeastBit addr
segRelAddr = segRelAddrRaw { addrOffset = MM.addrOffset segRelAddrRaw `xor` loBit }
if MM.segmentFlags seg `MMP.hasPerm` MMP.execute if MM.segmentFlags seg `MMP.hasPerm` MMP.execute
then do then do
let ao = addrOffset segRelAddr -- traceM ("Orig addr = " ++ show addr ++ " modified to " ++ show ao)
alignedMsegOff <- liftMaybe (ARMInvalidInstructionAddress seg ao) (MM.resolveSegmentOff seg ao) -- alignedMsegOff <- liftMaybe (ARMInvalidInstructionAddress seg ao) (MM.resolveSegmentOff seg ao)
contents <- liftMemError $ MM.segoffContentsAfter alignedMsegOff contents <- liftMemError $ MM.segoffContentsAfter alignedMsegOff
case contents of case contents of
[] -> ET.throwError $ ARMMemoryError (MM.AccessViolation segRelAddr) [] -> ET.throwError $ ARMMemoryError (MM.AccessViolation segRelAddr)
@ -276,12 +273,6 @@ readInstruction addr = do
Nothing -> ET.throwError $ ARMInvalidInstruction segRelAddr contents Nothing -> ET.throwError $ ARMInvalidInstruction segRelAddr contents
else ET.throwError $ ARMMemoryError (MM.PermissionsError segRelAddr) else ET.throwError $ ARMMemoryError (MM.PermissionsError segRelAddr)
liftMaybe :: ARMMemoryError w -> Maybe a -> Either (ARMMemoryError w) a
liftMaybe err ma =
case ma of
Just a -> Right a
Nothing -> Left err
liftMemError :: Either (MM.MemoryError w) a -> Either (ARMMemoryError w) a liftMemError :: Either (MM.MemoryError w) a -> Either (ARMMemoryError w) a
liftMemError e = liftMemError e =
case e of case e of

View File

@ -10,7 +10,7 @@ module Data.Macaw.ARM.Identify
) where ) where
import Control.Lens ( (^.) ) import Control.Lens ( (^.) )
import Data.Macaw.ARM.Arch import qualified Data.Macaw.ARM.ARMReg as AR
import Data.Macaw.AbsDomain.AbsState ( AbsProcessorState import Data.Macaw.AbsDomain.AbsState ( AbsProcessorState
, AbsValue(..) , AbsValue(..)
, transferValue , transferValue
@ -18,6 +18,7 @@ import Data.Macaw.AbsDomain.AbsState ( AbsProcessorState
) )
import qualified Data.Macaw.CFG as MC import qualified Data.Macaw.CFG as MC
import qualified Data.Macaw.Memory as MM import qualified Data.Macaw.Memory as MM
import qualified Data.Macaw.SemMC.Simplify as MSS
import qualified Data.Macaw.Types as MT import qualified Data.Macaw.Types as MT
import Data.Semigroup import Data.Semigroup
import qualified Data.Sequence as Seq import qualified Data.Sequence as Seq
@ -42,8 +43,14 @@ identifyCall :: MM.Memory (MC.ArchAddrWidth ARM.AArch32)
-> Seq.Seq (MC.Stmt ARM.AArch32 ids) -> Seq.Seq (MC.Stmt ARM.AArch32 ids)
-> MC.RegState (MC.ArchReg ARM.AArch32) (MC.Value ARM.AArch32 ids) -> MC.RegState (MC.ArchReg ARM.AArch32) (MC.Value ARM.AArch32 ids)
-> Maybe (Seq.Seq (MC.Stmt ARM.AArch32 ids), MC.ArchSegmentOff ARM.AArch32) -> Maybe (Seq.Seq (MC.Stmt ARM.AArch32 ids), MC.ArchSegmentOff ARM.AArch32)
identifyCall _mem _stmts0 _rs = Nothing -- KWQ: for now, nothing is identified as a call identifyCall mem stmts0 rs
| not (null stmts0)
, MC.RelocatableValue {} <- rs ^. MC.boundValue AR.arm_LR
, Just retVal <- MSS.simplifyValue (rs ^. MC.boundValue AR.arm_LR)
, Just retAddrVal <- MC.valueAsMemAddr retVal
, Just retAddr <- MM.asSegmentOff mem retAddrVal =
Just (stmts0, retAddr)
| otherwise = Nothing
-- | Intended to identify a return statement. -- | Intended to identify a return statement.
-- --

View File

@ -25,14 +25,15 @@ import qualified Control.Monad.Except as E
import qualified Control.Monad.State.Strict as St import qualified Control.Monad.State.Strict as St
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Data.Functor.Const as C import qualified Data.Functor.Const as C
import qualified Data.Bits as B
import qualified Data.BitVector.Sized as BVS
import Data.List (isPrefixOf) import Data.List (isPrefixOf)
import Data.Macaw.SemMC.TH.Monad import Data.Macaw.SemMC.TH.Monad
import Data.Macaw.ARM.ARMReg import Data.Macaw.ARM.ARMReg
import Data.Macaw.ARM.Arch import Data.Macaw.ARM.Arch
import qualified Data.Macaw.CFG as M import qualified Data.Macaw.CFG as M
import qualified Data.Macaw.SemMC.Generator as G import qualified Data.Macaw.SemMC.Generator as G
import qualified Data.Macaw.SemMC.Operands as O import Data.Macaw.SemMC.TH ( addEltTH, appToExprTH, evalNonceAppTH, evalBoundVar, natReprTH, symFnName )
import Data.Macaw.SemMC.TH ( addEltTH, appToExprTH, evalNonceAppTH, evalBoundVar, natReprTH, symFnName, asName )
import Data.Macaw.SemMC.TH.Monad import Data.Macaw.SemMC.TH.Monad
import qualified Data.Macaw.Types as M import qualified Data.Macaw.Types as M
import qualified Data.Parameterized.Context as Ctx import qualified Data.Parameterized.Context as Ctx
@ -44,13 +45,11 @@ import Data.Parameterized.Some ( Some(..) )
import qualified Data.Parameterized.TraversableFC as FC import qualified Data.Parameterized.TraversableFC as FC
import Data.Proxy ( Proxy(..) ) import Data.Proxy ( Proxy(..) )
import GHC.TypeLits as TL import GHC.TypeLits as TL
import Data.Parameterized.NatRepr
import Language.Haskell.TH import Language.Haskell.TH
import Language.Haskell.TH.Syntax import Language.Haskell.TH.Syntax
import qualified SemMC.Architecture.AArch32 as ARM import qualified SemMC.Architecture.AArch32 as ARM
import qualified SemMC.Architecture.ARM.Opcodes as ARM import qualified SemMC.Architecture.ARM.Opcodes as ARM
import qualified SemMC.Architecture as A
import qualified SemMC.Architecture.ARM.Location as Loc
import qualified SemMC.Architecture.Location as L
import qualified What4.BaseTypes as WT import qualified What4.BaseTypes as WT
import qualified What4.Expr.Builder as WB import qualified What4.Expr.Builder as WB
@ -58,7 +57,6 @@ import qualified Data.Kind as Kind
import Numeric.Natural import Numeric.Natural
import qualified Language.ASL.Globals as ASL import qualified Language.ASL.Globals as ASL
import qualified Language.ASL.Globals.Definitions as ASL
loadSemantics :: IO (ARM.ASLSemantics) loadSemantics :: IO (ARM.ASLSemantics)
loadSemantics = ARM.loadSemantics (ARM.ASLSemanticsOpts { ARM.aslOptTrimRegs = True}) loadSemantics = ARM.loadSemantics (ARM.ASLSemanticsOpts { ARM.aslOptTrimRegs = True})
@ -155,12 +153,12 @@ armNonceAppEval bvi nonceApp =
case args of case args of
Ctx.Empty Ctx.:> assert Ctx.:> bv -> Just $ do Ctx.Empty Ctx.:> assert Ctx.:> bv -> Just $ do
assertTH <- addEltTH M.LittleEndian bvi assert assertTH <- addEltTH M.LittleEndian bvi assert
bv <- addEltTH M.LittleEndian bvi bv bvElt <- addEltTH M.LittleEndian bvi bv
liftQ [| case $(return assertTH) of liftQ [| case $(return assertTH) of
M.BoolValue True -> return $(return bv) M.BoolValue True -> return $(return bvElt)
M.BoolValue False -> E.throwError (G.GeneratorMessage $ "Bitvector length assertion failed!") M.BoolValue False -> E.throwError (G.GeneratorMessage $ "Bitvector length assertion failed!")
-- FIXME: THIS SHOULD THROW AN ERROR -- FIXME: THIS SHOULD THROW AN ERROR
_ -> return $(return bv) _ -> return $(return bvElt)
-- nm -> E.throwError (G.GeneratorMessage $ "Bitvector length assertion failed: <FIXME: PRINT NAME>") -- nm -> E.throwError (G.GeneratorMessage $ "Bitvector length assertion failed: <FIXME: PRINT NAME>")
|] |]
_ -> fail "Invalid call to assertBV" _ -> fail "Invalid call to assertBV"
@ -314,6 +312,25 @@ concreteIte v t f = case v of
M.CValue (M.BoolCValue b) -> if b then t else f M.CValue (M.BoolCValue b) -> if b then t else f
_ -> E.throwError (G.GeneratorMessage $ "concreteIte: requires concrete value" <> show (M.ppValueAssignments v)) _ -> E.throwError (G.GeneratorMessage $ "concreteIte: requires concrete value" <> show (M.ppValueAssignments v))
-- | A smart constructor for division
--
-- The smart constructor recognizes divisions that can be converted into shifts.
-- We convert the operation to a shift if the divisior is a power of two.
sdiv :: (1 <= n)
=> NatRepr n
-> M.Value ARM.AArch32 ids (M.BVType n)
-> M.Value ARM.AArch32 ids (M.BVType n)
-> G.Generator ARM.AArch32 ids s (G.Expr ARM.AArch32 ids (M.BVType n))
sdiv repr dividend divisor =
case divisor of
M.BVValue nr val
| bv <- BVS.bitVector' repr val
, BVS.bvPopCount bv == 1 ->
withKnownNat repr $
let app = M.BVSar nr dividend (M.BVValue nr (fromIntegral (B.countTrailingZeros bv)))
in (G.ValueExpr . M.AssignedValue) <$> G.addAssignment (M.EvalApp app)
_ -> addArchAssignment (SDiv repr dividend divisor)
armAppEvaluator :: M.Endianness armAppEvaluator :: M.Endianness
-> BoundVarInterpretations ARM.AArch32 t fs -> BoundVarInterpretations ARM.AArch32 t fs
-> WB.App (WB.Expr t) ctp -> WB.App (WB.Expr t) ctp
@ -328,8 +345,7 @@ armAppEvaluator endianness interps elt =
WB.BVSdiv w bv1 bv2 -> return $ do WB.BVSdiv w bv1 bv2 -> return $ do
e1 <- addEltTH endianness interps bv1 e1 <- addEltTH endianness interps bv1
e2 <- addEltTH endianness interps bv2 e2 <- addEltTH endianness interps bv2
liftQ [| addArchAssignment (SDiv $(natReprTH w) $(return e1) $(return e2)) liftQ [| sdiv $(natReprTH w) $(return e1) $(return e2) |]
|]
WB.BVUrem w bv1 bv2 -> return $ do WB.BVUrem w bv1 bv2 -> return $ do
e1 <- addEltTH endianness interps bv1 e1 <- addEltTH endianness interps bv1
e2 <- addEltTH endianness interps bv2 e2 <- addEltTH endianness interps bv2

Binary file not shown.

View File

@ -0,0 +1,10 @@
R { funcs = [ (0x100d8, [(0x100d8, 48)])
, (0x1010c, [ (0x1010c, 32)
, (0x1012c, 12)
])
, (0x10138, [ (0x10138, 28)
, (0x10154, 4)
])
]
, ignoreBlocks = [0x10158]
}

View File

@ -1,4 +0,0 @@
R { funcs = [ (0x8001, [(0x8001, 6), (0x8007,10)])
]
, ignoreBlocks = []
}

View File

@ -52,6 +52,7 @@ simplifyApp a =
BVOr sz l r -> binopbv (.|.) sz l r BVOr sz l r -> binopbv (.|.) sz l r
BVShl sz l r -> binopbv (\l' r' -> shiftL l' (fromIntegral r')) sz l r BVShl sz l r -> binopbv (\l' r' -> shiftL l' (fromIntegral r')) sz l r
BVShr sz l r -> binopbv (\l' r' -> shiftR l' (fromIntegral r')) sz l r BVShr sz l r -> binopbv (\l' r' -> shiftR l' (fromIntegral r')) sz l r
BVSar sz l r -> binopbv (\l' r' -> shiftR (toSigned sz l') (fromIntegral (toSigned sz r'))) sz l r
BVAdd _ l (BVValue _ 0) -> Just l BVAdd _ l (BVValue _ 0) -> Just l
BVAdd _ (BVValue _ 0) r -> Just r BVAdd _ (BVValue _ 0) r -> Just r
BVAdd rep l@(BVValue {}) r@(RelocatableValue {}) -> BVAdd rep l@(BVValue {}) r@(RelocatableValue {}) ->
@ -66,10 +67,17 @@ simplifyApp a =
BVMul rep l r -> binopbv (*) rep l r BVMul rep l r -> binopbv (*) rep l r
SExt (BVValue u n) sz -> Just (BVValue sz (toUnsigned sz (toSigned u n))) SExt (BVValue u n) sz -> Just (BVValue sz (toUnsigned sz (toSigned u n)))
UExt (BVValue _ n) sz -> Just (mkLit sz n) UExt (BVValue _ n) sz -> Just (mkLit sz n)
UExt (RelocatableValue _arep addr) sz -> do
memword <- MM.asAbsoluteAddr addr
return $ mkLit sz (fromIntegral memword)
Trunc (BVValue _ x) sz -> Just (mkLit sz x) Trunc (BVValue _ x) sz -> Just (mkLit sz x)
Eq l r -> boolop (==) l r Eq l r -> boolop (==) l r
BVComplement sz x -> unop complement sz x BVComplement sz x -> unop complement sz x
BVSignedLe v1 v2 -> signedRelOp (<=) v1 v2
BVSignedLt v1 v2 -> signedRelOp (<) v1 v2
BVUnsignedLe v1 v2 -> unsignedRelOp (<=) v1 v2
BVUnsignedLt v1 v2 -> unsignedRelOp (<) v1 v2
_ -> Nothing _ -> Nothing
where where
unop :: forall n . (tp ~ BVType n) unop :: forall n . (tp ~ BVType n)
@ -97,3 +105,19 @@ simplifyApp a =
binopbv f sz (BVValue _ l) (BVValue _ r) = binopbv f sz (BVValue _ l) (BVValue _ r) =
Just (mkLit sz (f l r)) Just (mkLit sz (f l r))
binopbv _ _ _ _ = Nothing binopbv _ _ _ _ = Nothing
signedRelOp :: forall n
. (Integer -> Integer -> Bool)
-> Value arch ids (BVType n)
-> Value arch ids (BVType n)
-> Maybe (Value arch ids BoolType)
signedRelOp op (BVValue r1 v1) (BVValue _ v2) =
Just (BoolValue (op (toSigned r1 v1) (toSigned r1 v2)))
signedRelOp _ _ _ = Nothing
unsignedRelOp :: forall n
. (Integer -> Integer -> Bool)
-> Value arch ids (BVType n)
-> Value arch ids (BVType n)
-> Maybe (Value arch ids BoolType)
unsignedRelOp op (BVValue r1 v1) (BVValue _ v2) =
Just (BoolValue (op (toUnsigned r1 v1) (toUnsigned r1 v2)))
unsignedRelOp _ _ _ = Nothing