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: TVNIL, -- process requesting the debugger
frame: TVNIL, -- local frame requesting the debugger
worry: BOOLFALSE, -- 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: REFNIL];
worldName = NIL causes proc to be called for all booted events
UnRegisterBootedNotifier: PROC [proc: BootedNotifier, world: World ← NIL, clientData: REFNIL];
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.