<<>> <> <> <> <> <<>> DIRECTORY Breakpoint, BreakWorldArchitecture, Commander, CommanderOps, Convert, FakeCirio, IO, Spy, Rope, TargetArchitecture; SpyBreaksImpl: CEDAR PROGRAM IMPORTS Breakpoint, BreakWorldArchitecture, Commander, CommanderOps, Convert, FakeCirio, IO, Spy, Rope <> ~ BEGIN ROPE: TYPE ~ Rope.ROPE; SpyTraceBreakProcedure: PROCEDURE ~ { Spy.SampleMyStack[]; }; nameSpyTraceBreakProc: ROPE ~ "_SpyTraceBreakProcedure_P60"; breakWorld: BreakWorldArchitecture.BreakWorld ~ BreakWorldArchitecture.CreateBreakWorld[ name: "SPARC", peekContents: FakeCirio.PeekContents, pokeContents: FakeCirio.PokeContents, getProcAddress: FakeCirio.GetProcAddress, getProcDataSegment: FakeCirio.GetProcDataSegment, getPatchArea: FakeCirio.GetPatchArea, monitoredCall: FakeCirio.MonitoredCall, worldAccessData: NIL]; Fail: PROC [msg: ROPE] ~ { Spy.SampleMyStack[]; -- for debug when can't set breaks. CommanderOps.Failed[msg]; }; breaks: LIST OF Breakpoint.Break ¬ NIL; SpySetTraceBreakCommand: Commander.CommandProc ~ { ENABLE { FakeCirio.Cant => Fail[Rope.Concat["FakeCirio.Cant: ", message]]; Breakpoint.CantSet => Fail[Rope.Concat["Breakpoint.CantSet: ", message]]; Breakpoint.Cant => Fail[Rope.Concat["Breakpoint.Cant: ", message]]; BreakWorldArchitecture.Cant => Fail[Rope.Concat["BreakWorldArchitecture.Cant: ", message]]; Convert.Error => Fail["Illegal offset specified"]; }; arg: ROPE ~ CommanderOps.NextArgument[cmd]; IF arg # NIL AND CommanderOps.NextArgument[cmd] = NIL THEN { toSign: INT ~ Rope.SkipTo[arg, 0, "+-"]; procName: ROPE ~ Rope.Substr[arg, 0, toSign]; offset: INT ~ IF toSign = Rope.Size[arg] THEN 0 ELSE Convert.IntFromRope[Rope.Substr[arg, toSign]]; breakpointBaseAddress: BreakWorldArchitecture.Address ~ IF Rope.Size[procName] # 0 THEN FakeCirio.GetProcAddress[ breakWorld: breakWorld, procName: procName] ELSE BreakWorldArchitecture.nullAddress; breakpointAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[breakpointBaseAddress, offset]; breakProcedureAddress: BreakWorldArchitecture.Address ~ FakeCirio.GetProcAddress[ breakWorld: breakWorld, procName: nameSpyTraceBreakProc]; break: Breakpoint.Break ¬ Breakpoint.SetBreakpoint[ address: breakpointAddress, clientData: NIL, breakProc: breakProcedureAddress, breakData: 0]; breaks ¬ CONS[break, breaks]; { address: TargetArchitecture.Address ~ Breakpoint.AddressFromBreak[break].address; IO.PutF1[cmd.out, "Break set at pc=0%08xH\n", [cardinal[LOOPHOLE[address]]]]; RETURN; }; }; CommanderOps.Failed[cmd.procData.doc]; }; cantClear: Breakpoint.Break ¬ NIL; SpyClearTraceBreaksCommand: Commander.CommandProc ~ { ENABLE { FakeCirio.Cant => Fail[Rope.Concat["FakeCirio.Cant: ", message]]; Breakpoint.CantClear => Fail[Rope.Concat["Breakpoint.CantClear: ", message]]; Breakpoint.Cant => Fail[Rope.Concat["Breakpoint.Cant: ", message]]; BreakWorldArchitecture.Cant => Fail[Rope.Concat["BreakWorldArchitecture.Cant: ", message]]; }; IF cantClear # NIL THEN { IF breaks = NIL THEN breaks ¬ LIST[cantClear] ELSE FOR tail: LIST OF Breakpoint.Break ¬ breaks, tail.rest DO IF tail.rest = NIL THEN {tail.rest ¬ LIST[cantClear]; EXIT}; ENDLOOP; cantClear ¬ NIL; }; UNTIL breaks = NIL DO break: Breakpoint.Break ¬ breaks.first; cantClear ¬ break; breaks ¬ breaks.rest; { address: TargetArchitecture.Address ~ Breakpoint.AddressFromBreak[break].address; IO.PutF1[cmd.out, "Clearing break at pc=0%08xH ...", [cardinal[LOOPHOLE[address]]]]; }; Breakpoint.ClearBreakpoint[cantClear]; cantClear ¬ NIL; IO.PutRope[cmd.out, "Ok.\n"]; ENDLOOP; }; Commander.Register[ key: "SpySetTraceBreak", proc: SpySetTraceBreakCommand, doc: " - set a spy trace break"]; Commander.Register[ key: "SpyClearBreaks", proc: SpyClearTraceBreaksCommand, doc: "Clear all spy breaks"]; END.