[refinement] Add an unbounded memory allocation at the bottom of the allocation stack.

This commit is contained in:
Andrei Stefanescu 2019-02-07 16:47:03 -08:00
parent ec9acfc1e1
commit 45e4251bf3
2 changed files with 48 additions and 34 deletions

View File

@ -445,6 +445,7 @@ data RefinementContext arch t solver fp = RefinementContext
, memVar :: C.GlobalVar LLVM.Mem , memVar :: C.GlobalVar LLVM.Mem
, mem :: LLVM.MemImpl (C.OnlineBackend t solver fp) , mem :: LLVM.MemImpl (C.OnlineBackend t solver fp)
, memPtrTable :: MSM.MemPtrTable (C.OnlineBackend t solver fp) (MC.ArchAddrWidth arch) , memPtrTable :: MSM.MemPtrTable (C.OnlineBackend t solver fp) (MC.ArchAddrWidth arch)
, globalMappingFn :: MS.GlobalMap (C.OnlineBackend t solver fp) (MC.ArchAddrWidth arch)
} }
withDefaultRefinementContext withDefaultRefinementContext
@ -459,39 +460,50 @@ withDefaultRefinementContext loaded_binary k = do
C.withZ3OnlineBackend nonce_gen C.NoUnsatFeatures $ \sym -> C.withZ3OnlineBackend nonce_gen C.NoUnsatFeatures $ \sym ->
case MS.archVals (Proxy @arch) of case MS.archVals (Proxy @arch) of
Just arch_vals -> do Just arch_vals -> do
-- path_setter <- W.getOptionSetting W.z3Path (W.getConfiguration sym)
-- _ <- W.setOpt path_setter "z3-tee"
mem_var <- stToIO $ LLVM.mkMemVar handle_alloc mem_var <- stToIO $ LLVM.mkMemVar handle_alloc
-- empty_mem <- LLVM.emptyMem LLVM.LittleEndian
-- let ?ptrWidth = W.knownNat
-- (base_ptr, allocated_mem) <- LLVM.doMallocUnbounded
-- sym
-- LLVM.GlobalAlloc
-- LLVM.Mutable
-- "flat memory"
-- empty_mem
-- LLVM.noAlignment
-- let Right mem_name = W.userSymbol "mem"
-- mem_array <- W.freshConstant sym mem_name W.knownRepr
-- initialized_mem <- LLVM.doArrayStoreUnbounded
-- sym
-- allocated_mem
-- base_ptr
-- LLVM.noAlignment
-- mem_array
(mem, mem_ptr_table) <- MSM.newGlobalMemory (mem, mem_ptr_table) <- MSM.newGlobalMemory
(Proxy @arch) (Proxy @arch)
sym sym
LLVM.LittleEndian LLVM.LittleEndian
MSM.ConcreteMutable MSM.ConcreteMutable
(MBL.memoryImage loaded_binary) (MBL.memoryImage loaded_binary)
let ?ptrWidth = W.knownNat
(base_ptr, allocated_mem) <- LLVM.doMallocUnbounded
sym
LLVM.GlobalAlloc
LLVM.Mutable
"flat memory"
mem
LLVM.noAlignment
let Right mem_name = W.userSymbol "mem"
mem_array <- W.freshConstant sym mem_name W.knownRepr
initialized_mem <- LLVM.doArrayStoreUnbounded
sym
allocated_mem
base_ptr
LLVM.noAlignment
mem_array
let global_mapping_fn = \sym' mem' base off -> do
flat_mem_ptr <- LLVM.ptrAdd sym' W.knownNat base_ptr off
MSM.mapRegionPointers
mem_ptr_table
flat_mem_ptr
sym'
mem'
base
off
MS.withArchEval arch_vals sym $ \arch_eval_fns -> do MS.withArchEval arch_vals sym $ \arch_eval_fns -> do
let ext_impl = MS.macawExtensions let ext_impl = MS.macawExtensions
arch_eval_fns arch_eval_fns
mem_var mem_var
(MSM.mapRegionPointers mem_ptr_table) global_mapping_fn
(MS.LookupFunctionHandle $ \_ _ _ -> undefined) (MS.LookupFunctionHandle $ \_ _ _ -> undefined)
k $ RefinementContext k $ RefinementContext
{ symbolicBackend = sym { symbolicBackend = sym
, archVals = arch_vals , archVals = arch_vals
@ -499,9 +511,9 @@ withDefaultRefinementContext loaded_binary k = do
, nonceGenerator = nonce_gen , nonceGenerator = nonce_gen
, extensionImpl = ext_impl , extensionImpl = ext_impl
, memVar = mem_var , memVar = mem_var
-- , mem = empty_mem , mem = initialized_mem
, mem = mem
, memPtrTable = mem_ptr_table , memPtrTable = mem_ptr_table
, globalMappingFn = global_mapping_fn
} }
Nothing -> fail $ "unsupported architecture" Nothing -> fail $ "unsupported architecture"
@ -582,7 +594,7 @@ smtSolveTransfer RefinementContext{..} discovery_state blocks = do
ip_off <- liftIO $ W.bvLit symbolicBackend W.knownNat $ ip_off <- liftIO $ W.bvLit symbolicBackend W.knownNat $
MC.memWordToUnsigned $ MC.addrOffset entry_addr MC.memWordToUnsigned $ MC.addrOffset entry_addr
entry_ip_val <- liftIO $ fromJust <$> entry_ip_val <- liftIO $ fromJust <$>
(MSM.mapRegionPointers memPtrTable) symbolicBackend mem2 ip_base ip_off globalMappingFn symbolicBackend mem2 ip_base ip_off
init_regs <- initRegs archVals symbolicBackend entry_ip_val init_sp_val init_regs <- initRegs archVals symbolicBackend entry_ip_val init_sp_val
some_cfg <- liftIO $ stToIO $ MS.mkBlockPathCFG some_cfg <- liftIO $ stToIO $ MS.mkBlockPathCFG

View File

@ -342,10 +342,11 @@ mapRegionPointers :: ( MC.MemWidth w
, CB.IsSymInterface sym , CB.IsSymInterface sym
) )
=> MemPtrTable sym w => MemPtrTable sym w
-> CL.LLVMPtr sym w
-> MS.GlobalMap sym w -> MS.GlobalMap sym w
mapRegionPointers mpt = \sym mem regionNum offsetVal -> mapRegionPointers mpt default_ptr = \sym mem regionNum offsetVal ->
case WI.asNat regionNum of case WI.asNat regionNum of
Just 0 -> mapBitvectorToLLVMPointer mpt sym mem offsetVal Just 0 -> mapBitvectorToLLVMPointer mpt sym mem offsetVal default_ptr
Just _ -> Just _ ->
-- This is the case where the region number is concrete and non-zero, -- This is the case where the region number is concrete and non-zero,
-- meaning that it is already an LLVM pointer -- meaning that it is already an LLVM pointer
@ -354,7 +355,7 @@ mapRegionPointers mpt = \sym mem regionNum offsetVal ->
-- In this case, the region number is symbolic, so we need to be very -- In this case, the region number is symbolic, so we need to be very
-- careful to handle the possibility that it is zero (and thus must be -- careful to handle the possibility that it is zero (and thus must be
-- conditionally mapped to one or all of our statically-allocated regions. -- conditionally mapped to one or all of our statically-allocated regions.
mapSymbolicRegionPointer mpt sym mem regionNum offsetVal mapSymbolicRegionPointer mpt sym mem regionNum offsetVal default_ptr
-- | This is a relatively simple case where we know that the region number is -- | This is a relatively simple case where we know that the region number is
-- zero. This means that the bitvector we have needs to be mapped to a pointer. -- zero. This means that the bitvector we have needs to be mapped to a pointer.
@ -366,8 +367,9 @@ mapBitvectorToLLVMPointer :: ( MC.MemWidth w
-> sym -> sym
-> CS.RegValue sym CL.Mem -> CS.RegValue sym CL.Mem
-> CS.RegValue sym (CT.BVType w) -> CS.RegValue sym (CT.BVType w)
-> CL.LLVMPtr sym w
-> IO (Maybe (CL.LLVMPtr sym w)) -> IO (Maybe (CL.LLVMPtr sym w))
mapBitvectorToLLVMPointer mpt@(MemPtrTable im _) sym mem offsetVal = mapBitvectorToLLVMPointer mpt@(MemPtrTable im _) sym mem offsetVal default_ptr =
case WI.asUnsignedBV offsetVal of case WI.asUnsignedBV offsetVal of
Just concreteOffset -> do Just concreteOffset -> do
-- This is the simplest case where the bitvector is concretely known. We -- This is the simplest case where the bitvector is concretely known. We
@ -399,7 +401,7 @@ mapBitvectorToLLVMPointer mpt@(MemPtrTable im _) sym mem offsetVal =
-- --
-- We will handle this by creating a mux tree that allows the pointer to -- We will handle this by creating a mux tree that allows the pointer to
-- be in *any* of our statically-allocated regions. -- be in *any* of our statically-allocated regions.
Just <$> staticRegionMuxTree mpt sym mem offsetVal Just <$> staticRegionMuxTree mpt sym mem offsetVal default_ptr
-- | Create a mux tree that maps the input bitvector (which is the offset in a -- | Create a mux tree that maps the input bitvector (which is the offset in a
-- LLVMPointer with region == 0) to one of the regions that are statically -- LLVMPointer with region == 0) to one of the regions that are statically
@ -420,11 +422,10 @@ staticRegionMuxTree :: ( CB.IsSymInterface sym
-> sym -> sym
-> CL.MemImpl sym -> CL.MemImpl sym
-> WI.SymExpr sym (WI.BaseBVType w) -> WI.SymExpr sym (WI.BaseBVType w)
-> CL.LLVMPtr sym w
-> IO (CL.LLVMPtr sym w) -> IO (CL.LLVMPtr sym w)
staticRegionMuxTree (MemPtrTable im _) sym mem offsetVal = do staticRegionMuxTree (MemPtrTable im _) sym mem offsetVal default_ptr =
let rep = WI.bvWidth offsetVal F.foldlM addMuxForRegion default_ptr (IM.toList im)
np <- CL.mkNullPointer sym rep
F.foldlM addMuxForRegion np (IM.toList im)
where where
handleCase f alloc start end greater less = do handleCase f alloc start end greater less = do
let rep = WI.bvWidth offsetVal let rep = WI.bvWidth offsetVal
@ -457,10 +458,11 @@ mapSymbolicRegionPointer :: ( MC.MemWidth w
-> CS.RegValue sym CL.Mem -> CS.RegValue sym CL.Mem
-> CS.RegValue sym CT.NatType -> CS.RegValue sym CT.NatType
-> CS.RegValue sym (CT.BVType w) -> CS.RegValue sym (CT.BVType w)
-> CL.LLVMPtr sym w
-> IO (Maybe (CL.LLVMPtr sym w)) -> IO (Maybe (CL.LLVMPtr sym w))
mapSymbolicRegionPointer mpt sym mem regionNum offsetVal = do mapSymbolicRegionPointer mpt sym mem regionNum offsetVal default_ptr = do
zeroNat <- WI.natLit sym 0 zeroNat <- WI.natLit sym 0
staticRegion <- staticRegionMuxTree mpt sym mem offsetVal staticRegion <- staticRegionMuxTree mpt sym mem offsetVal default_ptr
isZeroRegion <- WI.natEq sym zeroNat regionNum isZeroRegion <- WI.natEq sym zeroNat regionNum
let nonZeroPtr = CL.LLVMPointer regionNum offsetVal let nonZeroPtr = CL.LLVMPointer regionNum offsetVal
Just <$> CL.muxLLVMPtr sym isZeroRegion staticRegion nonZeroPtr Just <$> CL.muxLLVMPtr sym isZeroRegion staticRegion nonZeroPtr