Skip to content

Commit c7651db

Browse files
committed
Introduce pause frame tracking
* stub tracks the numbe of pauses, starting at zero. * stub returns the current pause frame number on all pause requests * Client.hs tracks the current pause frame number in Debuggee
1 parent dc87b0b commit c7651db

File tree

4 files changed

+42
-7
lines changed

4 files changed

+42
-7
lines changed

client/src/GHC/Debug/Client.hs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# LANGUAGE GADTs #-}
2+
13
module GHC.Debug.Client
24
( Debuggee
35
, DebuggeeAction
@@ -7,6 +9,7 @@ module GHC.Debug.Client
79
, pauseDebuggee
810
, request
911
, Request(..)
12+
, getCurrentFrame
1013
, getInfoTblPtr
1114
, decodeClosure
1215
, decodeStack
@@ -41,6 +44,7 @@ import System.Endian
4144
import Data.Foldable
4245
import Data.Coerce
4346
import Data.Bitraversable
47+
import Data.Word (Word32)
4448

4549

4650
import qualified Data.Dwarf as Dwarf
@@ -61,6 +65,7 @@ data Debuggee = Debuggee { debuggeeHdl :: Handle
6165
, debuggeeInfoTblEnv :: HM.HashMap InfoTablePtr RawInfoTable
6266
, debuggeeDwarf :: Maybe Dwarf
6367
, debuggeeFilename :: FilePath
68+
, debuggeeFrame :: Word32
6469
}
6570

6671
type DebuggeeAction a = StateT Debuggee IO a
@@ -101,13 +106,19 @@ withDebuggeeSocket exeName sockName mdwarf action = do
101106
s <- socket AF_UNIX Stream defaultProtocol
102107
connect s (SockAddrUnix sockName)
103108
hdl <- socketToHandle s ReadWriteMode
104-
evalStateT action (Debuggee hdl mempty mdwarf exeName)
109+
evalStateT action (Debuggee hdl mempty mdwarf exeName 0)
105110

106111
-- | Send a request to a 'Debuggee' paused with 'pauseDebuggee'.
107112
request :: Request resp -> DebuggeeAction resp
108113
request req = do
109-
hdl <- gets debuggeeHdl
110-
liftIO $ doRequest hdl req
114+
hdl <- gets debuggeeHdl
115+
payload <- liftIO $ doRequest hdl req
116+
-- if we did a successful pause, the payload contains the current frame
117+
-- number
118+
case req of
119+
RequestPause -> modify' $ \d -> d { debuggeeFrame = payload }
120+
_ -> return ()
121+
return payload
111122

112123
lookupInfoTable :: RawClosure -> DebuggeeAction (RawInfoTable, RawClosure)
113124
lookupInfoTable rc = do
@@ -248,3 +259,7 @@ warnIfNewer fpSrc fpBin = do
248259
fpSrc fpBin
249260
else
250261
return ()
262+
263+
-- | Return the current frame number
264+
getCurrentFrame :: DebuggeeAction Word32
265+
getCurrentFrame = gets debuggeeFrame

common/src/GHC/Debug/Types.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ import GHC.Debug.Types.Ptr as T
3535
data Request a where
3636
-- | Request protocol version
3737
RequestVersion :: Request Word32
38-
-- | Pause the debuggee.
39-
RequestPause :: Request ()
38+
-- | Pause the debuggee, get number of current pause frame.
39+
RequestPause :: Request Word32
4040
-- | Resume the debuggee.
4141
RequestResume :: Request ()
4242
-- | Request the debuggee's root pointers.
@@ -136,7 +136,7 @@ putRequest (RequestFindPtr c) =
136136

137137
getResponse :: Request a -> Get a
138138
getResponse RequestVersion = getWord32be
139-
getResponse RequestPause = get
139+
getResponse RequestPause = getWord32be
140140
getResponse RequestResume = get
141141
getResponse RequestRoots = many get
142142
getResponse (RequestClosures _) = many getRawClosure

stub/cbits/stub.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ class Response {
187187
};
188188

189189
static bool paused = false;
190+
// track how often the target was paused
191+
static uint32_t num_pause_frame = 0;
190192
static RtsPaused r_paused;
191193
static Response * r_poll_pause_resp = NULL;
192194

@@ -199,6 +201,7 @@ void pause_mutator() {
199201
r_poll_pause_resp->finish(RESP_OKAY);
200202
}
201203
paused = true;
204+
++num_pause_frame;
202205
}
203206

204207
extern "C"
@@ -282,9 +285,13 @@ static int handle_command(Socket& sock, const char *buf, uint32_t cmd_len) {
282285
trace("PAUSE: %d", paused);
283286
if (paused) {
284287
trace("ALREADY");
288+
// even though we are already paused we tell the callee what pause
289+
// frame we are in
290+
resp.write(htonl(num_pause_frame));
285291
resp.finish(RESP_ALREADY_PAUSED);
286292
} else {
287293
pause_mutator();
294+
resp.write(htonl(num_pause_frame));
288295
resp.finish(RESP_OKAY);
289296
}
290297
break;

test/Test.hs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import GHC.Debug.Client
44
import GHC.Debug.Types.Graph
55

66
import Control.Monad
7-
import Control.Monad.State.Lazy (liftIO, get)
7+
import Control.Monad.State.Lazy (liftIO, get, gets)
88
import Debug.Trace
99
import Control.Exception
1010
import Control.Concurrent
1111
import Data.Bitraversable
1212
import GHC.Vis
13+
import Text.Printf
1314

1415
prog = "/home/matt/ghc-debug/dist-newstyle/build/x86_64-linux/ghc-8.9.0.20190806/ghc-debug-stub-0.1.0.0/x/debug-test/build/debug-test/debug-test"
1516

@@ -201,3 +202,15 @@ p16 = do
201202
dbg <- get
202203
hg <- liftIO $ buildHeapGraph (derefBox dbg) 20 () so
203204
liftIO $ putStrLn $ ppHeapGraph hg
205+
206+
p17 = do
207+
printFrame
208+
replicateM_ 20 $ do
209+
printFrame
210+
request RequestPause
211+
request RequestResume
212+
where
213+
printFrame = do
214+
frame <- getCurrentFrame
215+
liftIO $ putStrLn $
216+
printf "Current frame number: %d" frame

0 commit comments

Comments
 (0)