Merge branch 'master' of github.com:GaloisInc/macaw

This commit is contained in:
Joe Hendrix 2018-07-27 00:28:50 -07:00
commit e4a27d7bbc
No known key found for this signature in database
GPG Key ID: 8DFA5FF784098C4F
5 changed files with 189 additions and 98 deletions

View File

@ -817,8 +817,21 @@ parseVariable :: V.Vector FilePath
-> Map DieID Type -> Map DieID Type
-> DIE -> DIE
-> Parser Variable -> Parser Variable
parseVariable file_vec typeMap d = runDIEParser "parseVariable" d $ do parseVariable = parseVariableOrParameter DW_TAG_variable
checkTag DW_TAG_variable
parseParameter :: V.Vector FilePath
-> Map DieID Type
-> DIE
-> Parser Variable
parseParameter = parseVariableOrParameter DW_TAG_formal_parameter
parseVariableOrParameter :: Dwarf.DW_TAG
-> V.Vector FilePath
-> Map DieID Type
-> DIE
-> Parser Variable
parseVariableOrParameter tag file_vec typeMap d = runDIEParser "parseVariable" d $ do
checkTag tag
mloc <- getMaybeAttribute DW_AT_location $ \case mloc <- getMaybeAttribute DW_AT_location $ \case
DW_ATVAL_BLOB b -> ComputedLoc <$> parseDwarfExpr b DW_ATVAL_BLOB b -> ComputedLoc <$> parseDwarfExpr b
@ -911,6 +924,8 @@ data Subprogram = Subprogram { subExternal :: !Bool
, subPrototyped :: !Bool , subPrototyped :: !Bool
, subDef :: !(Maybe SubprogramDef) , subDef :: !(Maybe SubprogramDef)
, subVars :: !(Map DieID Variable) , subVars :: !(Map DieID Variable)
, subParams :: !(Map DieID Variable)
, subRetType :: !(Maybe Type)
} }
@ -923,6 +938,8 @@ instance Pretty Subprogram where
, text "prototyped: " <+> text (show (subPrototyped sub)) , text "prototyped: " <+> text (show (subPrototyped sub))
, maybe (text "") pretty (subDef sub) , maybe (text "") pretty (subDef sub)
, ppList "variables" (pretty <$> Map.elems (subVars sub)) , ppList "variables" (pretty <$> Map.elems (subVars sub))
, ppList "parameters" (pretty <$> Map.elems (subParams sub))
, text "return type: " <+> text (show (subRetType sub))
] ]
instance Show Subprogram where instance Show Subprogram where
@ -963,6 +980,10 @@ parseSubprogram file_vec typeMap d = runDIEParser "parseSubprogram" d $ do
typeMap' <- Map.union typeMap <$> parseTypeMap file_vec typeMap' <- Map.union typeMap <$> parseTypeMap file_vec
vars <- parseChildrenList DW_TAG_variable (parseVariable file_vec typeMap') vars <- parseChildrenList DW_TAG_variable (parseVariable file_vec typeMap')
params <- parseChildrenList DW_TAG_formal_parameter $
parseParameter file_vec typeMap'
retType <- getMaybeAttribute DW_AT_type $
parseType typeMap' <=< attributeAsDieID
ignoreAttribute DW_AT_GNU_all_tail_call_sites ignoreAttribute DW_AT_GNU_all_tail_call_sites
ignoreAttribute DW_AT_sibling ignoreAttribute DW_AT_sibling
@ -979,6 +1000,8 @@ parseSubprogram file_vec typeMap d = runDIEParser "parseSubprogram" d $ do
, subPrototyped = fromMaybe False prototyped , subPrototyped = fromMaybe False prototyped
, subDef = def , subDef = def
, subVars = Map.fromList [ (varDieID v, v) | v <- vars ] , subVars = Map.fromList [ (varDieID v, v) | v <- vars ]
, subParams = Map.fromList [ (varDieID p, p) | p <- params ]
, subRetType = retType
} }
------------------------------------------------------------------------ ------------------------------------------------------------------------

View File

@ -43,28 +43,28 @@ newtype BlockIndex = BlockIndex Word64
newtype AssignId ids (tp::Type) = AssignId (Nonce ids tp) newtype AssignId ids (tp::Type) = AssignId (Nonce ids tp)
data Value arch ids tp where data Value arch ids tp where
-- | A constant bitvector
--
-- The integer should be between 0 and 2^n-1.
BVValue :: (1 <= n) BVValue :: (1 <= n)
=> !(NatRepr n) => !(NatRepr n)
-> !Integer -> !Integer
-> Value arch ids (BVType n) -> Value arch ids (BVType n)
-- ^ A constant bitvector -- | A constant Boolean
--
-- The integer should be between 0 and 2^n-1.
BoolValue :: !Bool -> Value arch ids BoolType BoolValue :: !Bool -> Value arch ids BoolType
-- ^ A constant Boolean -- | A memory address
RelocatableValue :: !(AddrWidthRepr (ArchAddrWidth arch)) RelocatableValue :: !(AddrWidthRepr (ArchAddrWidth arch))
-> !(ArchMemAddr arch) -> !(ArchMemAddr arch)
-> Value arch ids (BVType (ArchAddrWidth arch)) -> Value arch ids (BVType (ArchAddrWidth arch))
-- ^ A memory address -- | Reference to a symbol identifier.
--
-- This appears when dealing with relocations.
SymbolValue :: !(AddrWidthRepr (ArchAddrWidth arch)) SymbolValue :: !(AddrWidthRepr (ArchAddrWidth arch))
-> !SymbolIdentifier -> !SymbolIdentifier
-> Value arch ids (BVType (ArchAddrWidth arch)) -> Value arch ids (BVType (ArchAddrWidth arch))
-- ^ Reference to a symbol identifier. -- | Value from an assignment statement.
--
-- This appears when dealing with relocations.
AssignedValue :: !(AssignId ids tp) AssignedValue :: !(AssignId ids tp)
-> Value arch ids tp -> Value arch ids tp
-- ^ Value from an assignment statement.
type BVValue arch ids w = Value arch ids (BVType w) type BVValue arch ids w = Value arch ids (BVType w)
@ -75,26 +75,26 @@ data Stmt arch ids where
AssignStmt :: !(AssignId ids tp) AssignStmt :: !(AssignId ids tp)
-> !(AssignRhs arch (Value arch ids) tp) -> !(AssignRhs arch (Value arch ids) tp)
-> Stmt arch ids -> Stmt arch ids
-- | This denotes a write to memory, and consists of an address to write to, a `MemRepr` defining
-- how the value should be stored in memory, and the value to be written.
WriteMem :: !(ArchAddrValue arch ids) WriteMem :: !(ArchAddrValue arch ids)
-> !(MemRepr tp) -> !(MemRepr tp)
-> !(Value arch ids tp) -> !(Value arch ids tp)
-> Stmt arch ids -> Stmt arch ids
-- ^ This denotes a write to memory, and consists of an address to write to, a `MemRepr` defining -- | The start of an instruction
-- how the value should be stored in memory, and the value to be written.
InstructionStart :: !(ArchAddrWord arch)
-> !Text
-> Stmt arch ids
-- ^ The start of an instruction
-- --
-- The information includes the offset relative to the start of the block and the -- The information includes the offset relative to the start of the block and the
-- disassembler output if available (or empty string if unavailable) -- disassembler output if available (or empty string if unavailable)
InstructionStart :: !(ArchAddrWord arch)
-> !Text
-> Stmt arch ids
-- | A user-level comment
Comment :: !Text -> Stmt arch ids Comment :: !Text -> Stmt arch ids
-- ^ A user-level comment -- | Execute an architecture specific statement
ExecArchStmt :: !(ArchStmt arch (Value arch ids)) -> Stmt arch ids ExecArchStmt :: !(ArchStmt arch (Value arch ids)) -> Stmt arch ids
-- ^ Execute an architecture specific statement -- /\ A call statement.
-- RegCall :: !(RegState (ArchReg arch) (Value arch ids)) -- RegCall :: !(RegState (ArchReg arch) (Value arch ids))
-- -> Stmt arch ids -- -> Stmt arch ids
-- ^ A call statement.
-- | This is a calling convention that explains how the linear list of -- | This is a calling convention that explains how the linear list of
-- arguments should be stored for the ABI. -- arguments should be stored for the ABI.
@ -104,39 +104,39 @@ type family CallingConvention arch
-- of how block ending with a a FetchAndExecute statement should be -- of how block ending with a a FetchAndExecute statement should be
-- interpreted. -- interpreted.
data TermStmt arch ids where data TermStmt arch ids where
-- | A call with the current register values and location to return to or 'Nothing' if this is a tail call.
TailCall :: !(CallingConvention arch) TailCall :: !(CallingConvention arch)
-> !(BVValue arch ids (ArchAddrWidth arch)) -> !(BVValue arch ids (ArchAddrWidth arch))
-- /\ IP to call -- /\ IP to call
-> ![Some (Value arch ids)] -> ![Some (Value arch ids)]
-> TermStmt arch ids -> TermStmt arch ids
-- ^ A call with the current register values and location to return to or 'Nothing' if this is a tail call. -- | A jump to an explicit address within a function.
Jump :: !BlockIndex Jump :: !BlockIndex
-> TermStmt arch ids -> TermStmt arch ids
-- ^ A jump to an explicit address within a function. -- | A lookup table that branches to one of a vector of addresses.
LookupTable :: !(BVValue arch ids (ArchAddrWidth arch))
-> !(V.Vector BlockIndex)
-> TermStmt arch ids
-- ^ A lookup table that branches to one of a vector of addresses.
-- --
-- The value contains the index to jump to as an unsigned bitvector, and the -- The value contains the index to jump to as an unsigned bitvector, and the
-- possible addresses as a table. If the index (when interpreted as -- possible addresses as a table. If the index (when interpreted as
-- an unsigned number) is larger than the number of entries in the vector, then the -- an unsigned number) is larger than the number of entries in the vector, then the
-- result is undefined. -- result is undefined.
LookupTable :: !(BVValue arch ids (ArchAddrWidth arch))
-> !(V.Vector BlockIndex)
-> TermStmt arch ids
-- | A return with the given registers.
Return :: !(MapF (ArchReg arch) (Value arch ids)) Return :: !(MapF (ArchReg arch) (Value arch ids))
-> TermStmt arch ids -> TermStmt arch ids
-- ^ A return with the given registers. -- | An if-then-else
Ite :: !(Value arch ids BoolType) Ite :: !(Value arch ids BoolType)
-> !BlockIndex -> !BlockIndex
-> !BlockIndex -> !BlockIndex
-> TermStmt arch ids -> TermStmt arch ids
-- ^ An if-then-else -- | An architecture-specific statement with the registers prior to execution, and
-- the given next control flow address.
ArchTermStmt :: !(ArchTermStmt arch ids) ArchTermStmt :: !(ArchTermStmt arch ids)
-> !(MapF (ArchReg arch) (Value arch ids)) -> !(MapF (ArchReg arch) (Value arch ids))
-> !(MapF (ArchReg arch) (Value arch ids)) -> !(MapF (ArchReg arch) (Value arch ids))
-> !(Maybe BlockIndex) -> !(Maybe BlockIndex)
-> TermStmt arch ids -> TermStmt arch ids
-- ^ An architecture-specific statement with the registers prior to execution, and
-- the given next control flow address.
data SCFGBlock arch ids data SCFGBlock arch ids

View File

@ -36,7 +36,7 @@ module Data.Macaw.Symbolic
, Data.Macaw.Symbolic.CrucGen.MacawArchConstraints , Data.Macaw.Symbolic.CrucGen.MacawArchConstraints
, MacawArchEvalFn , MacawArchEvalFn
, EvalStmtFunc , EvalStmtFunc
, LookupFunctionHandle , LookupFunctionHandle(..)
, Regs , Regs
, freshValue , freshValue
, GlobalMap , GlobalMap
@ -84,7 +84,6 @@ import Data.Macaw.Symbolic.CrucGen
import Data.Macaw.Symbolic.PersistentState import Data.Macaw.Symbolic.PersistentState
import Data.Macaw.Symbolic.MemOps import Data.Macaw.Symbolic.MemOps
data MacawSimulatorState sym = MacawSimulatorState
{- {-
mkMemSegmentBinding :: (1 <= w) mkMemSegmentBinding :: (1 <= w)
@ -391,21 +390,16 @@ type EvalStmtFunc f p sym ext =
type MacawArchEvalFn sym arch = type MacawArchEvalFn sym arch =
EvalStmtFunc (MacawArchStmtExtension arch) (MacawSimulatorState sym) sym (MacawExt arch) EvalStmtFunc (MacawArchStmtExtension arch) (MacawSimulatorState sym) sym (MacawExt arch)
type Regs sym arch = Ctx.Assignment (C.RegValue' sym)
(MacawCrucibleRegTypes arch)
type LookupFunctionHandle sym arch =
MM.MemImpl sym -> Regs sym arch -> IO (C.FnHandle (Ctx.EmptyCtx Ctx.::> ArchRegStruct arch) (ArchRegStruct arch))
-- | This evaluates a Macaw statement extension in the simulator. -- | This evaluates a Macaw statement extension in the simulator.
execMacawStmtExtension :: execMacawStmtExtension ::
IsSymInterface sym => IsSymInterface sym =>
MacawArchEvalFn sym arch {- ^ Function for executing -} -> MacawArchEvalFn sym arch {- ^ Function for executing -} ->
C.GlobalVar MM.Mem -> C.GlobalVar MM.Mem ->
GlobalMap sym arch -> GlobalMap sym (M.ArchAddrWidth arch) ->
LookupFunctionHandle sym arch -> LookupFunctionHandle sym arch ->
EvalStmtFunc (MacawStmtExtension arch) (MacawSimulatorState sym) sym (MacawExt arch) EvalStmtFunc (MacawStmtExtension arch) (MacawSimulatorState sym) sym (MacawExt arch)
execMacawStmtExtension archStmtFn mvar globs lookupH s0 st = execMacawStmtExtension archStmtFn mvar globs (LFH lookupH) s0 st =
case s0 of case s0 of
MacawReadMem w mr x -> doReadMem st mvar globs w mr x MacawReadMem w mr x -> doReadMem st mvar globs w mr x
MacawCondReadMem w mr p x d -> doCondReadMem st mvar globs w mr p x d MacawCondReadMem w mr p x d -> doCondReadMem st mvar globs w mr p x d
@ -424,8 +418,8 @@ execMacawStmtExtension archStmtFn mvar globs lookupH s0 st =
where sym = st^.C.stateSymInterface where sym = st^.C.stateSymInterface
MacawLookupFunctionHandle _ args -> do MacawLookupFunctionHandle _ args -> do
hv <- C.HandleFnVal <$> doLookupFunctionHandle lookupH st mvar (C.regValue args) (hv, st') <- doLookupFunctionHandle lookupH st mvar (C.regValue args)
return (hv, st) return (C.HandleFnVal hv, st')
MacawArchStmtExtension s -> archStmtFn s st MacawArchStmtExtension s -> archStmtFn s st
MacawArchStateUpdate {} -> return ((), st) MacawArchStateUpdate {} -> return ((), st)
@ -489,7 +483,7 @@ macawExtensions ::
IsSymInterface sym => IsSymInterface sym =>
MacawArchEvalFn sym arch -> MacawArchEvalFn sym arch ->
C.GlobalVar MM.Mem -> C.GlobalVar MM.Mem ->
GlobalMap sym arch -> GlobalMap sym (M.ArchAddrWidth arch) ->
LookupFunctionHandle sym arch -> LookupFunctionHandle sym arch ->
C.ExtensionImpl (MacawSimulatorState sym) sym (MacawExt arch) C.ExtensionImpl (MacawSimulatorState sym) sym (MacawExt arch)
macawExtensions f mvar globs lookupH = macawExtensions f mvar globs lookupH =
@ -497,13 +491,6 @@ macawExtensions f mvar globs lookupH =
, C.extensionExec = execMacawStmtExtension f mvar globs lookupH , C.extensionExec = execMacawStmtExtension f mvar globs lookupH
} }
-- | Maps region indexes to the pointers representing them.
type GlobalMap sym arch = Map M.RegionIndex
(MM.LLVMPtr sym (M.ArchAddrWidth arch))
-- | Run the simulator over a contiguous set of code. -- | Run the simulator over a contiguous set of code.
runCodeBlock :: forall sym arch blocks runCodeBlock :: forall sym arch blocks
. (C.IsSyntaxExtension (MacawExt arch), IsSymInterface sym) . (C.IsSyntaxExtension (MacawExt arch), IsSymInterface sym)
@ -512,7 +499,7 @@ runCodeBlock :: forall sym arch blocks
-- ^ Translation functions -- ^ Translation functions
-> MacawArchEvalFn sym arch -> MacawArchEvalFn sym arch
-> C.HandleAllocator RealWorld -> C.HandleAllocator RealWorld
-> (MM.MemImpl sym, GlobalMap sym arch) -> (MM.MemImpl sym, GlobalMap sym (M.ArchAddrWidth arch))
-> LookupFunctionHandle sym arch -> LookupFunctionHandle sym arch
-> C.CFG (MacawExt arch) blocks (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch) -> C.CFG (MacawExt arch) blocks (EmptyCtx ::> ArchRegStruct arch) (ArchRegStruct arch)
-> Ctx.Assignment (C.RegValue' sym) (MacawCrucibleRegTypes arch) -> Ctx.Assignment (C.RegValue' sym) (MacawCrucibleRegTypes arch)

View File

@ -11,6 +11,7 @@
{-# Language PatternGuards #-} {-# Language PatternGuards #-}
module Data.Macaw.Symbolic.MemOps module Data.Macaw.Symbolic.MemOps
( PtrOp ( PtrOp
, GlobalMap
, doPtrAdd , doPtrAdd
, doPtrSub , doPtrSub
, doPtrMux , doPtrMux
@ -24,21 +25,26 @@ module Data.Macaw.Symbolic.MemOps
, doGetGlobal , doGetGlobal
, doLookupFunctionHandle , doLookupFunctionHandle
, doPtrToBits , doPtrToBits
, Regs
, MacawSimulatorState(..)
, LookupFunctionHandle(..)
) where ) where
import Control.Lens ((^.),(&),(%~)) import Control.Lens ((^.),(&),(%~))
import Control.Monad (guard) import Control.Monad (guard)
import Data.Bits (testBit) import Data.Bits (testBit)
import Data.Map (Map) import Data.Maybe ( fromMaybe )
import qualified Data.Map as Map
import Data.Parameterized (Some(..)) import Data.Parameterized (Some(..))
import qualified Data.Parameterized.Context as Ctx
import What4.Interface import What4.Interface
import What4.Symbol (userSymbol) import What4.Symbol (userSymbol)
import Lang.Crucible.Backend import Lang.Crucible.Backend
import Lang.Crucible.CFG.Common (GlobalVar) import Lang.Crucible.CFG.Common (GlobalVar)
import qualified Lang.Crucible.FunctionHandle as C
import qualified Lang.Crucible.Simulator.RegMap as C
import Lang.Crucible.Simulator.ExecutionTree import Lang.Crucible.Simulator.ExecutionTree
( CrucibleState ( CrucibleState
, stateSymInterface , stateSymInterface
@ -58,7 +64,6 @@ import Lang.Crucible.LLVM.MemModel
, loadRaw , loadRaw
, loadRawWithCondition , loadRawWithCondition
, storeRaw , storeRaw
, doPtrAddOffset
) )
import Lang.Crucible.LLVM.MemModel.Pointer import Lang.Crucible.LLVM.MemModel.Pointer
( llvmPointerView, muxLLVMPtr, llvmPointer_bv, ptrAdd, ptrSub, ptrEq ( llvmPointerView, muxLLVMPtr, llvmPointer_bv, ptrAdd, ptrSub, ptrEq
@ -70,10 +75,69 @@ import Lang.Crucible.LLVM.MemModel.Generic (ppPtr)
import Lang.Crucible.LLVM.DataLayout (EndianForm(..)) import Lang.Crucible.LLVM.DataLayout (EndianForm(..))
import Lang.Crucible.LLVM.Bytes (toBytes) import Lang.Crucible.LLVM.Bytes (toBytes)
import Data.Macaw.Symbolic.CrucGen (addrWidthIsPos) import Data.Macaw.Symbolic.CrucGen (addrWidthIsPos, ArchRegStruct, MacawExt, MacawCrucibleRegTypes)
import Data.Macaw.Symbolic.PersistentState (ToCrucibleType) import Data.Macaw.Symbolic.PersistentState (ToCrucibleType)
import Data.Macaw.CFG.Core (MemRepr(BVMemRepr)) import Data.Macaw.CFG.Core (MemRepr(BVMemRepr))
import qualified Data.Macaw.Memory as M import qualified Data.Macaw.CFG as M
-- | The 'GlobalMap' is a function that maps from (possibly segmented) program
-- virtual addresses into pointers into the LLVM memory model heap (the
-- 'LLVMPtr' type).
--
-- There are two types of value translated here:
--
-- 1. Bitvectors treated as pointers, and
-- 2. Segmented addresses (e.g., from object files or shared libraries)
--
-- To set up the memory model to verify parts of a program, callers need to
-- allocate regions of memory to store data including the initial program state.
-- The user-facing API for allocating memory is the 'doMalloc' primitive from
-- Lang.Crucible.LLVM.MemModel. This allocates fresh memory that is distinct
-- from all other memory in the system. The distinctness is guaranteed because
-- each allocation has a unique region identifier. Each freshly allocated
-- region of memory has a base address of zero and a size.
--
-- In a machine code program, there are a few different kinds of memory to map
-- into the address space: 1) a *stack*, 2) the *data* segment, 3) and the
-- program *text* segment.
--
-- The *stack* should be logically separate from everything else, so an
-- allocation with 'doMalloc' is natural. It is the responsibility of the
-- caller to place the pointer to the stack (that is the LLVM memory model
-- pointer) into the appropriate register in the machine state for their
-- architecture.
--
-- The *data* and *text* segments are static data in the original binary image
-- being analyzed. They are usually disjoint, so it usually makes sense to
-- allocate one region of memory for each one using 'doMalloc'. To resolve a
-- computed address (which will be a bitvector, i.e., an LLVMPtr value with a
-- zero region index) that refers to either, a typical workflow in the
-- 'GlobalMap' function is:
--
-- 1. Inspect the region index (the @'RegValue' sym 'NatType'@ parameter)
-- 2. If the region index is zero, it is a bitvector to translate into an
-- LLVM memory model pointer ('LLVMPtr')
-- 3. Look up the offset of the pointer from zero (the @'RegValue' sym ('BVType'
-- w)@) in a map (probably an IntervalMap); that map should return the base
-- address of the allocation (which is an 'LLVMPtr')
-- 4. Depending on the representation of that pointer chosen by the
-- frontend/setup code, the 'LLVMPtr' may need to be corrected to rebase it,
-- as the segment being represented by that allocation may not actually start
-- at address 0 (while the LLVM offset does start at 0).
--
-- That discussion describes the translation of raw bitvectors into pointers.
-- This mapping is also used in another case (see 'doGetGlobal'): translating
-- the address of a relocatable value (which doesn't necessarily have a
-- well-defined absolute address) into an address in the LLVM memory model.
-- Relocatable values in this setting have a non-zero region index as an input.
-- The 'GlobalMap' is responsible for 1) determining which LLVM allocation
-- contains the relocatable value, and 2) returning the corresponding address in
-- that allocation.
type GlobalMap sym w = sym {-^ The symbolic backend -} ->
RegValue sym Mem {-^ The global handle to the memory model -} ->
RegValue sym NatType {-^ The region index of the pointer being translated -} ->
RegValue sym (BVType w) {-^ The offset of the pointer into the region -} ->
IO (Maybe (LLVMPtr sym w))
-- | This is called whenever a (bit-vector/pointer) is used as a bit-vector. -- | This is called whenever a (bit-vector/pointer) is used as a bit-vector.
-- The result is undefined (i.e., a fresh unknown value) if it is given -- The result is undefined (i.e., a fresh unknown value) if it is given
@ -90,16 +154,28 @@ doPtrToBits sym w p =
notPtr <- natEq sym base =<< natLit sym 0 notPtr <- natEq sym base =<< natLit sym 0
bvIte sym notPtr (asBits p) undef bvIte sym notPtr (asBits p) undef
data MacawSimulatorState sym = MacawSimulatorState
type Regs sym arch = Ctx.Assignment (C.RegValue' sym)
(MacawCrucibleRegTypes arch)
data LookupFunctionHandle sym arch = LFH
(forall rtp blocks r ctx
. CrucibleState (MacawSimulatorState sym) sym (MacawExt arch) rtp blocks r ctx
-> MemImpl sym
-> Regs sym arch
-> IO (C.FnHandle (Ctx.EmptyCtx Ctx.::> ArchRegStruct arch) (ArchRegStruct arch), CrucibleState (MacawSimulatorState sym) sym (MacawExt arch) rtp blocks r ctx))
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
doLookupFunctionHandle :: (IsSymInterface sym) doLookupFunctionHandle :: (IsSymInterface sym)
=> (MemImpl sym -> regs -> IO a) => (CrucibleState s sym ext trp blocks r ctx -> MemImpl sym -> regs -> IO (a, CrucibleState s sym ext trp blocks r ctx))
-> CrucibleState s sym ext trp blocks r ctx -> CrucibleState s sym ext trp blocks r ctx
-> GlobalVar Mem -> GlobalVar Mem
-> regs -> regs
-> IO a -> IO (a, CrucibleState s sym ext trp blocks r ctx)
doLookupFunctionHandle k st mvar regs = do doLookupFunctionHandle k st mvar regs = do
mem <- getMem st mvar mem <- getMem st mvar
k mem regs k st mem regs
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -112,27 +188,36 @@ doGetGlobal ::
(IsSymInterface sym, M.MemWidth w) => (IsSymInterface sym, M.MemWidth w) =>
CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} -> CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} ->
GlobalVar Mem {- ^ Model of memory -} -> GlobalVar Mem {- ^ Model of memory -} ->
Map M.RegionIndex (RegValue sym (LLVMPointerType w)) {- ^ Region ptrs -} -> GlobalMap sym w ->
M.MemAddr w {- ^ Address identifier -} -> M.MemAddr w {- ^ Address identifier -} ->
IO ( RegValue sym (LLVMPointerType w) IO ( RegValue sym (LLVMPointerType w)
, CrucibleState s sym ext rtp blocks r ctx , CrucibleState s sym ext rtp blocks r ctx
) )
doGetGlobal st mvar globs addr = doGetGlobal st mvar globs addr = do
case Map.lookup (M.addrBase addr) globs of let sym = st^.stateSymInterface
mem <- getMem st mvar
regionNum <- natLit sym (fromIntegral (M.addrBase addr))
offset <- bvLit sym (M.addrWidthNatRepr (M.addrWidthRepr addr)) (M.memWordInteger (M.addrOffset addr))
mptr <- globs sym mem regionNum offset
case mptr of
Nothing -> fail $ unlines Nothing -> fail $ unlines
[ "[doGetGlobal] Undefined global region:" [ "[doGetGlobal] Undefined global region:"
, "*** Region: " ++ show (M.addrBase addr) , "*** Region: " ++ show (M.addrBase addr)
, "*** Address: " ++ show addr , "*** Address: " ++ show addr
] ]
Just region -> -- <<<<<<< HEAD
do mem <- getMem st mvar Just ptr -> return (ptr, st)
let sym = st^.stateSymInterface -- =======
let w = M.addrWidthRepr addr -- Just region ->
LeqProof <- pure $ addrWidthAtLeast16 w -- do mem <- getMem st mvar
let ?ptrWidth = M.addrWidthNatRepr w -- let sym = st^.stateSymInterface
off <- bvLit sym ?ptrWidth (M.memWordInteger (M.addrOffset addr)) -- let w = M.addrWidthRepr addr
res <- doPtrAddOffset sym mem region off -- LeqProof <- pure $ addrWidthAtLeast16 w
return (res, st) -- let ?ptrWidth = M.addrWidthNatRepr w
-- off <- bvLit sym ?ptrWidth (M.memWordInteger (M.addrOffset addr))
-- res <- doPtrAddOffset sym mem region off
-- return (res, st)
-- >>>>>>> master
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -317,7 +402,7 @@ doReadMem ::
IsSymInterface sym => IsSymInterface sym =>
CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} -> CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} ->
GlobalVar Mem -> GlobalVar Mem ->
Map M.RegionIndex (RegValue sym (LLVMPointerType ptrW)) {- ^ Region ptrs -} -> GlobalMap sym ptrW ->
M.AddrWidthRepr ptrW -> M.AddrWidthRepr ptrW ->
MemRepr ty -> MemRepr ty ->
RegEntry sym (LLVMPointerType ptrW) -> RegEntry sym (LLVMPointerType ptrW) ->
@ -333,8 +418,7 @@ doReadMem st mvar globs w (BVMemRepr bytes endian) ptr0 =
bitw = natMultiply (knownNat @8) bytes bitw = natMultiply (knownNat @8) bytes
LeqProof <- return (leqMulPos (knownNat @8) bytes) LeqProof <- return (leqMulPos (knownNat @8) bytes)
ptr <- tryGlobPtr sym mem globs (regValue ptr0)
ptr <- tryGlobPtr sym mem globs w (regValue ptr0)
let ?ptrWidth = M.addrWidthNatRepr w let ?ptrWidth = M.addrWidthNatRepr w
ok <- isValidPtr sym mem w ptr ok <- isValidPtr sym mem w ptr
@ -347,7 +431,6 @@ doReadMem st mvar globs w (BVMemRepr bytes endian) ptr0 =
a <- case valToBits bitw val of a <- case valToBits bitw val of
Just a -> return a Just a -> return a
Nothing -> fail "[doReadMem] We read an unexpected value" Nothing -> fail "[doReadMem] We read an unexpected value"
return (a,st) return (a,st)
@ -356,7 +439,7 @@ doCondReadMem ::
IsSymInterface sym => IsSymInterface sym =>
CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} -> CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} ->
GlobalVar Mem {- ^ Memory model -} -> GlobalVar Mem {- ^ Memory model -} ->
Map M.RegionIndex (RegValue sym (LLVMPointerType ptrW)) {- ^ Region ptrs -} -> GlobalMap sym ptrW {- ^ Translate machine addresses to memory model addresses -} ->
M.AddrWidthRepr ptrW {- ^ Width of ptr -} -> M.AddrWidthRepr ptrW {- ^ Width of ptr -} ->
MemRepr ty {- ^ What/how we are reading -} -> MemRepr ty {- ^ What/how we are reading -} ->
RegEntry sym BoolType {- ^ Condition -} -> RegEntry sym BoolType {- ^ Condition -} ->
@ -376,7 +459,7 @@ doCondReadMem st mvar globs w (BVMemRepr bytes endian) cond0 ptr0 def0 =
LeqProof <- return (leqMulPos (knownNat @8) bytes) LeqProof <- return (leqMulPos (knownNat @8) bytes)
ptr <- tryGlobPtr sym mem globs w (regValue ptr0) ptr <- tryGlobPtr sym mem globs (regValue ptr0)
ok <- isValidPtr sym mem w ptr ok <- isValidPtr sym mem w ptr
check sym ok "doCondReadMem" check sym ok "doCondReadMem"
$ "Conditional read through an invalid pointer: " ++ $ "Conditional read through an invalid pointer: " ++
@ -407,7 +490,7 @@ doWriteMem ::
IsSymInterface sym => IsSymInterface sym =>
CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} -> CrucibleState s sym ext rtp blocks r ctx {- ^ Simulator state -} ->
GlobalVar Mem {- ^ Memory model -} -> GlobalVar Mem {- ^ Memory model -} ->
Map M.RegionIndex (RegValue sym (LLVMPointerType ptrW)) {- ^ Region ptrs -} -> GlobalMap sym ptrW ->
M.AddrWidthRepr ptrW {- ^ Width of ptr -} -> M.AddrWidthRepr ptrW {- ^ Width of ptr -} ->
MemRepr ty {- ^ What/how we are writing -} -> MemRepr ty {- ^ What/how we are writing -} ->
RegEntry sym (LLVMPointerType ptrW) {- ^ Pointer -} -> RegEntry sym (LLVMPointerType ptrW) {- ^ Pointer -} ->
@ -425,8 +508,7 @@ doWriteMem st mvar globs w (BVMemRepr bytes endian) ptr0 val =
LeqProof <- pure $ addrWidthIsPos w LeqProof <- pure $ addrWidthIsPos w
LeqProof <- pure $ addrWidthAtLeast16 w LeqProof <- pure $ addrWidthAtLeast16 w
LeqProof <- return (leqMulPos (knownNat @8) bytes) LeqProof <- return (leqMulPos (knownNat @8) bytes)
ptr <- tryGlobPtr sym mem globs (regValue ptr0)
ptr <- tryGlobPtr sym mem globs w (regValue ptr0)
ok <- isValidPtr sym mem w ptr ok <- isValidPtr sym mem w ptr
check sym ok "doWriteMem" check sym ok "doWriteMem"
$ "Write to an invalid location: " ++ show (ppPtr ptr) $ "Write to an invalid location: " ++ show (ppPtr ptr)
@ -606,33 +688,30 @@ mkName x = case userSymbol x of
{- | Every now and then we encoutner memory opperations that {- | Every now and then we encounter memory opperations that
just read/write to some constant. Normally, we do not allow just read/write to some constant. Normally, we do not allow
such things as we want memory to be allocated first. such things as we want memory to be allocated first.
However we need to make an exception for globals. However we need to make an exception for globals.
So, if we ever try to manipulate memory at some address So, if we ever try to manipulate memory at some address
which is statically known to be a constant, we consult which is statically known to be a constant, we consult
the global map to see if we know about a correpsonding the global map to see if we know about a correpsonding
addres.. If so, we use that for the memory operation. -} address. If so, we use that for the memory operation.
See the documentation of 'GlobalMap' for details about how that translation can
be handled.
-}
tryGlobPtr :: tryGlobPtr ::
IsSymInterface sym => IsSymInterface sym =>
sym -> sym ->
RegValue sym Mem -> RegValue sym Mem ->
Map M.RegionIndex (RegValue sym (LLVMPointerType w)) {- ^ Region ptrs -} -> GlobalMap sym w ->
M.AddrWidthRepr w ->
LLVMPtr sym w -> LLVMPtr sym w ->
IO (LLVMPtr sym w) IO (LLVMPtr sym w)
tryGlobPtr sym mem globs w val tryGlobPtr sym mem mapBVAddress val
| Just 0 <- asNat (ptrBase val) | Just 0 <- asNat (ptrBase val) = do
, Just r <- Map.lookup literalAddrRegion globs maddr <- mapBVAddress sym mem (ptrBase val) (asBits val)
, LeqProof <- addrWidthIsPos w return (fromMaybe val maddr)
, LeqProof <- addrWidthAtLeast16 w =
let ?ptrWidth = M.addrWidthNatRepr w
in doPtrAddOffset sym mem r (asBits val)
| otherwise = return val | otherwise = return val
where
literalAddrRegion = 0
isAlignMask :: (IsSymInterface sym) => LLVMPtr sym w -> Maybe Integer isAlignMask :: (IsSymInterface sym) => LLVMPtr sym w -> Maybe Integer
isAlignMask v = isAlignMask v =

View File

@ -323,15 +323,15 @@ data X86PrimFn f tp where
-- else -- else
-- return (false, trunc 32 temp64, trunc 32 (temp64 >> 32)) -- return (false, trunc 32 temp64, trunc 32 (temp64 >> 32))
CMPXCHG8B :: !(f (BVType 64)) CMPXCHG8B :: !(f (BVType 64))
-- ^ Address to read -- Address to read
-> !(f (BVType 32)) -> !(f (BVType 32))
-- ^ Value in EAX -- Value in EAX
-> !(f (BVType 32)) -> !(f (BVType 32))
-- ^ Value in EBX -- Value in EBX
-> !(f (BVType 32)) -> !(f (BVType 32))
-- ^ Value in ECX -- Value in ECX
-> !(f (BVType 32)) -> !(f (BVType 32))
-- ^ Value in EDX -- Value in EDX
-> X86PrimFn f (TupleType [BoolType, BVType 32, BVType 32]) -> X86PrimFn f (TupleType [BoolType, BVType 32, BVType 32])
-- | The RDTSC instruction. -- | The RDTSC instruction.
@ -828,6 +828,7 @@ data X86Stmt (v :: Type -> *) where
-- * @dir@ is a flag that indicates whether direction of move: -- * @dir@ is a flag that indicates whether direction of move:
-- * 'True' means we should decrement buffer pointers after each copy. -- * 'True' means we should decrement buffer pointers after each copy.
-- * 'False' means we should increment the buffer pointers after each copy. -- * 'False' means we should increment the buffer pointers after each copy.
RepStos :: !(RepValSize w) RepStos :: !(RepValSize w)
-> !(v (BVType 64)) -> !(v (BVType 64))
-- /\ Address to start assigning to. -- /\ Address to start assigning to.
@ -851,6 +852,7 @@ data X86Stmt (v :: Type -> *) where
EMMS :: X86Stmt v EMMS :: X86Stmt v
-- ^ Empty MMX technology State. Sets the x87 FPU tag word to empty. -- ^ Empty MMX technology State. Sets the x87 FPU tag word to empty.
--
-- Probably OK to use this for both EMMS FEMMS, the second being a a -- Probably OK to use this for both EMMS FEMMS, the second being a a
-- faster version from AMD 3D now. -- faster version from AMD 3D now.