mirror of
https://github.com/GaloisInc/macaw.git
synced 2024-12-25 23:23:18 +03:00
Add more disassembly infrastructure
This commit is contained in:
parent
7869f0e6c7
commit
d5c5d40ddb
@ -28,6 +28,7 @@ library
|
|||||||
-- other-extensions:
|
-- other-extensions:
|
||||||
build-depends: base >=4.9 && <5,
|
build-depends: base >=4.9 && <5,
|
||||||
containers,
|
containers,
|
||||||
|
bytestring,
|
||||||
dismantle-ppc,
|
dismantle-ppc,
|
||||||
semmc,
|
semmc,
|
||||||
semmc-ppc,
|
semmc-ppc,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE GADTs #-}
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
{-# LANGUAGE StandaloneDeriving #-}
|
||||||
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
module Data.Macaw.PPC.Disassemble ( disassembleFn ) where
|
module Data.Macaw.PPC.Disassemble ( disassembleFn ) where
|
||||||
|
|
||||||
import Control.Lens ( (^.) )
|
import Control.Lens ( (^.) )
|
||||||
@ -7,39 +10,88 @@ import Control.Monad ( unless )
|
|||||||
import qualified Control.Monad.Except as ET
|
import qualified Control.Monad.Except as ET
|
||||||
import Control.Monad.ST ( ST )
|
import Control.Monad.ST ( ST )
|
||||||
import Control.Monad.Trans ( lift )
|
import Control.Monad.Trans ( lift )
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
import qualified Data.ByteString.Lazy as LBS
|
||||||
import qualified Data.Foldable as F
|
import qualified Data.Foldable as F
|
||||||
import Data.Word ( Word64 )
|
import Data.Word ( Word64 )
|
||||||
|
|
||||||
|
import qualified Dismantle.PPC as D
|
||||||
|
|
||||||
import Data.Macaw.AbsDomain.AbsState as MA
|
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.Memory as MM
|
import qualified Data.Macaw.Memory as MM
|
||||||
|
import qualified Data.Macaw.Memory.Permissions as MMP
|
||||||
import qualified Data.Parameterized.Nonce as NC
|
import qualified Data.Parameterized.Nonce as NC
|
||||||
|
|
||||||
import Data.Macaw.PPC.Generator
|
import Data.Macaw.PPC.Generator
|
||||||
|
|
||||||
newtype DisM s a = DisM { unDisM :: ET.ExceptT DisassembleException (ST s) a }
|
newtype DisM ppc s a = DisM { unDisM :: ET.ExceptT (DisassembleException ppc) (ST s) a }
|
||||||
deriving (Functor,
|
deriving (Functor,
|
||||||
Applicative,
|
Applicative,
|
||||||
Monad,
|
Monad,
|
||||||
ET.MonadError DisassembleException)
|
ET.MonadError (DisassembleException ppc))
|
||||||
|
|
||||||
data DisassembleException = InvalidNextIP Word64 Word64
|
data DisassembleException w = InvalidNextIP Word64 Word64
|
||||||
deriving (Show)
|
| DecodeError (MM.MemoryError w)
|
||||||
|
|
||||||
liftST :: ST s a -> DisM s a
|
deriving instance (MM.MemWidth w) => Show (DisassembleException w)
|
||||||
|
|
||||||
|
liftST :: ST s a -> DisM ppc s a
|
||||||
liftST = DisM . lift
|
liftST = DisM . lift
|
||||||
|
|
||||||
tryDisassembleBlock :: (MM.MemWidth (RegAddrWidth (ArchReg ppc)))
|
-- | Read one instruction from the 'MM.Memory' at the given segmented offset.
|
||||||
|
--
|
||||||
|
-- Returns the instruction and number of bytes consumed /or/ an error.
|
||||||
|
readInstruction :: MM.Memory w
|
||||||
|
-> MM.MemSegmentOff w
|
||||||
|
-> Either (MM.MemoryError w) (D.Instruction, MM.MemWord w)
|
||||||
|
readInstruction mem addr = MM.addrWidthClass (MM.memAddrWidth mem) $ do
|
||||||
|
let seg = MM.msegSegment addr
|
||||||
|
case MM.segmentFlags seg `MMP.hasPerm` MMP.execute of
|
||||||
|
False -> ET.throwError (MM.PermissionsError (MM.relativeSegmentAddr addr))
|
||||||
|
True -> do
|
||||||
|
contents <- MM.addrContentsAfter mem (MM.relativeSegmentAddr addr)
|
||||||
|
case contents of
|
||||||
|
[] -> ET.throwError (MM.AccessViolation (MM.relativeSegmentAddr addr))
|
||||||
|
MM.SymbolicRef {} : _ ->
|
||||||
|
ET.throwError (MM.UnexpectedRelocation (MM.relativeSegmentAddr addr))
|
||||||
|
MM.ByteRegion bs : _rest
|
||||||
|
| BS.null bs -> ET.throwError (MM.AccessViolation (MM.relativeSegmentAddr addr))
|
||||||
|
| otherwise -> do
|
||||||
|
let (bytesRead, minsn) = D.disassembleInstruction (LBS.fromStrict bs)
|
||||||
|
case minsn of
|
||||||
|
Just insn -> return (insn, fromIntegral bytesRead)
|
||||||
|
Nothing -> ET.throwError (MM.InvalidInstruction (MM.relativeSegmentAddr addr) contents)
|
||||||
|
|
||||||
|
disassembleBlock :: (w ~ RegAddrWidth (ArchReg ppc))
|
||||||
|
=> MM.Memory (ArchAddrWidth ppc)
|
||||||
|
-> GenState ppc w s ids
|
||||||
|
-> MM.MemSegmentOff w
|
||||||
|
-> MM.MemWord w
|
||||||
|
-> DisM w s (MM.MemWord w, GenState ppc w s ids)
|
||||||
|
disassembleBlock mem gs curIPAddr maxOffset = do
|
||||||
|
let seg = MM.msegSegment curIPAddr
|
||||||
|
let off = MM.msegOffset curIPAddr
|
||||||
|
case readInstruction mem curIPAddr of
|
||||||
|
Left err -> undefined
|
||||||
|
Right (i, bytesRead) -> do
|
||||||
|
-- let nextIP = MM.relativeAddr seg (off + bytesRead)
|
||||||
|
-- let nextIPVal = MC.RelocatableValue undefined nextIP
|
||||||
|
undefined
|
||||||
|
|
||||||
|
tryDisassembleBlock :: (MM.MemWidth w,
|
||||||
|
w ~ RegAddrWidth (ArchReg ppc))
|
||||||
=> MM.Memory (ArchAddrWidth ppc)
|
=> MM.Memory (ArchAddrWidth ppc)
|
||||||
-> NC.NonceGenerator (ST s) s
|
-> NC.NonceGenerator (ST s) s
|
||||||
-> ArchSegmentOff ppc
|
-> ArchSegmentOff ppc
|
||||||
-> ArchAddrWord ppc
|
-> ArchAddrWord ppc
|
||||||
-> DisM s ([Block ppc s], MM.MemWord (ArchAddrWidth ppc))
|
-> DisM w s ([Block ppc s], MM.MemWord (ArchAddrWidth ppc))
|
||||||
tryDisassembleBlock mem nonceGen startAddr maxSize = do
|
tryDisassembleBlock mem nonceGen startAddr maxSize = do
|
||||||
let gs0 = initGenState nonceGen startAddr
|
let gs0 = initGenState nonceGen startAddr
|
||||||
let startOffset = MM.msegOffset startAddr
|
let startOffset = MM.msegOffset startAddr
|
||||||
(nextIPOffset, gs1) <- liftST $ runGenerator gs0 $ undefined
|
(nextIPOffset, gs1) <- disassembleBlock mem gs0 startAddr (startOffset + maxSize)
|
||||||
unless (nextIPOffset > startOffset) $ do
|
unless (nextIPOffset > startOffset) $ do
|
||||||
ET.throwError (InvalidNextIP (fromIntegral nextIPOffset) (fromIntegral startOffset))
|
ET.throwError (InvalidNextIP (fromIntegral nextIPOffset) (fromIntegral startOffset))
|
||||||
let blocks = F.toList (blockSeq gs1 ^. frontierBlocks)
|
let blocks = F.toList (blockSeq gs1 ^. frontierBlocks)
|
||||||
|
Loading…
Reference in New Issue
Block a user