<> <> <> DIRECTORY FileIO, Inline, IO, IOExtras, Rope, RPCPkt, TeleDebOps, TeleLoad; TDX: PROGRAM IMPORTS FileIO, IO, IOExtras, Rope, TeleDebOps EXPORTS TeleDebOps = { host: PUBLIC TeleDebOps.TeleDebugData; CoreWordBlock: TYPE = LONG POINTER TO RECORD [ advice: TeleLoad.Advice, address: TeleLoad.CoreAddress, data: SEQUENCE count: CARDINAL OF CARDINAL ]; headerSize: CARDINAL = SIZE[RPCPkt.Header]*2; PBIRecord: TYPE = RECORD [ link: ShortCoreAddress, -- Queue word queue: ShortCoreAddress, -- where to put after transmission clientWord: WORD, -- give client a value in each PBI pup: ShortCoreAddress -- The pup ]; PBI: TYPE = LONG POINTER TO PBIRecord; ShortCoreAddress: TYPE = TeleDebOps.ShortCoreAddress; RPCCtx: TYPE = RECORD [ link: ShortCoreAddress, -- Queue word stack: ShortCoreAddress, -- Saved stack top value when context inactive stackMin: ShortCoreAddress, -- Limit initialPC: ShortCoreAddress, -- Procedure forked by CreateNContext name: ShortCoreAddress, -- C string describing context <> maxrun: CARDINAL, caller: ShortCoreAddress, -- caller of Block after maxrun extra: ARRAY [0..6) OF UNSPECIFIED, <> myPSB: CARDINAL, -- if a context that uses RPC, its PSB. sigVec: ShortCoreAddress, -- where the signal vector is for this context. stackArea: ARRAY [0..0) OF UNSPECIFIED -- the stack -- ]; << Procedures intended to be called from the interpreter>> SetHost: PROC [hostName: Rope.ROPE] RETURNS [BOOL] = { host _ TeleDebOps.FindByNameOrAddress[hostName]; RETURN[host#NIL]; }; DspCtxQ: PROC [ctx: TeleLoad.CoreAddress _ 0, ctxRunning: TeleLoad.CoreAddress _ 0 ] = { ENABLE TeleDebOps.Failed => CONTINUE; CheckHost[]; <> IF ctx=0 THEN { ctxItem: TeleDebOps.STObject; found: BOOL; [item: ctxItem, found: found] _ TeleDebOps.FindVariable[host.program, "ctxQ"]; IF found THEN ctx _ TeleDebOps.ReadWord[host, ctxItem.addr] ELSE { host.out.PutF["can't get symbol ctxQ\n"]; RETURN; }; }; IF ctxRunning = 0 THEN { cxtxRunningItem: TeleDebOps.STObject; found: BOOL; [item: cxtxRunningItem, found: found] _ TeleDebOps.FindVariable[TeleDebOps.Monitor[host], "CtxRunning"]; IF found THEN ctxRunning _ TeleDebOps.ReadWord[host, cxtxRunningItem.addr]; }; IF ctxRunning#0 THEN DspCtx[ctxRunning, TRUE]; WHILE ctx#0 DO IF ctx#ctxRunning THEN DspCtx[ctx, FALSE]; ctx _ TeleDebOps.ReadWord[host, ctx]; ENDLOOP; }; ClrCtxStats: PROC [ ctx: TeleLoad.CoreAddress _ 0 ] = { ENABLE TeleDebOps.Failed => CONTINUE; CheckHost[]; IF ctx = 0 THEN { ctxItem: TeleDebOps.STObject; found: BOOL; [item: ctxItem, found: found] _ TeleDebOps.FindVariable[host.program, "ctxQ"]; IF found THEN ctx _ TeleDebOps.ReadWord[host, ctxItem.addr] ELSE { host.out.PutF["can't get symbol ctxQ\n"]; RETURN; }; }; WHILE ctx # 0 DO TeleDebOps.WriteWord[host: host, addr: ctx+offsetMaxrun*2, value: 0]; ctx _ TeleDebOps.ReadWord[host, ctx]; ENDLOOP; TeleDebOps.FlushWrites[host]; }; <<>> <> PrintFixed: PROC = { ENABLE TeleDebOps.Failed => CONTINUE; end: TeleDebOps.STObject; found: BOOL; fobp: TeleLoad.CoreAddress; fob: FOB; caller, caller2: TeleDebOps.STObject; CheckHost[]; [item: end, found: found] _ TeleDebOps.FindVariable[host.program, "end"]; IF NOT found THEN { host.out.PutF["can't get symbol end\n"]; RETURN; }; fobp _ end.addr; IF (fobp MOD 2) # 0 THEN fobp _ fobp + 1; DO fob _ ReadFob[host: host, fobAddr: fobp]; IF fob.length = 0 THEN EXIT; caller _ TeleDebOps.ProcedureEnclosing[host.program, fob.owner]; caller2 _ TeleDebOps.ProcedureEnclosing[host.program, fob.owner2]; host.out.PutF["adr: %04xH, len: %5d ", IO.card[fobp + 6], IO.card[fob.length]]; host.out.PutF["own: %g+%x ", IO.rope[caller.id], IO.card[fob.owner - caller.addr]]; host.out.PutF["own2: %g+%x\n", IO.rope[caller2.id], IO.card[fob.owner2 - caller2.addr]]; fobp _ fobp + (fob.length * 2) + 6; ENDLOOP; }; PrintCtxStats: PROC = { ENABLE TeleDebOps.Failed => CONTINUE; ctxStats: TeleDebOps.STObject; found: BOOL; val: Inline.LongNumber; CheckHost[]; [item: ctxStats, found: found] _ TeleDebOps.FindVariable[host.program, "ctxListTime"]; IF NOT found THEN { host.out.PutF[". . cannot find symbol ctxListTime\n"]; RETURN; }; host.out.PutRope["Context list histogram:\n"]; FOR i: NAT IN [0..20) DO val.lowbits _ TeleDebOps.ReadWord[host, ctxStats.addr + (4*i)]; val.highbits _ TeleDebOps.ReadWord[host, ctxStats.addr + (4*i) + 2]; host.out.PutF["[%2d..%2d): %8d\n", IO.card[i], IO.card[i+1], IO.card[val.lc]]; ENDLOOP; val.lowbits _ TeleDebOps.ReadWord[host, ctxStats.addr + (4*20)]; val.highbits _ TeleDebOps.ReadWord[host, ctxStats.addr + (4*20) + 2]; host.out.PutF["ov: %8d\n", IO.card[val.lc]]; }; ResetCtxStats: PROC = { ENABLE TeleDebOps.Failed => CONTINUE; ctxStats: TeleDebOps.STObject; found: BOOL; CheckHost[]; [item: ctxStats, found: found] _ TeleDebOps.FindVariable[host.program, "ctxListTime"]; IF NOT found THEN { host.out.PutF[". . cannot find symbol ctxListTime\n"]; RETURN; }; FOR i: NAT IN [0..21) DO TeleDebOps.WriteWord[host, ctxStats.addr + (4*i), 0]; TeleDebOps.WriteWord[host, ctxStats.addr + (4*i) + 2, 0]; ENDLOOP; TeleDebOps.FlushWrites[host]; }; PrintV: PROC [name: Rope.ROPE, words: NAT _ 1] = { ENABLE TeleDebOps.Failed => CONTINUE; CheckHost[]; TeleDebOps.PrintVariable[host, name, words]; }; <<>> <> SetVal: PROC [name: Rope.ROPE, value: CARDINAL, offset: NAT _ 0] = { ENABLE TeleDebOps.Failed => CONTINUE; CheckHost[]; [] _ TeleDebOps.SetValue[host: host, name:name, value: value, offset: offset]; }; SetBlock: PROC [low, high: CARDINAL, value: CARDINAL] = { ENABLE TeleDebOps.Failed => CONTINUE; addr: TeleLoad.CoreAddress _ low; CheckHost[]; IF high <= low THEN RETURN; IF ((high - low) MOD 2) # 0 THEN high _ high - 1 ELSE high _ high - 2; DO TeleDebOps.WriteWord[host: host, addr: addr, value: value]; addr _ addr + 2; IF addr > high THEN EXIT; ENDLOOP; }; CheckBlock: PROC [low, high: CARDINAL, value: CARDINAL, ignore: NAT _ 1] = { ENABLE TeleDebOps.Failed => CONTINUE; addr: TeleLoad.CoreAddress _ low; newValue: CARDINAL; start, stop: TeleLoad.CoreAddress _ 0; inside: {out, in, leaving}; CheckHost[]; IF high <= low THEN RETURN; IF ((high - low) MOD 2) # 0 THEN high _ high - 1 ELSE high _ high - 2; ignore _ ignore * 2; DO newValue _ TeleDebOps.ReadWord[host: host, addr: addr]; SELECT inside FROM out => { IF (newValue # value) THEN { start _ addr; inside _ in; }; }; in => { IF (newValue = value) THEN { stop _ addr; inside _ leaving; }; }; leaving => { IF (newValue = value) THEN { IF addr - stop = ignore THEN { inside _ out; host.out.PutF["[%04xH..%04xH] bad\n", IO.card[start], IO.card[stop]]; }; IF (addr - stop) > ignore THEN ERROR; } ELSE { -- newValue # value IF (addr - stop) < ignore THEN inside _ in; IF (addr - stop) = ignore THEN { host.out.PutF["[%04xH..%04xH] bad\n", IO.card[start], IO.card[stop]]; start _ addr; inside _ in; }; IF (addr - stop) > ignore THEN ERROR; }; }; ENDCASE => ERROR; IF host.in.CharsAvail[] THEN EXIT; addr _ addr + 2; IF addr > high THEN EXIT; ENDLOOP; }; <> <<>> CheckHost: PROC = { IF host = NIL THEN ERROR TeleDebOps.Failed; }; <<>> SetHostByRef: PUBLIC PROC [h: TeleDebOps.TeleDebugData] = { host _ h; }; DspQ: PROC[addr: TeleLoad.CoreAddress] = { ENABLE TeleDebOps.Failed => CONTINUE; host.out.PutF["--------------\rQueue at %4X:\r", IO.card[addr]]; WHILE (addr _ TeleDebOps.ReadWord[host, addr])#0 DO host.out.PutF[" %4X\r", IO.card[addr]]; ENDLOOP; host.out.PutRope["----\r\r"]; }; DspStack: PROC[bp: TeleLoad.CoreAddress, initPC: TeleLoad.CoreAddress] = { ENABLE TeleDebOps.Failed => CONTINUE; FOR i: NAT IN [0..15) DO -- limit depth IF bp = 0 THEN EXIT; host.out.PutF[" BP, IP = (%4X, %4X) [...", IO.card[bp], IO.card[initPC]]; host.out.PutF["%4X, %4X, %4X, %4X]", IO.card[TeleDebOps.ReadWord[host, bp-4]], IO.card[TeleDebOps.ReadWord[host, bp-2]], IO.card[TeleDebOps.ReadWord[host, bp+4]], IO.card[TeleDebOps.ReadWord[host, bp+6]]]; host.out.PutF[" (in %g)\n", IO.rope[TeleDebOps.ProcedureEnclosing[host.program, initPC].id]]; initPC _ TeleDebOps.ReadWord[host, bp+2]; bp _ TeleDebOps.ReadWord[host, bp]; IF bp = 0 THEN EXIT; ENDLOOP; host.out.PutChar['\n]; }; zbCtx: LONG POINTER TO RPCCtx = LOOPHOLE[LONG[0]]; offsetSigVec: LONG CARDINAL = LOOPHOLE[@zbCtx.sigVec]; offsetMaxrun: LONG CARDINAL = LOOPHOLE[@zbCtx.maxrun]; ReadCoreBlock: PROC [addr: TeleLoad.CoreAddress, count: CARDINAL] RETURNS [cb: TeleLoad.CoreBlock] = { cb _ NEW[TeleLoad.CoreBlockObject[count]]; FOR i: NAT IN [0..cb.count) DO cb.data[i] _ TeleDebOps.Read[host, addr+i]; ENDLOOP; }; DspCtx: PROC [addr: TeleLoad.CoreAddress, running: BOOLEAN_FALSE ] = { ENABLE TeleDebOps.Failed => CONTINUE; cb: TeleLoad.CoreBlock _ ReadCoreBlock[addr, SIZE[RPCCtx] * 2]; ctx: LONG POINTER TO RPCCtx = LOOPHOLE[@(LOOPHOLE[cb, CoreWordBlock]).data[0]]; bp, ip: ShortCoreAddress; hwm: ShortCoreAddress; host.out.PutRope["Ctx: "]; DspCString[host, TeleDebOps.Swab[ctx.name]]; host.out.PutF["(%2x)%g at %4x, limit %4x", IO.card[TeleDebOps.Swab[ctx.myPSB]], IO.char[IF running THEN '@ ELSE '\040], IO.card[addr], IO.card[TeleDebOps.Swab[ctx.stackMin]]]; host.out.PutF[", sigVec at %4X\n", IO.card[LOOPHOLE[addr+offsetSigVec*2]]]; hwm _ HighWaterMark[TeleDebOps.Swab[ctx.stackMin]]; host.out.PutF[" max run %4d(10) due to %4x, high water mark at %4x\n", IO.card[TeleDebOps.Swab[ctx.maxrun]], IO.card[TeleDebOps.Swab[ctx.caller]], IO.card[hwm]]; IF running THEN { TeleDebOps.FetchState[host]; bp _ host.larkState[BP]; ip _ host.larkState[IP]; } ELSE { cbw: CoreWordBlock; cb _ TeleDebOps.GetCoreBlock[host, TeleDebOps.Swab[ctx.stack], 4]; cbw _ LOOPHOLE[cb]; bp _ TeleDebOps.Swab[cbw[0]]; ip _ TeleDebOps.Swab[cbw[1]]; }; DspStack[bp, ip]; }; SB: TYPE = RECORD [ length: CARDINAL, user: CARDINAL, pSbNext: CARDINAL, pSbPrevious: CARDINAL ]; ZN: TYPE = RECORD [ anchor: SB, rover: CARDINAL, minAdr: CARDINAL, maxAdr: CARDINAL ]; ReadZN: PROC [a: TeleLoad.CoreAddress] RETURNS [z: ZN] = { z.anchor _ ReadSB[a]; z.rover _ TeleDebOps.ReadWord[host, a+8]; z.minAdr _ TeleDebOps.ReadWord[host, a+10]; z.maxAdr _ TeleDebOps.ReadWord[host, a+12]; }; ReadSB: PROC [a: TeleLoad.CoreAddress] RETURNS [s: SB] = { s.length _ TeleDebOps.ReadWord[host, a]; s.user _ TeleDebOps.ReadWord[host, a+2]; s.pSbNext _ TeleDebOps.ReadWord[host, a+4]; s.pSbPrevious _ TeleDebOps.ReadWord[host, a+6]; }; PrintZone: PROC = { ENABLE TeleDebOps.Failed => CONTINUE; sysZone: TeleDebOps.STObject; zone: TeleLoad.CoreAddress; ia: CARDINAL; addit: INTEGER; z: ZN; s: SB; as: CARDINAL; found: BOOL; [item: sysZone, found: found] _ TeleDebOps.FindVariable[host.program, "sysZone"]; IF NOT found THEN { host.out.PutF["can't get sysZone\n"]; RETURN; }; zone _ TeleDebOps.ReadWord[host, sysZone.addr]; z _ ReadZN[zone]; IF TeleDebOps.ReadWord[host, z.maxAdr] # 177777B THEN { host.out.PutF["CallSwat(ecAllocate+7)\n"]; RETURN; }; ia _ z.minAdr; as _ ia; s _ ReadSB[as]; DO IF z.maxAdr <= as THEN EXIT; addit _ LOOPHOLE[s.length]; IF addit >= 0 THEN { host.out.PutF["adr: %04xH, len: %5d, prev: %04xH next: %04xH\n", IO.card[as], IO.card[addit], IO.card[s.pSbPrevious], IO.card[s.pSbNext]]; } ELSE { item: TeleDebOps.STObject _ TeleDebOps.ProcedureEnclosing[host.program, s.user]; addit _ -addit; host.out.PutF["adr: %04xH, len: %5d, usedby: %g+%x\n", IO.card[as], IO.card[addit], IO.rope[item.id], IO.card[s.user-item.addr]]; }; ia _ ia + addit; IF as > LOOPHOLE[ia, CARDINAL] THEN { host.out.PutF["CallSwat(ecAllocate+8)\n"]; RETURN; }; as _ ia; s _ ReadSB[as]; ENDLOOP; }; FOB: TYPE = RECORD [ owner: CARDINAL, owner2: CARDINAL, length: CARDINAL ]; ReadFob: PROC [host: TeleDebOps.TeleDebugData, fobAddr: TeleLoad.CoreAddress] RETURNS [f: FOB] = { f.owner _ TeleDebOps.ReadWord[host, fobAddr]; f.owner2 _ TeleDebOps.ReadWord[host, fobAddr + 2]; f.length _ TeleDebOps.ReadWord[host, fobAddr + 4]; }; HighWaterMark: PROC [stackLim: TeleLoad.CoreAddress] RETURNS [hwm: TeleLoad.CoreAddress] = { ENABLE TeleDebOps.Failed => CONTINUE; addr: TeleLoad.CoreAddress _ stackLim; DO IF TeleDebOps.ReadWord[host, addr]#0 THEN RETURN[addr+1]; addr _ addr+2; ENDLOOP; }; DspCString: PROC[host: TeleDebOps.TeleDebugData, addr: ShortCoreAddress ] = { ENABLE TeleDebOps.Failed => CONTINUE; FOR i: NAT IN [0..20) DO c: CHAR _ LOOPHOLE[TeleDebOps.Read[host, addr+i]]; IF c = '\000 THEN RETURN; host.out.PutChar[c]; ENDLOOP; }; DspPkt: PROC[addr: TeleLoad.CoreAddress] = { ENABLE TeleDebOps.Failed => CONTINUE; cb: TeleLoad.CoreBlock _ ReadCoreBlock[addr, RPCPkt.pktLengthOverhead*2]; header: LONG POINTER TO RPCPkt.Header; typ: Rope.ROPE _ PktType[header.type]; offset: NAT _ IF typ.Length[]=0 THEN 0 ELSE headerSize; IF cb=NIL THEN RETURN; header _ LOOPHOLE[@(LOOPHOLE[cb, CoreWordBlock]).data[0]]; host.out.PutF["--------------\r%d byte packet at %4X:\r%s (%3B) ", IO.card[header.length*2], IO.card[addr], IO.rope[typ], IO.card[cb.data[3]]]; host.out.PutF["[%2B#%3B#%2B](%4X)", IO.card[header.destHost.net], IO.card[header.destHost.host], IO.card[header.destSoc.b], IO.card[header.destPSB]]; host.out.PutF[" _ [%2B#%3B#%2B](%4X)\r", IO.card[header.srceHost.net], IO.card[header.srceHost.host], IO.card[header.srceSoc.b], IO.card[header.srcePSB]]; host.out.PutF["conv: %8Xx, id: [act: %4X, count: %8Xx, seq: %4X]\r", MesaDbl[@header.conv], IO.card[header.pktID.activity], MesaDbl[@header.pktID.callSeq], IO.card[header.pktID.pktSeq]]; host.out.PutF["disp: [mds: %4X, id: %8X, hint: %4X]\r", IO.card[header.dispatcher.mds], MesaDbl[@header.dispatcher.dispatcherID], IO.card[header.dispatcher.dispatcherHint]]; host.out.PutRope["Data:\r"]; IF header.length>0 AND header.length<105 THEN { TeleDebOps.Show[host, addr+offset, header.length*2-offset]; }; }; DspPBI: PROC[addr: TeleLoad.CoreAddress] = { ENABLE TeleDebOps.Failed => CONTINUE; cb: TeleLoad.CoreBlock _ ReadCoreBlock[addr, SIZE[PBIRecord]*2]; pbi: PBI; IF cb=NIL THEN RETURN; pbi _ LOOPHOLE[@(LOOPHOLE[cb, CoreWordBlock]).data[0]]; host.out.PutF["--------------\rPBI at %4X:\r", IO.card[addr]]; host.out.PutF["link: %4X\r queue: %4X, clientWord: %4X, pup: %4X\r", IO.card[TeleDebOps.Swab[pbi.link]], IO.card[TeleDebOps.Swab[pbi.queue]], IO.card[TeleDebOps.Swab[pbi.clientWord]], IO.card[TeleDebOps.Swab[pbi.pup]]]; DspPkt[TeleDebOps.Swab[pbi.pup]]; }; MesaDbl: PROC[addr: LONG POINTER] RETURNS [IO.Value] = { ln: Inline.LongNumber _ LOOPHOLE[addr, LONG POINTER TO Inline.LongNumber]^; ln.lowbits _ TeleDebOps.Swab[ln.lowbits]; ln.highbits _ TeleDebOps.Swab[ln.highbits]; RETURN[IO.card[ln.lc]]; }; PktType: PROC[type: RPCPkt.PktType] RETURNS [Rope.ROPE] = { t: Rope.ROPE_NIL; IF type.subType#rpc THEN RETURN[NIL]; IF type.eom=notEnd THEN t_"notEnd-"; IF type.ack=pleaseAck AND type.class=ack THEN RETURN[t.Concat["Ping"]]; t_t.Concat[SELECT type.class FROM call=>"Call", data=>"Data", ack=>"Ack", rfa=>"Rfa", ENDCASE=>"??"]; IF type.ack=pleaseAck THEN t_t.Concat["/Ack"]; RETURN[t]; }; PrintVariable: PUBLIC PROC [host: TeleDebOps.TeleDebugData, name: Rope.ROPE, words: NAT _ 1] = { ENABLE TeleDebOps.Failed => CONTINUE; ob: TeleDebOps.STObject; address: TeleLoad.CoreAddress; found: BOOL; <> [item: ob, found: found] _ TeleDebOps.FindVariable[host.program, name]; <> IF NOT found THEN { host.out.PutF[" %g: not found\n", IO.rope[name]]; } ELSE { -- fetch data and print it address _ ob.addr; host.out.PutF[" %g (%04xH^): ", IO.rope[name], IO.int[address]]; FOR i: NAT IN [0..words) DO host.out.PutF[" %04xH", IO.card[TeleDebOps.ReadWord[host, address + (i * 2)]]]; ENDLOOP; host.out.PutChar['\n]; }; }; <> SetValue: PUBLIC PROC [host: TeleDebOps.TeleDebugData, name: Rope.ROPE, value: CARDINAL, offset: NAT _ 0] RETURNS [BOOL] = {{ ENABLE TeleDebOps.Failed => CONTINUE; ob: TeleDebOps.STObject; address: TeleLoad.CoreAddress; found: BOOL; oldValue: CARDINAL; <> [item: ob, found: found] _ TeleDebOps.FindVariable[host.program, name]; <> IF NOT found THEN { host.out.PutF[" %g: not found\n", IO.rope[name]]; RETURN[FALSE]; } ELSE { -- fetch data and print it address _ ob.addr; host.out.PutF[" %g + %04xH (%04xH^): ", IO.rope[name], IO.card[offset], IO.card[address]]; oldValue _ TeleDebOps.ReadWord[host, address + offset]; IF ob.type = variable THEN { TeleDebOps.WriteWord[host: host, addr: address + offset, value: value]; TeleDebOps.FlushWrites[host]; host.out.PutF["%04xH _ %04xH\n", IO.card[oldValue], IO.card[value]]; } ELSE { host.out.PutF["%04xH . . . not a variable\n", IO.card[oldValue]]; RETURN[FALSE]; }; }; }; RETURN[TRUE]; }; }. <> <> <> <> <>