<> <> DIRECTORY Ascii, Basics, Convert, CSegDebugDefs, ListerUtils, PrincOps, RESOut, Rope, ViewerTools; CSegDebugContents: CEDAR PROGRAM IMPORTS Basics, Convert, CSegDebugDefs, ListerUtils, RESOut, Rope, ViewerTools EXPORTS CSegDebugDefs = BEGIN OPEN RESOut, CSegDebugDefs; BYTE: TYPE = CSegDebugDefs.BYTE; ROPE: TYPE = Rope.ROPE; GFH: TYPE = PrincOps.GlobalFrameHandle; RopeForEsc: PUBLIC PROC [alpha: BYTE] RETURNS [r: ROPE] = {}; RopeForSdName: PUBLIC PROC [op: BYTE] RETURNS [r: ROPE] = {}; ShortREAD: PROC [addr: POINTER] RETURNS [UNSPECIFIED] = TRUSTED { RETURN [addr^]}; ReadCodeWord: PROC [gf: GFH, delta: INTEGER] RETURNS [UNSPECIFIED] = TRUSTED { code: PrincOps.FrameCodeBase _ gf.code; code.out _ FALSE; RETURN[(LOOPHOLE[code, LONG POINTER TO UNSPECIFIED]+delta)^]}; EscName: PROC [handle: Handle, alpha: BYTE] = { esc: ROPE = RopeForEsc[alpha]; eLength: CARDINAL = Rope.Length[esc]; IF eLength < 8 THEN THROUGH [eLength..8) DO PChar[handle, Ascii.SP] ENDLOOP ELSE PChar[handle, Ascii.SP]; PRope[handle, esc]}; SdName: PROC [handle: Handle, op: BYTE] = { s: ROPE = RopeForSdName[op]; sLength: CARDINAL = Rope.Length[s]; IF sLength < 8 THEN THROUGH [sLength..8) DO PChar[handle, Ascii.SP] ENDLOOP ELSE PChar[handle, Ascii.SP]; PRope[handle, s]}; GetByte: PROC [handle: Handle, gf: GFH] RETURNS [b: BYTE] = BEGIN w: RECORD [high, low: BYTE] = GetWord[handle, handle.offset, gf]; b _ IF handle.byte = 0 THEN w.high ELSE w.low; handle.byte _ 1 - handle.byte; IF handle.byte = 0 THEN handle.offset _ handle.offset + 1; END; GetWord: PROC [handle: Handle, delta: INTEGER, gf: GFH] RETURNS [UNSPECIFIED] = BEGIN RETURN [ReadCodeWord[gf, delta]]; END; PutAsCode: PUBLIC PROCEDURE [handle: Handle] = BEGIN nBytes: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.nVal]; handle.shortfall _ PutCodeBytes[handle, nBytes]; handle.bytesShown _ nBytes - handle.shortfall; END; PutAsOctal: PUBLIC PROCEDURE [handle: Handle] = BEGIN nBytes: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.nVal]; bytePC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal]; handle.offset _ bytePC/2; handle.byte _ bytePC MOD 2; IF handle.byte # 0 THEN handle.offset _ handle.offset + 1; PutOctalWords[handle, nBytes]; handle.bytesShown _ 2*nBytes + handle.byte; END; PutAsAscii: PUBLIC PROCEDURE [handle: Handle] = BEGIN nBytes: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.nVal]; bytePC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal]; handle.offset _ bytePC/2; handle.byte _ bytePC MOD 2; PutAsciiText[handle, nBytes]; handle.bytesShown _ nBytes; END; PutAsBytes: PUBLIC PROCEDURE [handle: Handle] = BEGIN nBytes: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.nVal]; bytePC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal]; handle.offset _ bytePC/2; handle.byte _ bytePC MOD 2; PutOctalBytes[handle, nBytes]; handle.bytesShown _ nBytes; END; DisplayPrefix: PUBLIC PROC [handle: Handle] = BEGIN csp: REF PrincOps.CSegPrefix; gfo: REF PrincOps.GlobalFrame; gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]]; PCr[handle]; gfo _ ReadGFrame[handle, gf]; PRope[handle, "Frame - gfi: "]; POctal[handle, gfo.gfi]; PrintCodeBase[handle, gfo.code]; IF gfo.codelinks THEN PNext[handle, "codelinks"]; IF gfo.started THEN PNext[handle, "started"]; IF gfo.copied THEN PNext[handle, "copied"]; IF gfo.alloced THEN PNext[handle, "alloced"]; IF gfo.shared THEN PNext[handle, "shared"]; IF gfo.trapxfers THEN PNext[handle, "trapxfers"]; PCr[handle]; PRope[handle, "Code - "]; csp _ ReadPrefix[handle, gf]; PRope[handle, "ngfi: "]; POctal[handle, csp.header.info.ngfi]; PNextUnsigned[handle, "nlinks", csp.header.info.nlinks]; IF csp.header.info.stops THEN PNext[handle, "stops"]; IF csp.header.swapinfo # 0 THEN PNextUnsigned[handle, "swapinfo", csp.header.swapinfo]; END; PrintCodeBase: PROC [handle: Handle, code: PrincOps.FrameCodeBase] = BEGIN wasOut: BOOLEAN = code.out; code.out _ FALSE; PNextLongOctal[handle, "code base", code.longbase] ; IF wasOut THEN PNext[handle, "out"]; END; ReadPrefix: PROC [handle: Handle, gf: GFH] RETURNS [csp: REF PrincOps.CSegPrefix] = TRUSTED BEGIN code: PrincOps.FrameCodeBase _ gf.code; ph: LONG POINTER TO PrincOps.CSegPrefix; code.out _ FALSE; ph _ LOOPHOLE[code]; csp _ NEW[PrincOps.CSegPrefix _ ph^]; END; ReadGFrame: PROC [handle: Handle, gf: GFH] RETURNS [gfRef: REF PrincOps.GlobalFrame] = <> TRUSTED BEGIN IF gf = PrincOps.NullGlobalFrame THEN Complain[handle, "not a valid global frame"]; gfRef _ NEW [PrincOps.GlobalFrame _ gf^]; END; GoToLf: PUBLIC PROC [handle: Handle, lf: PrincOps.FrameHandle] = { OPEN PrincOps; overhead: POINTER TO Frame; <> TRUSTED { overhead _ LOOPHOLE[lf, POINTER TO Frame.local]; ViewerTools.SetContents [ handle.cmd.gfVal, Convert.RopeFromInt[from: LOOPHOLE[overhead.accesslink, CARDINAL], base: 8, showRadix: TRUE]]; ViewerTools.SetContents [ handle.cmd.bpcVal, Convert.RopeFromInt[from: LOOPHOLE[overhead.pc, CARDINAL], base: 8, showRadix: TRUE]]}; }; DspLf: PUBLIC PROC [handle: Handle, lf: PrincOps.FrameHandle] = { OPEN PrincOps; overhead: POINTER TO Frame; nlocals: CARDINAL; fsi: CARDINAL; PCr[handle]; PRope[handle, "Local Frame: "]; POctal[handle, lf]; IF LOOPHOLE[lf, CARDINAL] MOD 4 # 0 THEN { PRope[handle, " -- not 0 mod 4"]; RETURN}; <> TRUSTED { fsi _ LOOPHOLE[lf-1, POINTER TO CARDINAL]^; overhead _ LOOPHOLE[lf, POINTER TO Frame.local]; PNextUnsigned[handle, "fsi", fsi]; PNextOctal[handle, "ret", overhead.returnlink]; PNextOctal[handle, "gf", overhead.accesslink]; PNextOctal[handle, "pc", overhead.pc]}; nlocals _ IF fsi IN FrameSizeIndex THEN FrameVec[fsi] - localbase ELSE 0; PCr[handle]; TRUSTED {FOR i: CARDINAL IN [0..nlocals) DO val: CARDINAL = ShortREAD[lf + localbase + i]; cols: CARDINAL _ Log8[val]; IF val > 7 THEN cols _ cols + 1; IF i # 0 AND MakeRoom[handle, cols+2, 0] THEN PRope[handle, ", "] ELSE {PRope[handle, "local("]; POctal[handle, i]; PRope[handle, "): "]}; POctal[handle, val]; ENDLOOP}}; PutEntryItem: PUBLIC PROC [handle: Handle, epi: CARDINAL] = BEGIN gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]]; epc: PrincOps.EntryVectorItem = GetEntryItem[handle, epi, gf]; PCr[handle]; PRope[handle, "ep["]; POctal[handle, epi]; PRope[handle, "] = bpc: "]; POctal[handle, epc.initialpc*2]; PNextUnsigned[handle, "fsi", epc.info.framesize]; IF epc.info.nparams # 0 THEN PNextUnsigned[handle, "nparams", epc.info.nparams]; IF epc.info.defaults THEN PNext[handle, "defaults"]; END; GetEntryItem: PROC [handle: Handle, epi: CARDINAL, gf: GFH] RETURNS [evi: PrincOps.EntryVectorItem] = TRUSTED BEGIN offset: CARDINAL = LOOPHOLE [ @LOOPHOLE[1, POINTER TO PrincOps.CSegPrefix].entry[epi], CARDINAL] - 1; p: POINTER TO CARDINAL = LOOPHOLE[@evi]; FOR i: CARDINAL IN [0..SIZE[PrincOps.EntryVectorItem]) DO (p+i)^ _ GetWord[handle, offset+i, gf]; ENDLOOP; END; FindEP: PUBLIC PROC [handle: Handle, pc: CARDINAL] = TRUSTED BEGIN bestPc: CARDINAL _ 0; gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]]; wpc: CARDINAL = pc/2; bestI: INTEGER _ -1; csp: REF PrincOps.CSegPrefix; csp _ ReadPrefix[handle, gf]; FOR i: CARDINAL IN [0..PrincOps.EPRange*csp.header.info.ngfi) DO epOffset: CARDINAL = LOOPHOLE [ @LOOPHOLE[1, POINTER TO PrincOps.CSegPrefix].entry[i], CARDINAL] - 1; evi: PrincOps.EntryVectorItem _ GetEntryItem[handle, i, gf]; IF evi.initialpc <= epOffset THEN EXIT; -- ran off the end IF evi.initialpc IN (bestPc..wpc] THEN {bestI _ i; bestPc _ evi.initialpc}; ENDLOOP; PCr[handle]; PRope[handle, "pc = "]; POctal[handle, pc]; IF bestI = -1 THEN PRope[handle, " not found"] ELSE {PRope[handle, " closest to ep "]; POctal[handle, bestI]; PutEntryItem[handle, bestI]}; END; PutLink: PUBLIC PROC [handle: Handle, lki: PUBLIC CARDINAL] = TRUSTED BEGIN codeLinks: BOOLEAN; link: PrincOps.ControlLink; gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]]; gfo: REF PrincOps.GlobalFrame; gfo _ ReadGFrame[handle, gf]; codeLinks _ gfo.codelinks; link _ IF codeLinks THEN GetWord[handle, -1-lki, gf] ELSE ShortREAD[ LOOPHOLE[gf - SIZE[PrincOps.GlobalFrame]-1-lki]]; PCr[handle]; PRope[handle, SELECT TRUE FROM codeLinks => "(code", ENDCASE => "(frame"]; PRope[handle, ")link["]; POctal[handle, lki]; PRope[handle, "] = "]; POctal[handle, link]; IF link.proc THEN { PRope[handle, " = ["]; POctal[handle, link.gfi]; PChar[handle, ',]; POctal[handle, link.ep]; PChar[handle, ',]; POctal[handle, link.tag]; PChar[handle, ']];}; END; PutAsProcDesc: PUBLIC PROC [handle: Handle, desc: UNSPECIFIED] = BEGIN link: PrincOps.ControlLink = desc; PCr[handle]; POctal[handle, desc]; PRope[handle, " = "]; SELECT TRUE FROM link.proc => { PChar[handle, '[]; POctal[handle, link.gfi]; PChar[handle, ',]; POctal[handle, link.ep]; PChar[handle, ',]; POctal[handle, link.tag]; PChar[handle, ']];}; link.indirect => PRope[handle, " (indirect)"]; ENDCASE => PRope[handle, " (frame)"]; END; PrintPos: PROC [handle: Handle, word, bytepc: BOOLEAN _ FALSE, delta: CARDINAL _ 1] = BEGIN parity: ARRAY [0..1] OF ROPE = [",E", ",O"]; pc: CARDINAL _ 2*handle.offset + handle.byte - delta; wo: CARDINAL _ pc / 2; bo: CARDINAL _ pc MOD 2; IF word THEN POctal[handle, wo]; IF word AND bytepc THEN {PRope[handle, parity[bo]]; PChar[handle, Ascii.TAB]}; IF bytepc THEN POctal[handle, pc]; PChar[handle, ':]; PChar[handle, Ascii.TAB]; END; PutCodeBytes: PROC [handle: Handle, n: CARDINAL] RETURNS [unused: CARDINAL] = { bytePC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal]; RETURN[GenOperations[handle, bytePC, PutInstLine, n! UNWIND => handle.bytesShown _ handle.bytesSeen]]}; GenOperations: PUBLIC PROC [handle: Handle, startPC: CARDINAL, Action: PROC [handle: Handle, pc: CARDINAL, op: Operation] RETURNS [BOOLEAN], n: CARDINAL] RETURNS [unused: CARDINAL] = BEGIN gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]]; --op: Operation; il: [0..3]; pc: CARDINAL; inst: BYTE; total: CARDINAL = n; IF handle.opData = NIL THEN TRUSTED {handle.opData _ ListerUtils.GetOpCodeArray[]}; handle.offset _ startPC/2; handle.byte _ startPC MOD 2; WHILE n > 0 DO ENABLE UNWIND => handle.bytesSeen _ total - n; pc _ handle.offset*2+handle.byte; inst _ GetByte[handle, gf]; il _ MAX[handle.opData[inst].length, 1]; IF il > n THEN RETURN[n]; {op: Operation _ [inst: inst, params: il-1]; SELECT il FROM 1 => NULL; 2 => op.param[1] _ GetByte[handle, gf]; 3 => {op.param[1] _ GetByte[handle, gf]; op.param[2] _ GetByte[handle, gf]}; ENDCASE; n _ n - il; IF Action[handle, pc, op] THEN EXIT; }; ENDLOOP; RETURN[0]; END; PutInstLine: PROC [handle: Handle, pc: CARDINAL, op: Operation] RETURNS [stop: BOOLEAN _ FALSE] = BEGIN parity: ARRAY [0..1] OF ROPE = [",E", ",O"]; oper: Operation = op; -- PrincOps has an op defined in it PutPair: PROC [handle: Handle, alpha: CARDINAL] = BEGIN a: CARDINAL = alpha/16; b: CARDINAL = alpha MOD 16; PChar[handle, '[]; POctal[handle, a]; PChar[handle, ',]; POctal[handle, b]; PChar[handle, ']]; RETURN END; PCr[handle]; POctal[handle, pc/2]; PRope[handle, parity[pc MOD 2]]; PChar[handle, Ascii.TAB]; POctal[handle, pc]; PChar[handle, ':]; PChar[handle, Ascii.TAB]; PRope[handle, RopeForMop[handle, oper.inst]]; SELECT oper.params FROM 0 => IF oper.inst IN JumpOp THEN { PChar[handle, Ascii.TAB]; PutJumpAddress[handle, op.inst, 0]}; 1 => BEGIN OPEN PrincOps; PChar[handle, Ascii.TAB]; SELECT oper.inst FROM zRILP, zWILP, zRXLP, zWXLP, zRIGP, zRXLPL, zWXLPL, zRXGPL, zWXGPL, zRILPL, zWILPL, zRIGPL, zWIGPL => PutPair[handle, oper.param[1]]; ENDCASE => POctal[handle, oper.param[1]]; IF oper.inst IN JumpOp THEN PutJumpAddress[handle, oper.inst, oper.param[1]]; SELECT oper.inst FROM zMISC => EscName[handle, oper.param[1]]; zKFCB => SdName[handle, oper.param[1]]; ENDCASE; END; 2 => BEGIN OPEN PrincOps; PChar[handle, Ascii.TAB]; SELECT oper.inst FROM zRF, zWF, zWSF, zRFC, zRFL, zWFL => BEGIN POctal[handle, oper.param[1]]; PRope[handle, ", "]; PutPair[handle, oper.param[2]]; END; ENDCASE => BEGIN POctal[handle, oper.wparam]; END; SELECT oper.inst FROM zJIB, zJIW => NULL; IN JumpOp => PutJumpAddress[handle, oper.inst, oper.wparam]; ENDCASE; END; ENDCASE; END; JumpOp: TYPE = [PrincOps.zJ2..PrincOps.zJIW]; BackupPc: PUBLIC PROC [handle: Handle] = BEGIN oldPC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal]; delta: CARDINAL _ MIN[oldPC, 10]; DoNothing: PROC [handle: Handle, pc: CARDINAL, op: Operation] RETURNS [BOOLEAN] = { RETURN[FALSE]}; WHILE delta # 0 DO IF GenOperations[handle, oldPC - delta, DoNothing, delta] = 0 THEN EXIT; delta _ delta - 1; ENDLOOP; ViewerTools.SetContents [ handle.cmd.bpcVal, Convert.RopeFromInt[from: oldPC - delta, base: 8, showRadix: TRUE]]; END; PutJumpAddress: PROC [handle: Handle, jop: BYTE, arg: INTEGER] = BEGIN OPEN PrincOps; d: RECORD [SELECT OVERLAID * FROM word => [i: INTEGER], bytes => [b1, b2: CSegDebugDefs.BYTE], nibbles => [fill: CSegDebugDefs.BYTE, n1, n2: [0..16)], ENDCASE] = [word[arg]]; SELECT handle.opData[jop].length FROM 1 => SELECT jop FROM IN [zJ2..zJ9] => arg _ jop - zJ2 + 2; IN [zJEQ2..zJEQ9] => arg _ jop - zJEQ2 + 2; IN [zJNE2..zJNE9] => arg _ jop - zJNE2 + 2; ENDCASE => ERROR; 2 => BEGIN IF arg > 177B THEN arg _ Basics.BITOR[arg, 177400B]; arg _ arg - 1; END; ENDCASE => arg _ arg - 2; PRope[handle, " ("]; POctal[handle, 2*handle.offset+handle.byte-1+LOOPHOLE[arg, CARDINAL]]; PChar[handle, ')]; END; Octal0: NumberFormat = [base: 8, unsigned: TRUE, zerofill: FALSE, columns: 0]; Decimal0: NumberFormat = [base: 10, unsigned: TRUE, zerofill: FALSE, columns: 0]; PutOctalWords: PUBLIC PROC [handle: Handle, count: CARDINAL] = BEGIN gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]]; cols, val: CARDINAL; PCr[handle]; FOR i: CARDINAL IN [0..count) DO ENABLE UNWIND => handle.bytesShown _ i*2; -- could be "off" by 1 val _ GetWord[handle, handle.offset, gf]; handle.offset _ handle.offset + 1; cols _ Log8[val]; IF val > 7 THEN cols _ cols + 1; IF i # 0 AND MakeRoom[handle, cols+2, 0] THEN PRope[handle, ", "] ELSE PrintPos[handle: handle, word: TRUE, delta: 2]; POctal[handle, val]; ENDLOOP; END; PutOctalBytes: PUBLIC PROC [handle: Handle, count: CARDINAL] = BEGIN cols, val: CARDINAL; gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]]; PCr[handle]; FOR i: CARDINAL IN [0..count) DO ENABLE UNWIND => handle.bytesShown _ i; val _ GetByte[handle, gf]; cols _ Log8[val]; IF val > 7 THEN cols _ cols + 1; IF i # 0 AND MakeRoom[handle, cols+2, 0] THEN PRope[handle, ", "] ELSE PrintPos[handle, TRUE, TRUE]; POctal[handle, val]; ENDLOOP; END; PutAsciiText: PUBLIC PROC [handle: Handle, count: CARDINAL] = BEGIN cols: CARDINAL; ch: CHARACTER; gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]]; PCr[handle]; FOR i: CARDINAL IN [0..count) DO ENABLE UNWIND => handle.bytesShown _ i; ch _ LOOPHOLE[GetByte[handle, gf]]; cols _ SELECT ch FROM Ascii.CR, Ascii.SP => 4, Ascii.TAB, Ascii.ESC, Ascii.NUL, Ascii.DEL => 5, < 40C => 2, > 200C => 5, ENDCASE => 1; IF i = 0 OR ~MakeRoom[handle, cols, 0] THEN PrintPos[handle, TRUE, TRUE]; SELECT ch FROM Ascii.SP => PRope[handle, ""]; Ascii.CR => PRope[handle, ""]; Ascii.TAB => PRope[handle, ""]; Ascii.ESC => PRope[handle, ""]; Ascii.NUL => PRope[handle, ""]; Ascii.DEL => PRope[handle, ""]; < 40C => {PChar[handle, '^]; PChar[handle, ch + 100B]}; > 200C => {PChar[handle, '<]; PNumber[handle, ch, Octal0]; PChar[handle, '>]}; ENDCASE => PChar[handle, ch]; ENDLOOP; END; END.