diff --git a/macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs b/macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs index eb474787..6beebe5a 100644 --- a/macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs +++ b/macaw-ppc/src/Data/Macaw/PPC/Disassemble.hs @@ -27,16 +27,22 @@ import qualified Data.Parameterized.Nonce as NC import Data.Macaw.PPC.Generator -newtype DisM ppc s a = DisM { unDisM :: ET.ExceptT (DisassembleException ppc) (ST s) a } +type LocatedFailure ppc s = ([Block ppc s], MM.MemWord (RegAddrWidth (ArchReg ppc)), TranslationError (RegAddrWidth (ArchReg ppc))) +newtype DisM ppc s a = DisM { unDisM :: ET.ExceptT (LocatedFailure ppc s) (ST s) a } deriving (Functor, Applicative, Monad, - ET.MonadError (DisassembleException ppc)) + ET.MonadError (LocatedFailure ppc s)) -data DisassembleException w = InvalidNextIP Word64 Word64 - | DecodeError (MM.MemoryError w) +data TranslationError w = TranslationError { transErrorAddr :: MM.MemSegmentOff w + , transErrorReason :: TranslationErrorReason w + } -deriving instance (MM.MemWidth w) => Show (DisassembleException w) +data TranslationErrorReason w = InvalidNextIP Word64 Word64 + | DecodeError (MM.MemoryError w) + deriving (Show) + +deriving instance (MM.MemWidth w) => Show (TranslationError w) liftST :: ST s a -> DisM ppc s a liftST = DisM . lift @@ -65,35 +71,45 @@ readInstruction mem addr = MM.addrWidthClass (MM.memAddrWidth mem) $ do 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) +failAt :: GenState ppc s ids + -> MM.MemWord (ArchAddrWidth ppc) + -> MM.MemSegmentOff (ArchAddrWidth ppc) + -> TranslationErrorReason (ArchAddrWidth ppc) + -> DisM ppc s a +failAt gs offset curIPAddr reason = do + let exn = TranslationError { transErrorAddr = curIPAddr + , transErrorReason = reason + } + undefined ([], offset, exn) + +disassembleBlock :: MM.Memory (ArchAddrWidth ppc) + -> GenState ppc s ids + -> MM.MemSegmentOff (ArchAddrWidth ppc) + -> MM.MemWord (ArchAddrWidth ppc) + -> DisM ppc s (MM.MemWord (ArchAddrWidth ppc), GenState ppc 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 + Left err -> failAt gs off curIPAddr (DecodeError err) 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)) +tryDisassembleBlock :: (MM.MemWidth (ArchAddrWidth ppc)) => MM.Memory (ArchAddrWidth ppc) -> NC.NonceGenerator (ST s) s -> ArchSegmentOff ppc -> ArchAddrWord ppc - -> DisM w s ([Block ppc s], MM.MemWord (ArchAddrWidth ppc)) + -> DisM ppc s ([Block ppc s], MM.MemWord (ArchAddrWidth ppc)) tryDisassembleBlock mem nonceGen startAddr maxSize = do let gs0 = initGenState nonceGen startAddr let startOffset = MM.msegOffset startAddr (nextIPOffset, gs1) <- disassembleBlock mem gs0 startAddr (startOffset + maxSize) unless (nextIPOffset > startOffset) $ do - ET.throwError (InvalidNextIP (fromIntegral nextIPOffset) (fromIntegral startOffset)) + let reason = InvalidNextIP (fromIntegral nextIPOffset) (fromIntegral startOffset) + failAt gs1 nextIPOffset startAddr reason let blocks = F.toList (blockSeq gs1 ^. frontierBlocks) return (blocks, nextIPOffset - startOffset) @@ -116,5 +132,5 @@ disassembleFn :: (MM.MemWidth (RegAddrWidth (ArchReg ppc))) disassembleFn _ mem nonceGen startAddr maxSize _ = do mr <- ET.runExceptT (unDisM (tryDisassembleBlock mem nonceGen startAddr maxSize)) case mr of - Left exn -> return ([], 0, Just (show exn)) + Left (blocks, off, exn) -> return (blocks, off, Just (show exn)) Right (blocks, bytes) -> return (blocks, bytes, Nothing) diff --git a/macaw-ppc/src/Data/Macaw/PPC/Generator.hs b/macaw-ppc/src/Data/Macaw/PPC/Generator.hs index 47dce5cc..23c0ac3a 100644 --- a/macaw-ppc/src/Data/Macaw/PPC/Generator.hs +++ b/macaw-ppc/src/Data/Macaw/PPC/Generator.hs @@ -82,15 +82,16 @@ pBlockState = lens _pBlockState (\s v -> s { _pBlockState = v }) ------------------------------------------------------------------------ -- GenState -data GenState ppc w s ids = GenState { assignIdGen :: !(NC.NonceGenerator (ST s) ids) - , blockSeq :: !(BlockSeq ppc ids) - , _blockState :: !(PreBlock ppc ids) - , genAddr :: !(MM.MemSegmentOff w) - } +data GenState ppc s ids = + GenState { assignIdGen :: !(NC.NonceGenerator (ST s) ids) + , blockSeq :: !(BlockSeq ppc ids) + , _blockState :: !(PreBlock ppc ids) + , genAddr :: !(MM.MemSegmentOff (ArchAddrWidth ppc)) + } initGenState :: NC.NonceGenerator (ST s) ids - -> MM.MemSegmentOff w - -> GenState ppc w s ids + -> MM.MemSegmentOff (ArchAddrWidth ppc) + -> GenState ppc s ids initGenState nonceGen addr = GenState { assignIdGen = nonceGen , blockSeq = BlockSeq { _nextBlockID = 0, _frontierBlocks = Seq.empty } @@ -98,54 +99,54 @@ initGenState nonceGen addr = , genAddr = addr } -blockState :: Simple Lens (GenState ppc w s ids) (PreBlock ppc ids) +blockState :: Simple Lens (GenState ppc s ids) (PreBlock ppc ids) blockState = lens _blockState (\s v -> s { _blockState = v }) -curPPCState :: Simple Lens (GenState ppc w s ids) (RegState (PPCReg ppc) (Value ppc ids)) +curPPCState :: Simple Lens (GenState ppc s ids) (RegState (PPCReg ppc) (Value ppc ids)) curPPCState = blockState . pBlockState ------------------------------------------------------------------------ -- PPCGenerator -newtype PPCGenerator ppc w s ids a = PPCGenerator { runGen :: St.StateT (GenState ppc w s ids) (ST s) a } +newtype PPCGenerator ppc s ids a = PPCGenerator { runGen :: St.StateT (GenState ppc s ids) (ST s) a } deriving (Monad, Functor, Applicative, - St.MonadState (GenState ppc w s ids)) + St.MonadState (GenState ppc s ids)) -runGenerator :: GenState ppc w s ids -> PPCGenerator ppc w s ids a -> ST s (a, GenState ppc w s ids) +runGenerator :: GenState ppc s ids -> PPCGenerator ppc s ids a -> ST s (a, GenState ppc s ids) runGenerator s0 act = St.runStateT (runGen act) s0 -execGenerator :: GenState ppc w s ids -> PPCGenerator ppc w s ids () -> ST s (GenState ppc w s ids) +execGenerator :: GenState ppc s ids -> PPCGenerator ppc s ids () -> ST s (GenState ppc s ids) execGenerator s0 act = St.execStateT (runGen act) s0 -- Given a stateful computation on the underlying GenState, create a PPCGenerator -- that runs that same computation. -modGenState :: St.State (GenState ppc w s ids) a -> PPCGenerator ppc w s ids a +modGenState :: St.State (GenState ppc s ids) a -> PPCGenerator ppc s ids a modGenState m = PPCGenerator $ St.StateT $ \genState -> do return $ St.runState m genState -addStmt :: Stmt ppc ids -> PPCGenerator ppc w s ids () +addStmt :: Stmt ppc ids -> PPCGenerator ppc s ids () addStmt stmt = (blockState . pBlockStmts) %= (Seq.|> stmt) -newAssignId :: PPCGenerator ppc w s ids (AssignId ids tp) +newAssignId :: PPCGenerator ppc s ids (AssignId ids tp) newAssignId = do nonceGen <- St.gets assignIdGen n <- liftST $ NC.freshNonce nonceGen return (AssignId n) -liftST :: ST s a -> PPCGenerator ppc w s ids a +liftST :: ST s a -> PPCGenerator ppc s ids a liftST = PPCGenerator . lift addAssignment :: AssignRhs ppc ids tp - -> PPCGenerator ppc w s ids (Assignment ppc ids tp) + -> PPCGenerator ppc s ids (Assignment ppc ids tp) addAssignment rhs = do l <- newAssignId let a = Assignment l rhs addStmt $ AssignStmt a return a -getReg :: PPCReg ppc tp -> PPCGenerator ppc w s ids (Expr ppc ids tp) +getReg :: PPCReg ppc tp -> PPCGenerator ppc s ids (Expr ppc ids tp) getReg r = PPCGenerator $ St.StateT $ \genState -> do let expr = ValueExpr (genState ^. blockState ^. pBlockState ^. boundValue r) return (expr, genState)