AMEvents.mesa - interactions with client
Copyright © 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell September 20, 1983 3:25 pm
Paul Rovner July 20, 1983 12:42 am
Russ Atkinson (RRA) February 11, 1985 11:35:14 pm PST
DIRECTORY
AMModel USING [ Section ],
AMTypes USING [ TV ],
Rope USING [ ROPE ],
WorldVM USING [ Address, World ];
AMEvents: DEFINITIONS = BEGIN OPEN AMModel, AMTypes, Rope, WorldVM;
EventProc:
TYPE =
PROC [data:
REF
ANY, event: Event]
RETURNS [outcome: Outcome];
"data" is as passed to "GetEvents". An EventProc is called whenever something interesting happens in the client world. Returning from the event allows the client process to proceed, as specified by outcome.type:
quit => raise ABORTED in victim process
proceed => depending on the event.type:
breakpoints => execute saved byte and continue (result=NIL)
explicit call => return from the call (result=NIL)
signals => RESUME[result]
retry => redo the call that caused specified local frame, with given arguments.
returnFrom => return control from specified local frame, with given result.
Event: TYPE = REF EventRec;
Eventuality:
TYPE = { break, call, signal, unknown };
EventRec:
TYPE =
RECORD[
world: World ← NIL, -- world requesting the debugger
session: INT ← 0, -- monotonic, incremented at StopEvents or when world boots
process: TV ← NIL, -- process requesting the debugger
frame: TV ← NIL, -- local frame requesting the debugger
worry: BOOL ← FALSE, -- TRUE => don't try to call client procedures
detail:
SELECT type: Eventuality
FROM
break => [id: BreakID, clientData: REF ANY],
call => [msg: ROPE],
signal => [signal, args: TV ],
unknown => [why: ROPE], -- client bug; psbi and frame are valid.
ENDCASE];
Outcome:
TYPE =
RECORD[
SELECT type: *
FROM
proceed => [result: TV],
quit => NULL,
retry => [frame, result: TV],
returnFrom => [frame, result: TV],
ENDCASE] ← [proceed[NIL]];
GetEvents: PROC [world: World, data: REF ANY, proc: EventProc];
StopEvents: PROC [world: World];
Debugging: --INFORMATIONAL-- SIGNAL;
Debugged:
--INFORMATIONAL--
SIGNAL;
"Debugging" is raised in a process when it is about to be suspended for an event --
"Debugged" is raised in a process when the EventProc returns --
NOTE: These are raised as "informational" signals: clients may catch them, but must not
jump out of their catch-phrase. The signaller will resume them.
BootedNotifier:
TYPE =
PROC [world: World, session:
INT, clientData:
REF];
registered "BootedNotifiers" are called at end of a client session. This occurs when StopEvents is called for that world, or when AMEventsImpl notices that the debuggee has been booted. All events for which "session" is <= the given "session" should return (their result will be ignored). At end of session, all outstanding calls of "Apply" for that debuggee are terminated by raising the "EndSession" signal.
RegisterBootedNotifier:
PROC [proc: BootedNotifier, world: World ←
NIL, clientData:
REF ←
NIL];
worldName = NIL causes proc to be called for all booted events
UnRegisterBootedNotifier:
PROC [proc: BootedNotifier, world: World ←
NIL, clientData:
REF ←
NIL];
clientData = NIL implies wildcard match on clientData
ditto for world
WorldSwapLocalSignals:
PROC [
BOOL];
Iff the last call of this procedure has argument "TRUE", signals in the local world
will be sent to the world-swap debugger instead of being reported locally.
CallDebugger:
PROC [msg:
ROPE];
Cause a local "call" event. If someone is handling local events, this will debug without
a world-swap, otherwise it will world-swap. Note that DebuggerSwap.CallDebugger will
always cause a world-swap.
ProvokeProcessEvent:
PROC [p:
TV, frame:
TV, msg:
ROPE]
RETURNS [outcome: Outcome];
... causes a "call" event with the given message to appear as if from the given frame in the given process. This is used by AMProcess to force the debugger's attention to a given frame.
Breakpoints
Multiple breaks at one place are illegal.
BreakID: TYPE = REF BreakRec;
BreakRec: TYPE;
DuplicateBreakpoint: ERROR;
BreakAt:
PROC [world: World, section: Section, clientData:
REF
ANY]
RETURNS [id: BreakID];
Sets breakpoint at beginning of the section (statement or procedure).
BreakAfter:
PROC [world: World, section: Section, clientData:
REF
ANY]
RETURNS [id: BreakID];
Sets breakpoint at end of the section (procedure only).
FrameBreak:
PROC [gf:
TV, pc:
CARDINAL, clientData:
REF
ANY]
RETURNS [id: BreakID];
OctalBreak(1): Sets breakpoint at specified byte relative to "gf"s codebase --
SetBreak:
PROC [world: World, addr: Address, pc:
CARDINAL, clientData:
REF
ANY]
RETURNS [id: BreakID];
OctalBreak(2): Sets breakpoint at specified byte. "addr" is typically a codebase.
ClearBreak: PROC [id: BreakID];
NextBreak:
PROC [world: World, prev: BreakID]
RETURNS [id: BreakID, clientData:
REF
ANY];
Enumerator for breakpoints. Starts and ends with NIL. Returns the currently set breakpoints in most-recent-first order. If "world" is NIL, returns breakpoint in any world.
Procedure invocation
Apply:
PROC [control, args:
TV]
RETURNS [result:
TV];
"control" may have class "procedure", "signal" or "error", corresponding to procedure calls or raising a signal or error. Error's are treated the same as signals. This may raise BadControlLink, BadArgType, BadResStack or EndSession.
BadControlLink: ERROR; -- "control" had wrong type class
BadArgType: ERROR; -- type of "arg" # range of type of "control"
BadResStack: ERROR; -- result stack size was incorrect.
EndSession: ERROR; -- debuggee was booted (or StopEvents was called) instead of returning.
Other stuff
Kill:
SAFE
PROC [world: World];
Currently, calls TemporaryBooting.BootButton[] in client world.
Screen: SAFE PROC [world: World];
END.