module GHC.Debug.Decode.Stack
( decodeStack
) where
import Data.Word
import qualified Data.ByteString as BS
import Data.Binary.Get as B
import GHC.Debug.Types
import Control.Monad
import Data.Coerce
decodeStack :: Monad m
=> (RawClosure -> m StgInfoTableWithPtr)
-> (Word32 -> m PtrBitmap)
-> RawStack
-> m StackFrames
decodeStack :: forall (m :: * -> *).
Monad m =>
(RawClosure -> m StgInfoTableWithPtr)
-> (Word32 -> m PtrBitmap) -> RawStack -> m StackFrames
decodeStack RawClosure -> m StgInfoTableWithPtr
decodeInfoTable Word32 -> m PtrBitmap
getBitmap RawStack
rs = do
forall b. [DebugStackFrame b] -> GenStackFrames b
GenStackFrames forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word32 -> RawStack -> m [DebugStackFrame ClosurePtr]
get_frames Word32
0 RawStack
rs
where
get_frames :: Word32 -> RawStack -> m [DebugStackFrame ClosurePtr]
get_frames Word32
sp raw :: RawStack
raw@(RawStack ByteString
c) = do
StgInfoTableWithPtr
st_it <- RawClosure -> m StgInfoTableWithPtr
decodeInfoTable (coerce :: forall a b. Coercible a b => a -> b
coerce RawStack
raw)
PtrBitmap
bm <- Word32 -> m PtrBitmap
getBitmap Word32
sp
let res :: Decoder (DebugStackFrame ClosurePtr)
res = forall a. Get a -> Decoder a
B.runGetIncremental (PtrBitmap
-> StgInfoTableWithPtr -> Get (DebugStackFrame ClosurePtr)
getFrame PtrBitmap
bm StgInfoTableWithPtr
st_it) forall a. Decoder a -> ByteString -> Decoder a
`pushChunk` ByteString
c
case Decoder (DebugStackFrame ClosurePtr)
res of
Fail ByteString
_rem ByteOffset
_offset String
err -> forall a. HasCallStack => String -> a
error String
err
Partial Maybe ByteString -> Decoder (DebugStackFrame ClosurePtr)
_inp -> forall a. HasCallStack => String -> a
error String
"Not enough input"
Done ByteString
more ByteOffset
offset DebugStackFrame ClosurePtr
v
| ByteString -> Bool
BS.null ByteString
more -> forall (m :: * -> *) a. Monad m => a -> m a
return []
| Bool
otherwise -> (DebugStackFrame ClosurePtr
vforall a. a -> [a] -> [a]
:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word32 -> RawStack -> m [DebugStackFrame ClosurePtr]
get_frames (Word32
sp forall a. Num a => a -> a -> a
+ (forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteOffset
offset)) (ByteString -> RawStack
RawStack ByteString
more)
getFrame :: PtrBitmap
-> StgInfoTableWithPtr
-> Get (DebugStackFrame ClosurePtr)
getFrame :: PtrBitmap
-> StgInfoTableWithPtr -> Get (DebugStackFrame ClosurePtr)
getFrame PtrBitmap
st_bitmap StgInfoTableWithPtr
itbl =
case StgInfoTable -> ClosureType
tipe (StgInfoTableWithPtr -> StgInfoTable
decodedTable StgInfoTableWithPtr
itbl) of
ClosureType
RET_BCO ->
forall a. HasCallStack => String -> a
error String
"getStack: RET_BCO"
ClosureType
ty -> do
[Word64]
_itblPtr <- forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (forall {a}. Num a => ClosureType -> a
headerSize ClosureType
ty) Get Word64
getWord64le
[FieldValue ClosurePtr]
fields <- forall (m :: * -> *) a.
Monad m =>
(Bool -> m a) -> PtrBitmap -> m [a]
traversePtrBitmap Bool -> Get (FieldValue ClosurePtr)
decodeField PtrBitmap
st_bitmap
return (forall b.
StgInfoTableWithPtr -> [FieldValue b] -> DebugStackFrame b
DebugStackFrame StgInfoTableWithPtr
itbl [FieldValue ClosurePtr]
fields)
where
decodeField :: Bool -> Get (FieldValue ClosurePtr)
decodeField Bool
True = forall b. b -> FieldValue b
SPtr forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> ClosurePtr
mkClosurePtr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Word64
getWord
decodeField Bool
False = forall b. Word64 -> FieldValue b
SNonPtr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Word64
getWord
headerSize :: ClosureType -> a
headerSize ClosureType
RET_FUN = a
3
headerSize ClosureType
RET_BCO = a
2
headerSize ClosureType
_ = a
1
getWord :: Get Word64
getWord :: Get Word64
getWord = Get Word64
getWord64le