-- File: CommDebug.mesa, Last Edit: HGM March 20, 1981 5:15 PM -- This module lives and runs in the debugger. It looks in the users core image to find and print things. DIRECTORY DebugUsefulDefs USING [ Enumerate, Name, ShortREAD, ShortCopyREAD, LongREAD, LongCopyREAD], Event USING [AddNotifier, Item, Masks, Notifier], Format USING [], -- Needed by Put.Number Menu USING [ItemObject, MCRType, Create, Instantiate], UserInput USING [GetDefaultWindow], Put USING [Char, CR, Line, LongNumber, Number, Octal, Text], String USING [EquivalentStrings], Storage USING [Node, Free, FreeNodeNil], Boss USING [bigBoy], BufferMgr USING [accessHandleChainHead, systemBufferQueue], StatsDefs USING [StatCounterIndex], PupRouterDefs USING [ PupRouterSocket, PupRouterSocketObject, RoutingTableEntry, RoutingTableObject], PupDefs USING [defaultNumberOfNetworks], DriverDefs USING [GiantVector, NetworkObject], SpecialSystem USING [HostNumber, NetworkAddress], BufferDefs USING [ Buffer, BufferAccessHandle, BufferAccessObject, BufferObject, OisBufferObject, PupAddress, Queue]; CommDebug: PROGRAM IMPORTS DebugUsefulDefs, Event, Menu, UserInput, Put, String, Storage SHARES Boss, BufferMgr, DriverDefs, BufferDefs = BEGIN OPEN BufferDefs; giantVector: POINTER TO DriverDefs.GiantVector ← NIL; freeQueue: Queue; -- our copies of the real thing routingTable: POINTER TO ARRAY [0..PupDefs.defaultNumberOfNetworks] OF PupRouterDefs.RoutingTableObject ← NIL; routingTableLength: CARDINAL; wordsPerBuffer: CARDINAL; GetThings: PROCEDURE RETURNS [BOOLEAN] = BEGIN IF boss = NIL THEN BEGIN Put.Line[NIL, "Scanning GFT...."L]; LookForFrames[]; IF boss = NIL THEN BEGIN Put.Line[NIL, "**** Can't find Boss!"L]; RETURN[FALSE]; END; IF bufferMgr = NIL THEN BEGIN Put.Line[NIL, "**** Can't find BufferMgr!"L]; RETURN[FALSE]; END; END; Put.CR[NIL]; CopyRead[ to: giantVector, from: @boss.bigBoy, nwords: SIZE[DriverDefs.GiantVector]]; routingTableLength ← LENGTH[giantVector.pupRoutingTable]; freeQueue ← ReadLong[@bufferMgr.systemBufferQueue]; IF routingTableLength > LENGTH[routingTable↑] THEN BEGIN Put.Line[NIL, "routingTable is huge - truncating."L]; routingTableLength ← LENGTH[routingTable↑]; END; LongCopyRead[ to: routingTable, from: BASE[giantVector.pupRoutingTable], nwords: routingTableLength*SIZE[PupRouterDefs.RoutingTableObject]]; wordsPerBuffer ← giantVector.wordsPerBuffer; RETURN[TRUE]; END; PupRoute: PROCEDURE = BEGIN IF ~GetThings[] THEN RETURN; Put.Text[NIL, " Pup Network Routing Table"L]; Put.Line[NIL, " ix hp tm rt network net hst"L]; FOR i: CARDINAL IN [0..routingTableLength) DO rte: PupRouterDefs.RoutingTableEntry; network: DriverDefs.NetworkObject; rte ← @routingTable[i]; IF rte.network # NIL THEN BEGIN O4[i]; D4[rte.hop]; D4[rte.time]; O4[rte.route]; Put.Text[NIL, " "L]; O9L[rte.network]; LongCopyRead[ to: @network, from: rte.network, nwords: SIZE[DriverDefs.NetworkObject]]; O4[network.netNumber.b]; O4[network.hostNumber]; Put.Line[NIL, ""L]; END; ENDLOOP; END; PupSockets: PROCEDURE = BEGIN so: PupRouterDefs.PupRouterSocketObject; IF ~GetThings[] THEN RETURN; Put.Line[NIL, " Pup Socket Table ix loc ready IQ local, remote"L]; LongCopyRead[ to: @so.next, from: giantVector.firstPupSocket, nwords: SIZE[PupRouterDefs.PupRouterSocket]]; FOR i: CARDINAL IN [0..25) UNTIL so.next = NIL DO OPEN so; D2[i]; O9L[next]; LongCopyRead[ to: @so, from: next, nwords: SIZE[PupRouterDefs.PupRouterSocketObject]]; O7[LOOPHOLE[@ready, POINTER]↑]; -- first word of CONDITION is process handle D4[input.length]; Put.Text[NIL, " "L]; PrintPupAddress[local]; Put.Char[NIL, ',]; PrintPupAddress[remote]; Put.Line[NIL, ""L]; ENDLOOP; END; EnumerateBuffers: PROCEDURE [proc: PROCEDURE [Buffer, CARDINAL]] = BEGIN bah: BufferAccessHandle ← ReadLong[@bufferMgr.accessHandleChainHead]; baho: BufferAccessObject; i: CARDINAL ← 0; UNTIL bah = NIL DO b: Buffer; LongCopyRead[to: @baho, from: bah, nwords: SIZE[BufferAccessObject]]; b ← baho.firstBuffer; IF b # NIL THEN BEGIN FOR k: CARDINAL IN [0..MIN[baho.total, 100]) DO proc[b, i]; i ← i + 1; IF i > 100 THEN RETURN; b ← b + baho.wordsPerBuffer; ENDLOOP; END; bah ← baho.next; ENDLOOP; END; Buffers: PROCEDURE = BEGIN IF ~GetThings[] THEN RETURN; Put.Line[NIL, " Buffers n loc queue reque owner next f type dev"L]; EnumerateBuffers[ShowBuffer]; END; ShowBuffer: PROCEDURE [b: Buffer, n: CARDINAL] = BEGIN bo: pup BufferObject; D4[n]; LongCopyRead[to: @bo, from: b, nwords: SIZE[pup BufferObject]]; O9L[b]; Q[bo.queue]; O7[bo.requeueProcedure]; O7[bo.debug]; C[bo.next]; SELECT bo.bufFunc FROM send => Put.Text[NIL, " s"L]; receive => Put.Text[NIL, " r"L]; systemUse => Put.Text[NIL, " "L]; ENDCASE => Put.Text[NIL, " ?"L]; SELECT bo.type FROM raw => Put.Text[NIL, " raw"L]; pup => Put.Text[NIL, " pup"L]; ois => Put.Text[NIL, " ois"L]; ENDCASE => Put.Text[NIL, " ???"L]; SELECT bo.device FROM ethernet => Put.Text[NIL, " EN"L]; sla => Put.Text[NIL, " sla"L]; arpanet => Put.Text[NIL, " AN"L]; packetradio => Put.Text[NIL, " PR"L]; unknown => Put.Text[NIL, " unk"L]; ENDCASE => Put.Text[NIL, " ???"L]; Put.Line[NIL, ""L]; END; PacketsAsPups: PROCEDURE = BEGIN IF ~GetThings[] THEN RETURN; Put.Line[NIL, " Packets as Pups n len PT pupID dest ← source"L]; EnumerateBuffers[ShowPacketsAsPups]; END; ShowPacketsAsPups: PROCEDURE [b: Buffer, n: CARDINAL] = BEGIN bo: pup BufferObject; D4[n]; LongCopyRead[to: @bo, from: b, nwords: SIZE[pup BufferObject]]; D4[bo.pupLength]; SELECT bo.pupType FROM error => Put.Text[NIL, " ERR"L]; rfc => Put.Text[NIL, " RFC"L]; abort => Put.Text[NIL, " AB"L]; end => Put.Text[NIL, " END"L]; endRep => Put.Text[NIL, " ERP"L]; data => Put.Text[NIL, " D"L]; aData => Put.Text[NIL, " aD"L]; ack => Put.Text[NIL, " ACK"L]; mark => Put.Text[NIL, " MK"L]; aMark => Put.Text[NIL, " aM"L]; gatewayRequest => Put.Text[NIL, " GR"L]; gatewayInfo => Put.Text[NIL, " GI"L]; request => Put.Text[NIL, " req"L]; result => Put.Text[NIL, " res"L]; unsolicited => Put.Text[NIL, " uns"L]; custodian => Put.Text[NIL, " cus"L]; sync => Put.Text[NIL, " syn"L]; pineAck => Put.Text[NIL, " pA"L]; noop => Put.Text[NIL, " nop"L]; ENDCASE => O4[bo.pupType]; Put.Text[NIL, " "L]; O7[bo.pupID.a]; O7[bo.pupID.b]; Put.Text[NIL, " "L]; PrintPupAddress[bo.dest]; Put.Text[NIL, " ←"L]; PrintPupAddress[bo.source]; Put.Line[NIL, ""L]; END; PacketsAsOiscp: PROCEDURE = BEGIN IF ~GetThings[] THEN RETURN; Put.Line[NIL, " Packets as Oiscp len PT pupID dest ← source"L]; EnumerateBuffers[ShowPacketsAsOiscp]; END; ShowPacketsAsOiscp: PROCEDURE [b: Buffer, n: CARDINAL] = BEGIN bo: OisBufferObject; D4[n]; LongCopyRead[to: @bo, from: b, nwords: SIZE[ois BufferObject]]; D4[bo.ois.pktLength]; SELECT bo.ois.transCntlAndPktTp.packetType FROM routingInformation => Put.Text[NIL, " RTI"L]; echo => Put.Text[NIL, " Eco"L]; error => Put.Text[NIL, " Err"L]; packetExchange => Put.Text[NIL, " PE"L]; sequencedPacket => Put.Text[NIL, " SPP"L]; ENDCASE => O4[bo.ois.transCntlAndPktTp.packetType]; Put.Text[NIL, " "L]; PrintOiscpAddress[bo.ois.destination]; Put.Text[NIL, " ←"L]; PrintOiscpAddress[bo.ois.source]; Put.Line[NIL, ""L]; END; BufferChain: PROCEDURE = BEGIN bah: BufferAccessHandle; IF ~GetThings[] THEN RETURN; Put.Line[NIL, " Buffer Control Blocks ru su r s t v first next"L]; bah ← ReadLong[@bufferMgr.accessHandleChainHead]; FOR i: CARDINAL IN [0..100) UNTIL bah = NIL DO baho: BufferAccessObject; LongCopyRead[to: @baho, from: bah, nwords: SIZE[BufferAccessObject]]; D3[baho.receiveInUse]; D3[baho.sendInUse]; D3[baho.receive]; D3[baho.send]; D3[baho.total]; D3[baho.reserve]; O9L[baho.firstBuffer]; O9L[baho.next]; IF baho.madeForSystem THEN Put.Text[NIL, ", System"L]; IF ~baho.active THEN Put.Text[NIL, ", Not Active"L]; Put.Line[NIL, ""L]; bah ← baho.next; ENDLOOP; END; All: PROCEDURE = BEGIN IF ~GetThings[] THEN RETURN; BufferChain[]; PupRoute[]; PupSockets[]; Buffers[]; PacketsAsPups[]; PacketsAsOiscp[]; END; -- Interface to the debugger Read: PROCEDURE [p: POINTER] RETURNS [UNSPECIFIED] = BEGIN RETURN[DebugUsefulDefs.ShortREAD[p]]; END; ReadLong: PROCEDURE [from: POINTER] RETURNS [x: LONG UNSPECIFIED] = BEGIN CopyRead[to: @x, from: from, nwords: 2]; END; LongRead: PROCEDURE [LONG POINTER] RETURNS [UNSPECIFIED] = DebugUsefulDefs.LongREAD; CopyRead: PROCEDURE [to: POINTER, from: POINTER, nwords: CARDINAL] = BEGIN DebugUsefulDefs.ShortCopyREAD[from: from, nwords: nwords, to: to]; END; LongCopyRead: PROCEDURE [to: POINTER, from: LONG POINTER, nwords: CARDINAL] = BEGIN DebugUsefulDefs.LongCopyREAD[from: from, nwords: nwords, to: to]; END; LongReadLong: PROCEDURE [from: LONG POINTER] RETURNS [x: LONG UNSPECIFIED] = BEGIN LongCopyRead[to: @x, from: from, nwords: 2]; END; -- Print out Statistics Counters: TYPE = ARRAY StatsDefs.StatCounterIndex OF LONG INTEGER; Strings: TYPE = ARRAY StatsDefs.StatCounterIndex OF STRING; Stats: PROCEDURE = BEGIN hisCounters: Counters; hisStrings: Strings; s: StatsDefs.StatCounterIndex; temp: STRING = [204]; -- maxlength gets clobbered IF ~GetThings[] THEN RETURN; LongCopyRead[ to: @hisCounters, from: giantVector.statCounters, nwords: SIZE[Counters]]; LongCopyRead[ to: @hisStrings, from: giantVector.statStrings, nwords: SIZE[Strings]]; FOR s IN StatsDefs.StatCounterIndex DO IF hisCounters[s] = 0 THEN LOOP; LD10[hisCounters[s]]; Put.Char[NIL, ' ]; IF hisStrings[s] # NIL THEN BEGIN CopyRead[to: temp, from: hisStrings[s], nwords: 100]; Put.Line[NIL, temp]; END ELSE Put.CR[NIL]; ENDLOOP; END; -- get a block of info from the "right" address space PrintPupAddress: PROCEDURE [a: PupAddress] = BEGIN Put.Char[NIL, ' ]; Put.Octal[NIL, a.net]; Put.Char[NIL, '#]; Put.Octal[NIL, a.host]; Put.Char[NIL, '#]; IF a.socket.a # 0 THEN BEGIN Put.Octal[NIL, a.socket.a]; Put.Char[NIL, '|]; END; Put.Octal[NIL, a.socket.b]; END; PrintOiscpAddress: PROCEDURE [a: SpecialSystem.NetworkAddress] = BEGIN Put.Char[NIL, ' ]; IF a.net.a # 0 THEN BEGIN Put.Octal[NIL, a.net.a]; Put.Char[NIL, '|]; END; Put.Octal[NIL, a.net.b]; Put.Char[NIL, '#]; PrintHostNumber[a.host]; Put.Char[NIL, '#]; Put.Octal[NIL, a.socket]; END; PrintHostNumber: PROCEDURE [host: SpecialSystem.HostNumber] = BEGIN WITH h: host SELECT FROM physical => BEGIN IF h.a # 0 THEN BEGIN Put.Octal[NIL, h.a]; Put.Char[NIL, '|]; END; IF h.a # 0 OR h.b # 0 THEN BEGIN Put.Octal[NIL, h.b]; Put.Char[NIL, '|]; END; Put.Octal[NIL, h.c]; END; multicast => BEGIN Put.Char[NIL, 'M]; IF h.a # 0 THEN BEGIN Put.Octal[NIL, h.a]; Put.Char[NIL, '|]; END; IF h.a # 0 OR h.b # 0 THEN BEGIN Put.Octal[NIL, h.b]; Put.Char[NIL, '|]; END; Put.Octal[NIL, h.c]; END; ENDCASE => ERROR; END; C: PROCEDURE [b: Buffer] = BEGIN IF b = NIL THEN Put.Text[NIL, " NIL"L] ELSE O9L[b]; END; -- Printout routines D2: PROCEDURE [num: UNSPECIFIED] = BEGIN Put.Number[NIL, num, [10, FALSE, TRUE, 2]]; END; D3: PROCEDURE [num: UNSPECIFIED] = BEGIN Put.Number[NIL, num, [10, FALSE, TRUE, 3]]; END; D4: PROCEDURE [num: UNSPECIFIED] = BEGIN Put.Number[NIL, num, [10, FALSE, TRUE, 4]]; END; D5: PROCEDURE [num: UNSPECIFIED] = BEGIN Put.Number[NIL, num, [10, FALSE, TRUE, 5]]; END; D6: PROCEDURE [num: UNSPECIFIED] = BEGIN Put.Number[NIL, num, [10, FALSE, TRUE, 6]]; END; LP: PROCEDURE [num: LONG POINTER] = BEGIN short: RECORD [p: POINTER, other: WORD] = LOOPHOLE[num]; Put.Char[NIL, IF short.other = 0 THEN ' ELSE '?]; Put.Number[NIL, short.p, [8, FALSE, TRUE, 6]]; END; LD10: PROCEDURE [num: LONG INTEGER] = BEGIN Put.LongNumber[NIL, num, [10, FALSE, TRUE, 10]]; END; O3: PROCEDURE [num: UNSPECIFIED] = BEGIN Put.Number[NIL, num, [8, FALSE, TRUE, 3]]; END; O4: PROCEDURE [num: UNSPECIFIED] = BEGIN Put.Number[NIL, num, [8, FALSE, TRUE, 4]]; END; O9L: PROCEDURE [num: LONG UNSPECIFIED] = BEGIN Put.LongNumber[NIL, num, [8, FALSE, TRUE, 9]]; END; O7: PROCEDURE [num: UNSPECIFIED] = BEGIN Put.Number[NIL, num, [8, FALSE, TRUE, 7]]; END; Q: PROCEDURE [q: Queue] = BEGIN SELECT q FROM NIL => Put.Text[NIL, " none"L]; freeQueue => Put.Text[NIL, " free"L]; ENDCASE => O9L[q]; END; SetUp: PROCEDURE = BEGIN giantVector ← Storage.Node[SIZE[DriverDefs.GiantVector]]; routingTable ← Storage.Node[ (PupDefs.defaultNumberOfNetworks + 1)*SIZE[ PupRouterDefs.RoutingTableObject]]; END; SetDown: PROCEDURE = BEGIN IF giantVector # NIL THEN giantVector ← Storage.FreeNodeNil[giantVector]; IF routingTable # NIL THEN routingTable ← Storage.FreeNodeNil[routingTable]; END; items: ARRAY [0..8) OF Menu.ItemObject ← [["All", DoInfo], ["BufferChain", DoInfo], ["PupRoute", DoInfo], ["PupSockets", DoInfo], ["Buffers", DoInfo], ["Pups", DoInfo], ["Oiscp", DoInfo], ["Statistics", DoInfo]]; all: CARDINAL = 0; bufferChain: CARDINAL = 1; pupRoute: CARDINAL = 2; pupSockets: CARDINAL = 3; buffers: CARDINAL = 4; pups: CARDINAL = 5; oiscp: CARDINAL = 6; stats: CARDINAL = 7; DoInfo: Menu.MCRType = BEGIN SetUp[]; SELECT index FROM all => All[]; bufferChain => BufferChain[]; pupRoute => PupRoute[]; pupSockets => PupSockets[]; pups => PacketsAsPups[]; oiscp => PacketsAsOiscp[]; buffers => Buffers[]; stats => Stats[]; ENDCASE => ERROR; SetDown[]; END; boss: POINTER TO FRAME[Boss] ← NIL; bufferMgr: POINTER TO FRAME[BufferMgr] ← NIL; nMods: CARDINAL = 2; LookForFrames: PROCEDURE = BEGIN moduleName: ARRAY [0..nMods) OF STRING ← ["Boss"L, "BufferMgr"L]; basePtr: ARRAY [0..nMods) OF POINTER ← [@boss, @bufferMgr]; keyString: STRING = [40]; nFound: CARDINAL ← 0; CheckOneFrame: PROCEDURE [han: UNSPECIFIED] RETURNS [BOOLEAN] = BEGIN name: POINTER TO ARRAY [0..nMods) OF STRING = @moduleName; base: POINTER TO ARRAY [0..nMods) OF POINTER = @basePtr; key: STRING = keyString; key.length ← 0; DebugUsefulDefs.Name[name: key, gf: han]; FOR i: CARDINAL IN [0..nMods) DO IF String.EquivalentStrings[key, name[i]] THEN BEGIN IF base[i]↑ = NIL THEN BEGIN base[i]↑ ← han; nFound ← nFound + 1 END ELSE BEGIN Put.Text[NIL, "Duplicate: "L]; Put.Line[NIL, key]; END; EXIT END; ENDLOOP; RETURN[nFound = nMods]; END; FOR i: CARDINAL IN [0..nMods) DO basePtr[i]↑ ← NIL; ENDLOOP; [] ← DebugUsefulDefs.Enumerate[CheckOneFrame]; IF nFound # nMods THEN BEGIN FOR i: CARDINAL IN [0..nMods) DO IF basePtr[i]↑ = NIL THEN BEGIN Put.Text[NIL, "Missing: "L]; Put.Line[NIL, moduleName[i]]; END; ENDLOOP; END; END; notifierItem: Event.Item ← [eventMask: Event.Masks[newSession], eventProc: Notify]; Notify: Event.Notifier = BEGIN SELECT why FROM newSession => BEGIN boss ← NIL; END; ENDCASE; END; -- initialization Event.AddNotifier[@notifierItem]; Menu.Instantiate[ Menu.Create[DESCRIPTOR[items], "Pup"], UserInput.GetDefaultWindow[]]; END.