MBDebug.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Sandman on 28-Jan-81 10:42:17
Lewis on 25-Sep-81 15:33:42
Levin on January 17, 1984 10:24 am
Russ Atkinson on March 8, 1985 5:00:55 pm PST
DIRECTORY
Ascii USING [SP],
BasicTime USING [earliestGMT, FromPupTime, GMT],
BcdDefs USING [Base, BcdBase, CTHandle, CTIndex, CTNull, FPHandle, FPIndex, FTIndex, FTSelf, MTHandle, MTIndex, NameRecord, NameString, NTHandle, NTIndex, SGHandle, SGIndex, SpaceID, SPHandle, SPIndex],
BcdOps USING [ProcessConfigs, ProcessFramePacks, ProcessModules, ProcessNames, ProcessSegs, ProcessSpaces],
BootFile USING [Location, Header],
BootStartList USING [Base, Entry, Header, Index, SwapUnitInfo, SpaceType, startIndex, StateVectorCounts, Switches],
IO USING [bool, card, PutChar, PutF, PutRope, rope, time],
MB USING [BIndex, Handle, MT, VirtualGlobalFrame],
MBVM USING [CodeSeg, DataSeg, FileSeg, Seg, Segs],
PrincOps USING [GlobalFrameHandle],
Rope USING [Cat, ROPE];
MBDebug: CEDAR PROGRAM
IMPORTS BasicTime, BcdOps, IO, MB, Rope
EXPORTS MB =
BEGIN
data: MB.Handle ← NIL;
InitDebug: PUBLIC PROC [h: MB.Handle] = {data ← h};
FinishDebug: PUBLIC PROC = {data ← NIL};
DumpSegs: PUBLIC PROC [segs: MBVM.Segs, msg: Rope.ROPE] = {
DumpSeg: PROC [s: MBVM.Seg] = {
data.loadmap.PutF["Seg[%n] type: ", IO.card[LOOPHOLE[s]]];
WITH s SELECT FROM
seg: MBVM.DataSeg => data.loadmap.PutRope["data"];
seg: MBVM.CodeSeg => data.loadmap.PutRope["code"];
seg: MBVM.FileSeg => data.loadmap.PutRope["file"];
ENDCASE;
data.loadmap.PutF[", vmpage: %n, info: %g, scriptIndex: %n, booted: %z\N",
IO.card[s.base], IO.rope[GetSwapUnitInfo[s.info]],
IO.card[LOOPHOLE[s.index].LONG], IO.bool[s.bootLoaded]];
IF s.objType ~= data THEN
data.loadmap.PutF[" location: %f[%n,%n]\N",
IO.rope[s.file],
IO.card[s.fileBase], IO.card[s.pages]];
};
data.loadmap.PutF["\NSEGMENT TABLE JUST BEFORE %g:\N\N", IO.rope[msg]];
FOR i: CARDINAL IN [0..segs.length) DO DumpSeg[segs[i]]; ENDLOOP;
};
GetSwapUnitInfo: PROC [info: BootStartList.SwapUnitInfo] RETURNS [Rope.ROPE] = {
RETURN[Rope.Cat[
"[readOnly: ",
IF info.readOnly THEN "T, " ELSE "F, ",
SELECT info.state FROM
resident => "resident",
residentDescriptor => "residentDescriptor",
ENDCASE => "swappable",
"]"
]]
};
DumpInputBcds: PUBLIC PROC = TRUSTED {
OPEN BcdDefs, BcdOps;
data.loadmap.PutRope["\NINPUT BCDS:\N\N"];
FOR i: MB.BIndex IN [0..data.inputBCDs.nBcds) DO
bcd: BcdBase = data.inputBCDs.bcds[i].bcd;
ctb: Base = LOOPHOLE[bcd + bcd.ctOffset];
mtb: Base = LOOPHOLE[bcd + bcd.mtOffset];
ftb: Base = LOOPHOLE[bcd + bcd.ftOffset];
ssb: NameString = LOOPHOLE[bcd + bcd.ssOffset];
level: CARDINAL ← 2;
DumpName: PROC [name: NameRecord] RETURNS [length: CARDINAL] = TRUSTED {
length ← ssb.size[name];
FOR i: CARDINAL IN [name..name+length) DO
data.loadmap.PutChar[ssb.string[i]];
ENDLOOP;
};
DumpCTName: PROC [cti: CTIndex] RETURNS [length: CARDINAL ← 0] = TRUSTED {
cth: CTHandle = @ctb[cti];
IF cth.namedInstance THEN {
FindConfigInstanceName: PROC [nth: NTHandle, nti: NTIndex]
RETURNS [BOOL] = TRUSTED {
WITH namee: nth.item SELECT FROM
config => IF namee.cti = cti THEN {length ← DumpName[nth.name]; RETURN[TRUE]};
ENDCASE;
RETURN[FALSE]
};
[] ← ProcessNames[bcd, FindConfigInstanceName];
data.loadmap.PutRope[": "]; length ← length + 2};
length ← length + DumpName[cth.name];
};
DumpMTName: PROC [mti: MTIndex] RETURNS [length: CARDINAL ← 0] = TRUSTED {
mth: MTHandle = @mtb[mti];
IF mth.namedInstance THEN {
FindModuleInstanceName: PROC [nth: NTHandle, nti: NTIndex]
RETURNS [BOOL] = TRUSTED {
WITH namee: nth.item SELECT FROM
module =>
IF namee.mti = mti THEN {length ← DumpName[nth.name]; RETURN[TRUE]};
ENDCASE;
RETURN[FALSE]
};
[] ← ProcessNames[bcd, FindModuleInstanceName];
data.loadmap.PutRope[": "]; length ← length + 2;
};
length ← length + DumpName[mth.name];
};
DumpConfigsWithParent: PROC [parentConfig: CTIndex] = TRUSTED {
DumpConfigsWithinParent: PROC [cth: CTHandle, cti: CTIndex]
RETURNS [BOOL] = TRUSTED {
IF cth.config = parentConfig THEN {
data.loadmap.PutF["%s", IO.card[level]];
[] ← DumpCTName[cti];
IF cth.nControls > 0 THEN {
data.loadmap.PutRope[" control list:"];
FOR i: CARDINAL IN [0..cth.nControls) DO
data.loadmap.PutChar[Ascii.SP];
WITH cItem: cth.controls[i] SELECT FROM
module => [] ← DumpMTName[cItem.mti];
config => [] ← DumpCTName[cItem.cti];
ENDCASE;
ENDLOOP;
};
data.loadmap.PutChar['\N];
level ← level + 2;
DumpConfigsWithParent[cti];
level ← level - 2;
};
RETURN[FALSE]
};
DumpModulesWithinParent: PROC [mth: MTHandle, mti: MTIndex]
RETURNS [BOOL] = TRUSTED {
IF mth.config = parentConfig THEN {
nameLength: CARDINAL;
data.loadmap.PutF["%s", IO.card[level]];
nameLength ← DumpMTName[mti];
data.loadmap.PutF[" links: %g, framesize: %n, residentFrame: %z, packageable: %z, nGFI: %n,\N",
IO.rope[SELECT mth.linkLoc FROM frame => "frame", ENDCASE => "code"],
IO.card[mth.framesize],
IO.bool[mth.residentFrame], IO.bool[mth.packageable],
IO.card[mth.ngfi]
];
data.loadmap.PutF["%scode: [sgi: %n, linkspace: %z, packed: %z, offset: %n",
IO.card[level+nameLength+2],
IO.card[LOOPHOLE[mth.code.sgi].LONG],
IO.bool[mth.code.linkspace], IO.bool[mth.code.packed],
IO.card[mth.code.offset]
];
IF mth.packageable THEN data.loadmap.PutF[", length: %n", IO.card[mth.code.length]];
data.loadmap.PutRope["]\N"];
};
RETURN[FALSE]
};
[] ← ProcessModules[bcd, DumpModulesWithinParent];
[] ← ProcessConfigs[bcd, DumpConfigsWithinParent];
};
DumpSegment: PROC [sgh: SGHandle, sgi: SGIndex] RETURNS [BOOL] = TRUSTED {
IF sgh.class = code THEN {
DumpCodePacksInSegment: PROC [sph: SPHandle, spi: SPIndex]
RETURNS [BOOL] = TRUSTED {
IF sph.seg = sgi THEN {
FOR i: CARDINAL IN [0..sph.length) DO
space: SpaceID = sph.spaces[i];
data.loadmap.PutRope[" "];
[] ← DumpName[space.name];
data.loadmap.PutF[" resident: %z, relative location: [%n,%n]\N",
IO.bool[space.resident], IO.card[space.offset], IO.card[space.pages]
];
ENDLOOP;
};
RETURN[FALSE]
};
data.loadmap.PutF[" Code Segment [sgi: %n], location: ", IO.card[LOOPHOLE[sgi].LONG]];
IF sgh.file = FTSelf THEN data.loadmap.PutRope["(self)"]
ELSE [] ← DumpName[ftb[sgh.file].name];
data.loadmap.PutF["[%n,%n+%n]\N",
IO.card[sgh.base], IO.card[sgh.pages], IO.card[sgh.extraPages]
];
[] ← ProcessSpaces[bcd, DumpCodePacksInSegment];
};
RETURN[FALSE]
};
DumpFramePack: PROC [fph: FPHandle, fpi: FPIndex] RETURNS [BOOL] = TRUSTED {
data.loadmap.PutRope[" Frame Pack "]; [] ← DumpName[fph.name];
FOR i: CARDINAL IN [0..fph.length) DO
data.loadmap.PutRope["\N "]; [] ← DumpMTName[fph.modules[i]];
ENDLOOP;
data.loadmap.PutChar['\N];
RETURN[FALSE]
};
DumpSwapUnits: PROC = TRUSTED {
data.loadmap.PutF[" BCD is %n pages\N BCD header occupies [1,%n]\N",
IO.card[bcd.nPages], IO.card[bcd.nPages-bcd.rtPages.pages]
];
IF bcd.rtPages.pages = 0 THEN data.loadmap.PutRope[" No RT extension\N"]
ELSE {
data.loadmap.PutF[" RT extension occupies [%n,%n]\N",
IO.card[1+bcd.rtPages.relPageBase], IO.card[bcd.rtPages.pages]
];
};
};
data.loadmap.PutF["Configurations and Modules in %g:\N",
IO.rope[data.inputBCDs.bcds[i].name]];
DumpConfigsWithParent[CTNull];
data.loadmap.PutF["\NCode Segments, Code Packs, and Frame Packs in %g:\N",
IO.rope[data.inputBCDs.bcds[i].name]];
DumpSwapUnits[];
[] ← ProcessSegs[bcd, DumpSegment];
[] ← ProcessFramePacks[bcd, DumpFramePack];
data.loadmap.PutChar['\N];
ENDLOOP;
};
DumpStartList: PUBLIC PROC = TRUSTED {
base: BootStartList.Base ← data.scriptBase;
p: BootStartList.Index ← BootStartList.startIndex;
data.loadmap.PutRope["\NSTART LIST:\N\N"];
DumpStartListHeader[];
data.loadmap.PutRope["Script\N"];
DO
WITH e: base[p] SELECT FROM
space => {
OPEN e;
data.loadmap.PutF[" Space[%n] type: ", IO.card[LOOPHOLE[p].LONG]];
DumpSpaceType[type];
data.loadmap.PutF[", backingStore: %g, booted: %z\N",
IO.rope[IF backingStore = self THEN "self" ELSE "null"],
IO.bool[bootLoaded]
];
data.loadmap.PutF[" vmpage: %n, pages: %n",
IO.card[vmPage], IO.card[pages]];
IF backingStore = self THEN
data.loadmap.PutF[", backingPage: %n", IO.card[backingPage]];
data.loadmap.PutChar['\N];
p ← p + SIZE[space BootStartList.Entry];
};
swapUnit => {
OPEN e;
data.loadmap.PutF[" SwapUnit[%n] parent: %n, base: %n, pages: %n, info: %g\N",
IO.card[LOOPHOLE[p].LONG],
IO.card[LOOPHOLE[parent].LONG],
IO.card[base], IO.card[pages],
IO.rope[GetSwapUnitInfo[info]]
];
p ← p + SIZE[swapUnit BootStartList.Entry];
};
stop => {data.loadmap.PutRope[" Stop\N"]; EXIT};
ENDCASE => {data.loadmap.PutRope["**Unknown BootScript Type\N"]; EXIT};
ENDLOOP;
data.loadmap.PutChar['\N];
};
DumpSpaceType: PROC [type: BootStartList.SpaceType] = {
WITH type SELECT FROM
empty => data.loadmap.PutRope["[empty[]]"];
unitary =>
data.loadmap.PutF["[unitary[swapUnit: %n]]", IO.card[LOOPHOLE[swapUnit].LONG]];
family =>
data.loadmap.PutF["[family[resDescChildren: %z]]", IO.bool[anyResidentDescriptorChildren]];
ENDCASE;
};
DumpStartListHeader: PROC = {
h: REF BootStartList.Header ← data.header;
UCodeTime: PROC [pupTime: LONG CARDINAL] RETURNS [BasicTime.GMT] = {
RETURN [
IF pupTime = 0 THEN BasicTime.earliestGMT ELSE BasicTime.FromPupTime[pupTime]
]
};
data.loadmap.PutF[
"Header (%n)\N version: %n\N release: %n.%n.%n\N",
IO.card[LOOPHOLE[data.scriptBaseInVM]],
IO.card[h.version],
IO.card[h.release.major], IO.card[h.release.minor], IO.card[h.release.patch]
];
data.loadmap.PutF[" buildDate: %t\N", IO.time[BasicTime.FromPupTime[h.buildDate]]];
data.loadmap.PutF[
" uCodeDolphin: %t\N uCodeDorado: %t\N uCodeDandelion: %t\N uCodeDicentra: %t\N",
IO.time[UCodeTime[h.requiredUCode[dolphin]]],
IO.time[UCodeTime[h.requiredUCode[dorado]]],
IO.time[UCodeTime[h.requiredUCode[dandelion]]],
IO.time[UCodeTime[h.requiredUCode[dicentra]]],
];
data.loadmap.PutF[" controlList: %n\N initLoadState: %n\N",
IO.card[LOOPHOLE[h.controlList].LONG],
IO.card[LOOPHOLE[h.initLoadState].LONG]
];
data.loadmap.PutF[" mdsBase: %n\N pdaPages: %n\N",
IO.card[h.mdsBase], IO.card[h.pdaPages]
];
data.loadmap.PutRope[" stateVectorCounts: "];
DumpStateVectorCounts[h.stateVectorCounts];
data.loadmap.PutChar['\N];
data.loadmap.PutF[
" stateVectorSize: %n\N nProcesses: %n\N lastVMPage: %n\N lastBootLoadedPage: %n\N",
IO.card[h.stateVectorSize.LONG],
IO.card[h.nProcesses.LONG],
IO.card[h.lastVMPage],
IO.card[h.lastBootLoadedPage]
];
data.loadmap.PutRope[" switches: "];
DumpSwitches[h.switches];
data.loadmap.PutChar['\N];
data.loadmap.PutRope[" locDebuggerMicrocode: "];
DumpBootLocation[h.locDebuggerMicrocode];
data.loadmap.PutChar['\N];
data.loadmap.PutRope[" locDebuggerGerm: "];
DumpBootLocation[h.locDebuggerGerm];
data.loadmap.PutChar['\N];
data.loadmap.PutRope[" locDebugger: "];
DumpBootLocation[h.locDebugger];
data.loadmap.PutChar['\N];
data.loadmap.PutRope[" locDebuggee: "];
DumpBootLocation[h.locDebuggee];
data.loadmap.PutChar['\N];
};
DumpStateVectorCounts: PROC [svc: BootStartList.StateVectorCounts] = {
data.loadmap.PutChar['[];
FOR i: CARDINAL IN [0..SIZE[BootStartList.StateVectorCounts]) DO
data.loadmap.PutF["%g%n", IO.rope[IF i ~= 0 THEN ", " ELSE NIL], IO.card[svc[i]]];
ENDLOOP;
data.loadmap.PutChar[']];
};
DumpSwitches: PROC [s: BootStartList.Switches] = {
data.loadmap.PutF["[%n, %n, %n, %n]", IO.card[s.a], IO.card[s.b], IO.card[s.c], IO.card[s.d]];
};
DumpBootLocation: PROC [bl: BootFile.Location] = {
bits: ARRAY [0..SIZE[BootFile.Location]) OF CARDINAL = LOOPHOLE[bl];
data.loadmap.PutChar['[];
FOR i: CARDINAL IN [0..SIZE[BootFile.Location]) DO
data.loadmap.PutF["%g%n", IO.rope[IF i ~= 0 THEN ", " ELSE NIL], IO.card[bits[i]]];
ENDLOOP;
data.loadmap.PutChar[']];
};
DumpBootHeader: PUBLIC PROC = {
h: REF BootFile.Header ← data.bootHeader;
data.loadmap.PutF[
"\N\NBOOTFILE HEADER:\N version: %n\N creationDate: %t\N pStartListHeader: %n\N",
IO.card[h.version],
IO.time[BasicTime.FromPupTime[h.creationDate]],
IO.card[LOOPHOLE[h.pStartListHeader.LONG]]];
data.loadmap.PutF[" inLoadMode: %g\N continuation: ",
IO.rope[SELECT h.inLoadMode FROM load => "load", ENDCASE => "restore"]];
WITH h.continuation SELECT FROM
initial =>
data.loadmap.PutF["initial[mdsi: %n, destination: %n]",
IO.card[mdsi],
IO.card[LOOPHOLE[destination].LONG]];
ENDCASE => data.loadmap.PutRope["unexpected variant!!!"];
data.loadmap.PutF["\N countData: %n\N\N", IO.card[h.countData]];
};
DumpFrames: PUBLIC PROC = TRUSTED {
data.loadmap.PutRope["\NGLOBAL FRAMES AT COMPLETION OF LOADING:\N\N"];
FOR i: MB.BIndex IN [0..data.inputBCDs.nBcds) DO
mt: MB.MT = data.inputBCDs.bcds[i].mt;
data.loadmap.PutF["%g\N", IO.rope[data.inputBCDs.bcds[i].name]];
FOR gfi: CARDINAL IN [1..mt.length) DO
frame: PrincOps.GlobalFrameHandle;
IF mt[gfi].mth.gfi ~= gfi THEN LOOP;
frame ← mt[gfi].frame;
data.loadmap.PutF[
" Frame[%n] gfi: %n, shared: %z, alloced: %z, codelinks: %z",
IO.card[LOOPHOLE[frame].LONG],
IO.card[MB.VirtualGlobalFrame[frame].gfi],
IO.bool[MB.VirtualGlobalFrame[frame].shared],
IO.bool[MB.VirtualGlobalFrame[frame].alloced],
IO.bool[MB.VirtualGlobalFrame[frame].codelinks]
];
data.loadmap.PutF[", codebase: %n\N",
IO.card[LOOPHOLE[MB.VirtualGlobalFrame[frame].code.longbase]]
];
ENDLOOP;
data.loadmap.PutChar['\N];
ENDLOOP;
};
END.