<> <> <> <> DIRECTORY DebuggerFormat USING[ ExternalStateVector, Run, SwapInfo, VersionID, VMRunTable ], PrincOps USING[ PDA ], WorldVM USING[Address, CopyRead, World], WVMPrivate; WVMBackingMap: MONITOR IMPORTS WorldVM, WVMPrivate EXPORTS WVMPrivate, WorldVM = { VMBackingMapObject: PUBLIC TYPE = RECORD[ found: CARDINAL _ 0, -- maplog entries read in so far -- entries: REF DebuggerFormat.VMRunTable]; VMBackingMap: TYPE = REF VMBackingMapObject; CreateVMBackingMap: PUBLIC PROC[world: WorldVM.World] RETURNS[ VMBackingMap ] = { RETURN[NEW[VMBackingMapObject _ [0,NIL]]] }; ReadVMBackingMap: PUBLIC PROC[world: WorldVM.World, log: VMBackingMap] RETURNS[basic, real: WorldVM.Address] = { swapInfo: DebuggerFormat.SwapInfo; swapInfoAddr: WorldVM.Address = LOOPHOLE[@PrincOps.PDA.available]; esv: DebuggerFormat.ExternalStateVector; esvAddr: WorldVM.Address; WorldVM.CopyRead[world, swapInfoAddr, SIZE[DebuggerFormat.SwapInfo], @swapInfo]; esvAddr _ LOOPHOLE[swapInfo.externalStateVector]; WorldVM.CopyRead[world, esvAddr, SIZE[DebuggerFormat.ExternalStateVector], @esv]; basic _ WVMPrivate.PageAddress[esv.loadstatepage]; real _ LOOPHOLE[esv.loadState]; SELECT esv.versionident FROM DebuggerFormat.VersionID => { IF esv.vmRunTable # NIL THEN { temp: ARRAY [0..SIZE[DebuggerFormat.VMRunTable[0]]) OF WORD; cheat: POINTER TO DebuggerFormat.VMRunTable = LOOPHOLE[@temp]; WorldVM.CopyRead[world, LOOPHOLE[esv.vmRunTable, WorldVM.Address], SIZE[DebuggerFormat.VMRunTable[0]], @temp ]; log.entries _ NEW[DebuggerFormat.VMRunTable[cheat.length]]; WorldVM.CopyRead[world, LOOPHOLE[esv.vmRunTable, WorldVM.Address], SIZE[DebuggerFormat.VMRunTable[cheat.length]], LOOPHOLE[log.entries, LONG POINTER] ]; log.found _ log.entries.nRuns; }; }; ENDCASE => NULL; -- treat as if there was no maplog }; AddressFault: PUBLIC ERROR[mempage: WVMPrivate.PageNumber] = CODE; lastEntryIndex: CARDINAL _ 0; -- hint for log entry to try first -- GetVMBackingMapEntry: PUBLIC ENTRY PROC[log: VMBackingMap, mempage: WVMPrivate.PageNumber] RETURNS[ WVMPrivate.DiskAddress ] = { ENABLE UNWIND => NULL; entry: LONG POINTER TO DebuggerFormat.Run _ IF lastEntryIndex IN [0..log.found) -- lastEntryIndex may be for another log! THEN @log.entries[lastEntryIndex] ELSE NIL; IF entry = NIL OR mempage NOT IN [entry.page..entry.page+entry.count) THEN { <> FOR i: CARDINAL IN [0..log.found) DO entry _ @log.entries[lastEntryIndex_i]; IF mempage IN [entry.page..entry.page+entry.count) THEN EXIT; REPEAT FINISHED => ERROR AddressFault[mempage] ENDLOOP; }; RETURN[[entry.deviceType, entry.deviceOrdinal, entry.diskPage, mempage-entry.page, entry.labelCheck]]; }; }.