TDX.mesa
Teledeb extra stuff
Last modified by Stewart, April 4, 1983 8:06 pm
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
RPCSystem substructure
maxrun: CARDINAL,
caller: ShortCoreAddress, -- caller of Block after maxrun
extra: ARRAY [0..6) OF UNSPECIFIED,
RPCUser substructure
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[];
addr is address of first context, not of context queue.
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];
};
PrintZone, if there is a zone!
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];
};
changes the word at offset from an identifier, use for patch decks
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;
};
internal procedures
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: BOOLEANFALSE ] = {
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: CHARLOOPHOLE[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: NATIF 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.ROPENIL;
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;
Linear search in symbol table
[item: ob, found: found] ← TeleDebOps.FindVariable[host.program, name];
lookup address
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];
};
};
changes the word at offset from an identifier, use for patch decks
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;
Linear search in symbol table
[item: ob, found: found] ← TeleDebOps.FindVariable[host.program, name];
lookup address
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];
};
}.
Last modified by Swinehart, November 13, 1982 4:45 pm
Last modified by Stewart, November 19, 1982 4:43 pm
Last modified by Stewart, December 18, 1982 4:54 pm, better symtab stuff
Last modified by Stewart, December 20, 1982 12:46 pm, PUBLICs
Last modified by Stewart, February 16, 1983 9:52 pm, Binary search bug