DIRECTORY BasicTime USING[GMT, Now, Period], CardTab, CCTypes USING[CCError, CCErrorCase, CreateIndirectNode, GetIndirectCreateNode, GetIndirectType, GetRopeType, SetRopeType], CedarOtherPureTypes USING[CreateIndirectToAnUnknownType, CreateRopeNode, CreateUnknownType], CirioMemory, CirioNubAccess USING[Handle, LookupSymEntryByName, RemoteAddress, SymEntry], CirioTypes, Frames USING[CreateIndirectFrameNode, CreateIndirectFrameType, CreateIndirectGlobalFrameNode, CreateIndirectGlobalFrameType, IndirectFrameData, IndirectFrameTypeData, IndirectGlobalFrameData, IndirectGlobalFrameTypeData], --IntHashTable,-- IO, LoadStateAccess, MobAccess, MobObjectFiles USING[FindNearBTHAncestorsForBlock, FindNearBTHAncestorsForPC, GetCatchPhraseStrandedStaticLinkLoc, GetGlobalFrameVarLoc, GetGlobalLinkVar, GetLocalFrameExtensionVar, GetRootBTH, GetSPOffset, GetStaticLinkVar, GetStrandedStaticLinkLoc, GetVarLoc, JointMobParsedInfo, VarLoc, VarLocBody], NewRMTW USING[BaToCnra, CedarModuleSet, FrameNodeInfo, GetLoadedModuleInfo, LoadedModuleInfo, RawFrameInfo], RefTab USING[Create, Fetch, Store], RMTWPrivate, Rope, SymTab, SystemInterface USING [ShowReport]; RMTWFrames: CEDAR PROGRAM IMPORTS BasicTime, CardTab, CCTypes, CedarOtherPureTypes, CirioMemory, CirioNubAccess, CirioTypes, Frames, --IntHashTable,-- IO, LoadStateAccess, MobAccess, MobObjectFiles, NewRMTW, RefTab, RMTWPrivate, Rope, --SymTab,-- SystemInterface EXPORTS NewRMTW, RMTWPrivate = BEGIN OPEN LSA:LoadStateAccess, MA:MobAccess, MOF:MobObjectFiles, RMTWPrivate; CCE: ERROR[case: CCTypes.CCErrorCase, msg: ROPE _ NIL] _ CCTypes.CCError; BTH: TYPE = MA.BTH; BTR: TYPE = MA.BTR; RemoteAddress: TYPE = CirioNubAccess.RemoteAddress; InvalidRemoteAddress: RemoteAddress _ [NIL, 0, 0, FALSE, FALSE]; invalidPtr: CARD = CARD.LAST; RemoteMimosaTargetWorldBody: PUBLIC TYPE = RMTWPrivate.RemoteMimosaTargetWorldBody; CreateRemoteMimosaTargetWorld: PUBLIC PROC[serverName: ROPE, handle: CirioNubAccess.Handle, cc: CC, cedarModules: NewRMTW.CedarModuleSet, lsh: LSA.LoadStateHandle, reports: IO.STREAM, setCTC: BOOL] RETURNS[RemoteMimosaTargetWorld] = BEGIN now: BasicTime.GMT ~ BasicTime.Now[]; rmtw: RemoteMimosaTargetWorld _ NEW[RemoteMimosaTargetWorldBody_[ sehHash: CreateSehHashTable[], bthHash: CreateBthHashTable[], ctxHash: CreateCtxHashTable[], tcHash: CardTab.Create[], unknownSymbolFlushTime: now, ropeStudyTime: now, atomRecRT: NIL, serverName: serverName, nub: handle, cc: cc, moduleScope: NEW [CirioTypes.ModuleScopeBody _ [GetModule, DontGetInterface, NIL]], cedarModules: cedarModules, lsh: lsh, setCTC: setCTC]]; rmtw.moduleScope.data _ rmtw; IF setCTC THEN StudyRopes[rmtw]; RETURN[rmtw]; END; GetRMTWInfo: PUBLIC PROC [rmtw: RemoteMimosaTargetWorld] RETURNS [serverName: ROPE, handle: CirioNubAccess.Handle, cc: CC, cedarModules: NewRMTW.CedarModuleSet, lsh: LSA.LoadStateHandle] ~ {RETURN[rmtw.serverName, rmtw.nub, rmtw.cc, rmtw.cedarModules, rmtw.lsh]}; GetModuleScope: PUBLIC PROC [rmtw: RemoteMimosaTargetWorld] RETURNS [CirioTypes.ModuleScope] ~ {RETURN [rmtw.moduleScope]}; FlushUnknownSymbolCache: PUBLIC PROC[rmtw: RemoteMimosaTargetWorld, flushTime: BasicTime.GMT, reports: IO.STREAM] = { rmtw.unknownSymbolFlushTime _ flushTime; RETURN}; GetNodeForCedarFrame: PUBLIC PROC[rmtw: RemoteMimosaTargetWorld, loadedModuleInfo: REF NewRMTW.LoadedModuleInfo, rawFrameInfo: REF NewRMTW.RawFrameInfo] RETURNS[REF NewRMTW.FrameNodeInfo] = BEGIN cc: CC _ rmtw.cc; ledo: REF LSA.LoadedModuleInfo _ loadedModuleInfo.loadedModule; dotORelPC: CARD _ rawFrameInfo.absPC - ledo.lsi[text].base; jmpi: MOF.JointMobParsedInfo _ loadedModuleInfo.jmpi; IF jmpi = NIL THEN CCE[operation, "can't find mob or dotO"] ELSE BEGIN blockList: LIST OF BTH _ MOF.FindNearBTHAncestorsForPC[dotORelPC, jmpi]; rootBTH: BTH _ MOF.GetRootBTH[jmpi]; SELECT TRUE FROM (blockList = NIL) => RETURN[NEW[NewRMTW.FrameNodeInfo _ [NIL, GetBadCedarFrameDiagnosticInfo, NEW[BadCedarFrameInfo_["blockList was NIL"]]]]]; (blockList.first = NIL) => RETURN[NEW[NewRMTW.FrameNodeInfo _ [NIL, GetBadCedarFrameDiagnosticInfo, NEW[BadCedarFrameInfo_["blockList.first was NIL"]]]]]; blockList.first = rootBTH => BEGIN -- the frame is the global frame (probably one of the special C procedures) frameTypeInfo: FrameComponentInfo _ CreateIndirectGlobalFrameInfoFromRootBTH[blockList.first, jmpi, ledo, rmtw, FALSE]; targetType: Type _ frameTypeInfo.type; gfTypeInfo: GlobalFrameTypeInfo _ NARROW[frameTypeInfo.typeInfo]; moduleMem: Mem; frameNode: Node; moduleMem _ MakeDualMem[ nub: rmtw.nub, fp: invalidPtr, sp: invalidPtr, fep: [unspecdBA, unspecdBA], text: ledo.lsi[text], data: ledo.lsi[data], bss: ledo.lsi[bss], simple: [unspecdBA, unspecdBA] ]; frameNode _ FinalCreateIndirectGlobalFrameNode[gfTypeInfo, moduleMem].gf; RETURN[NEW[NewRMTW.FrameNodeInfo _ [frameNode, GetBadCedarFrameDiagnosticInfo, NEW[BadCedarFrameInfo_["the frame is the global frame"]]]]]; END; ENDCASE => BEGIN -- this is the normal case (a Mesa procedure) frameTypeInfo: FrameComponentInfo _ CreateProcedureFrameInfoFromBlockList[blockList, loadedModuleInfo, rmtw]; targetType: Type _ frameTypeInfo.type; procFrameTypeInfo: ProcFrameTypeInfo _ NARROW[frameTypeInfo.typeInfo]; codeBase: RemoteAddress _ RemoteAddrFromCard[rmtw, ledo.lsi[text].base]; fes: BitStretch; fm: Mem; frameNode: Node; frameNodeInfo: ProcFrameNodeInfo; WITH procFrameTypeInfo.basicInfo.frameExtensionVarLoc SELECT FROM f: REF frame MOF.VarLocBody => { fes _ [ CirioTypes.BaCons[rawFrameInfo.framePointer, f.bitOffset], CirioTypes.BitsToBa[f.bitSize] ]; }; f: REF indirect MOF.VarLocBody => { WITH f.base SELECT FROM f2: REF frame MOF.VarLocBody => { fes _ [ CirioTypes.BaCons[rawFrameInfo.framePointer, f2.bitOffset], CirioTypes.BitsToBa[f2.bitSize] ]; { tm: Mem ~ CreateSimpleMem[NewRMTW.BaToCnra[rmtw.nub, fes.start], ptrSize]; realStart: CARD _ tm.MemRead[bitsPerPtr, zeroBA]; fes _ [start: CirioTypes.PtrToBa[realStart], size: unspecdBA] }; }; ENDCASE => fes _ [unspecdBA, unspecdBA]; }; ENDCASE => fes _ [unspecdBA, unspecdBA]; fm _ MakeDualMem[ nub: rmtw.nub, fp: rawFrameInfo.framePointer, sp: rawFrameInfo.stackPointer, fep: fes, text: ledo.lsi[text], data: ledo.lsi[data], bss: ledo.lsi[bss], simple: [unspecdBA, unspecdBA] ]; [] _ fm.MemReadSegReg["text", 0]; --make sure it got created OK frameNode _ FinalBuildProcFrameNode[procFrameTypeInfo, NIL, fm, rmtw]; frameNodeInfo _ NEW[ProcFrameNodeInfoBody_[procFrameTypeInfo, fm, frameNode]]; RETURN[NEW[NewRMTW.FrameNodeInfo _ [frameNode, GetCedarFrameDiagnosticInfo, frameNodeInfo]]]; END; END; END; FrameComponentInfo: TYPE = REF FrameComponentInfoBody; FrameComponentInfoBody: TYPE = RECORD[ analyzedCTX: AnalyzedCTX, -- NIL if not appropriate type: Type, typeInfo: REF ANY _ ]; GetFrameComponentInfoForUnknown: PROC[explanation: ROPE, rmtw: RemoteMimosaTargetWorld] RETURNS[REF FrameComponentInfoBody] = BEGIN type: Type _ CedarOtherPureTypes.CreateUnknownType[rmtw.cc, explanation]; RETURN[NEW[FrameComponentInfoBody_[NIL, type, NIL]]]; END; RegByteSize: CARD = 4; CreateSimpleMem: PUBLIC PROC[addr: CirioNubAccess.RemoteAddress, size: BitAddr _ unspecdBA] RETURNS[Mem] ~ { RETURN[CirioMemory.CreateSimpleMem[addr, size]]; }; MakeDualMem: PUBLIC PROC [nub: CirioNubAccess.Handle, fp, sp: CARD, text, data, bss: LSA.LoadedSegmentInfo, fep, simple: BitStretch] RETURNS [mem: Mem] ~ { RETURN[CirioMemory.MakeDualMem[nub, fp, sp, LsiGetBitStr[text], LsiGetBitStr[data], LsiGetBitStr[bss], fep, simple]]; }; SelectVarLoc: PUBLIC PROC [nub: CirioNubAccess.Handle, fm: Mem, vl: MobObjectFiles.VarLoc] RETURNS [ans: Mem] ~ { thisSize: BitAddr; IF vl.bitSize = 0 OR vl.bitSize >= CARD[LAST[INT]] THEN CCE[cirioError, "implausible varLoc.bitSize"]; thisSize _ CirioTypes.BitsToBa[vl.bitSize]; WITH vl SELECT FROM regVL: REF register MOF.VarLocBody => { rego: INT ~ (regVL.regNum-16)*RegByteSize; --MJS February 6, 1990: this is where the SPARC stores the register, relative to the stack pointer IF NOT regVL.regNum IN [16..32) THEN CCE[cirioError, IO.PutFR1["trying to select var loc in register %g", [cardinal[regVL.regNum]] ]]; --MJS February 5, 1990: I suspect that on SPARCs, as reported through .o files, only registers 16-31 are used ans _ fm.MemPtrRegIndirect[sp, thisSize, CirioTypes.AusToBa[rego], TRUE]; }; frameVL: REF frame MOF.VarLocBody => ans _ fm.MemPtrRegIndirect[fp, thisSize, CirioTypes.BitsToBa[frameVL.bitOffset], TRUE]; frameExtVL: REF frameExtension MOF.VarLocBody => ans _ fm.MemPtrRegIndirect[fe, thisSize, CirioTypes.BitsToBa[frameExtVL.bitOffset], TRUE]; sVL: REF fSegment MOF.VarLocBody => { segName: ROPE ~ sVL.fSeg.fSegName; segMem: Mem ~ fm.MemSelectSegment[segName, 0, TRUE]; ans _ segMem.MemSubfield[[CirioTypes.BitsToBa[sVL.bitOffset], thisSize]]; }; ncVL: REF namedCommon MOF.VarLocBody => { EnsureAbsValid[nub, ncVL]; IF NOT ncVL.absFound THEN CCE[cirioError, IO.PutFR["can't find named common \"%q\"", [rope[ncVL.name]] ]]; ans _ fm.class.CreateSimple[fm.data, [CirioTypes.PtrToBa[ncVL.absBase].BaAdd[CirioTypes.BitsToBa[ncVL.bitOffset]], thisSize], TRUE]}; uVL: REF unknown MOF.VarLocBody => { CCE[cirioError, IO.PutFR["trying to resolve unknown (because %g) VarLoc", [rope[uVL.why]] ]]}; iVL: REF indirect MOF.VarLocBody => { sub: Mem ~ SelectVarLoc[nub, fm, iVL.base]; ans _ sub.MemIndirect[thisSize, iVL.offset]}; ENDCASE => ERROR; IF pickySelect AND vl.bitSize < bitsPerPtr THEN CCE[cirioError, "SelectVarLoc[bitSize<32, ...]"]; RETURN}; pickySelect: BOOL _ FALSE; --MJS, August 15, 1991: don't want to make this check for C; maybe there's a reason we want to make it for Cedar? EnsureAbsValid: PUBLIC PROC [nub: CirioNubAccess.Handle, nc: REF namedCommon MOF.VarLocBody] ~ { IF NOT nc.absValid THEN { se: CirioNubAccess.SymEntry ~ CirioNubAccess.LookupSymEntryByName[nub, nc.name, TRUE, TRUE, 0]; IF se#NIL THEN {nc.absBase _ se.value; nc.absFound _ TRUE} ELSE nc.absFound _ FALSE; nc.absValid _ TRUE}; RETURN}; CreateBthHashTable: PUBLIC PROC RETURNS[BthHashTable] = {RETURN[NEW[BthHashTableBody _ [RefTab.Create[]]]]}; GetBthInfo: PROC[bth: BTH, tw: RemoteMimosaTargetWorld] RETURNS[BthInfo] = BEGIN info: BthInfo _ NARROW[RefTab.Fetch[tw.bthHash.table, bth].val]; IF info = NIL THEN BEGIN info _ NEW[BthInfoBody_[NIL, tw.unknownSymbolFlushTime, NIL, NIL, NIL]]; IF NOT RefTab.Store[tw.bthHash.table, bth, info] THEN CCE[cirioError]; -- shouldn't happen END; IF BasicTime.Period[info.effectiveFlushTime, tw.unknownSymbolFlushTime] > 0 THEN BEGIN info.effectiveFlushTime _ tw.unknownSymbolFlushTime; info.nestedBlock _ NIL; info.basicProcedureFrameInfo _ NIL; info.fullProcedureFrameInfo _ NIL; END; RETURN[info]; END; BasicProcFrameTypeInfo: TYPE = REF BasicProcFrameTypeInfoBody; BasicProcFrameTypeInfoBody: TYPE = RECORD[ lmi: REF NewRMTW.LoadedModuleInfo, callableBTH, rootBTH: BTH, enclosingBlockList: LIST OF BTH, args: FrameComponentInfo, results: FrameComponentInfo, frameExtensionVar: SEH, -- the frameExtension variable IS the frame extension frameExtensionVarLoc: MOF.VarLoc, staticLinkVar: SEH, -- holds a pointer to the frameExtension of the static enclosing procedure frame staticLinkVarLoc: MOF.VarLoc, globalLinkVar: SEH, -- holds a pointer to the global frame variable of the module. globalLinkVarLoc: MOF.VarLoc, spOffset: INT, -- the SP equals the FP + spOffset, hence spOffset is negative enclosingContext: FrameComponentInfo ]; GenDiagnosticRopesFromBasicProcFrameTypeInfo: PROC[info: BasicProcFrameTypeInfo, for: PROC[ROPE]] = BEGIN for[IO.PutFR["codedBti for callable bth = %g", IO.card[MA.GetCodedBTIFromBTH[info.callableBTH]]]]; END; CreateBasicProcedureFrameInfo: PROC[bth: BTH, lmi: REF NewRMTW.LoadedModuleInfo, rmtw: RemoteMimosaTargetWorld] RETURNS[BasicProcFrameTypeInfo] = { bthInfo: BthInfo _ GetBthInfo[bth, rmtw]; jmpi: MOF.JointMobParsedInfo _ lmi.jmpi; IF bthInfo.basicProcedureFrameInfo = NIL THEN { btr: BTR _ MA.FetchBTR[bth]; basicInfo: BasicProcFrameTypeInfo _ NEW[BasicProcFrameTypeInfoBody]; basicInfo.enclosingBlockList _ MOF.FindNearBTHAncestorsForBlock[bth, jmpi]; basicInfo.rootBTH _ MOF.GetRootBTH[jmpi]; basicInfo.lmi _ lmi; WITH btr.extension SELECT FROM ext: REF Callable MA.BTRExtension => { ioTypeSer: SER _ MA.FetchSER[ext.ioType]; WITH ioTypeSer.body SELECT FROM cons: REF cons MA.BodySE => WITH cons.typeInfo SELECT FROM transfer: REF transfer MA.TypeInfoConsSE => { basicInfo.args _ CreateArgResultRcdInfo[transfer.typeIn, bth, jmpi, rmtw]; basicInfo.results _ CreateArgResultRcdInfo[transfer.typeOut, bth, jmpi, rmtw]}; basic: REF basic MA.TypeInfoConsSE => { basicInfo.args _ CreateArgResultRcdInfo[NIL, bth, jmpi, rmtw]; basicInfo.results _ CreateArgResultRcdInfo[NIL, bth, jmpi, rmtw]} ENDCASE => CCE[cirioError]; ENDCASE => CCE[cirioError]}; ENDCASE => CCE[cirioError]; basicInfo.callableBTH _ bth; basicInfo.frameExtensionVar _ MOF.GetLocalFrameExtensionVar[bth, jmpi]; basicInfo.frameExtensionVarLoc _ MOF.GetVarLoc[basicInfo.frameExtensionVar, bth, jmpi]; basicInfo.staticLinkVar _ MOF.GetStaticLinkVar[bth, jmpi]; IF basicInfo.staticLinkVar#NIL THEN basicInfo.staticLinkVarLoc _ MOF.GetVarLoc[basicInfo.staticLinkVar, bth, jmpi] ELSE { IF btr.class=Scope THEN basicInfo.staticLinkVarLoc _ MOF.GetStrandedStaticLinkLoc[bth, jmpi] ELSE IF btr.class=Catch THEN basicInfo.staticLinkVarLoc _ MOF.GetCatchPhraseStrandedStaticLinkLoc[bth, jmpi]; }; IF basicInfo.frameExtensionVar=NIL AND basicInfo.staticLinkVarLoc#NIL THEN { IF btr.class=Scope OR btr.class=Catch THEN basicInfo.frameExtensionVarLoc _ MakeIndirect[basicInfo.staticLinkVarLoc]; }; basicInfo.globalLinkVar _ MOF.GetGlobalLinkVar[bth, jmpi]; basicInfo.globalLinkVarLoc _ MOF.GetVarLoc[basicInfo.globalLinkVar, bth, jmpi]; basicInfo.spOffset _ MOF.GetSPOffset[bth, jmpi]; { rootBTH: BTH _ basicInfo.rootBTH; enclosingBlockList: LIST OF BTH _ basicInfo.enclosingBlockList; IF enclosingBlockList = NIL THEN basicInfo.enclosingContext _ GetFrameComponentInfoForUnknown["enclosingBlockList = NIL", rmtw] ELSE IF enclosingBlockList.first = NIL THEN basicInfo.enclosingContext _ GetFrameComponentInfoForUnknown["enclosingBlockList.first = NIL", rmtw] ELSE IF enclosingBlockList.first = rootBTH THEN { basicInfo.enclosingContext _ CreateIndirectGlobalFrameInfoFromRootBTH[enclosingBlockList.first, jmpi, lmi.loadedModule, rmtw, FALSE]; } ELSE { basicInfo.enclosingContext _ CreateProcedureFrameInfoFromBlockList[enclosingBlockList, lmi, rmtw]; }; }; bthInfo.basicProcedureFrameInfo _ basicInfo; }; RETURN[bthInfo.basicProcedureFrameInfo]; }; MakeIndirect: PROC [vl: MOF.VarLoc] RETURNS [MOF.VarLoc] ~ { tmpLoc: MOF.VarLoc _ NIL; IF vl=NIL THEN RETURN[NIL]; RETURN [NEW[MOF.VarLocBody _ [ bitSize: vl.bitSize --MJS doesn't know why this is right, on Dec 13, 1991--, where: indirect[base: vl, offset: zeroBA] ]] ]}; CreateArgResultRcdInfo: PROC[seh: SEH, bth: BTH, jmpi: MOF.JointMobParsedInfo, rmtw: RemoteMimosaTargetWorld] RETURNS[FrameComponentInfo] = BEGIN IF seh = NIL THEN RETURN[AnalyzeCTXAsBlockRecord[NIL, bth, jmpi, rmtw]] ELSE BEGIN underSeh: SEH _ UnderTypeSEH[seh, rmtw]; -- should we build definition types? underSer: SER _ MA.FetchSER[underSeh]; WITH underSer.body SELECT FROM cons: REF cons MA.BodySE => WITH cons.typeInfo SELECT FROM ti: REF record MA.TypeInfoConsSE => RETURN[AnalyzeCTXAsBlockRecord[ti.fieldCtx, bth, jmpi, rmtw]]; ENDCASE => CCE[cirioError]; ENDCASE => CCE[cirioError]; END; END; ProcFrameTypeInfo: TYPE = REF ProcFrameTypeInfoBody; ProcFrameTypeInfoBody: TYPE = RECORD[ basicInfo: BasicProcFrameTypeInfo, frameType: Type, frameTypeData: REF Frames.IndirectFrameTypeData, nestedBlocks: SEQUENCE nBlocks: CARDINAL OF RECORD[bth: BTH, info: FrameComponentInfo]]; BthInfo: TYPE = REF BthInfoBody; BthInfoBody: TYPE = RECORD[ rmtw: RemoteMimosaTargetWorld, effectiveFlushTime: BasicTime.GMT, nestedBlock: FrameComponentInfo, basicProcedureFrameInfo: BasicProcFrameTypeInfo, fullProcedureFrameInfo: FrameComponentInfo ]; GenDiagnosticRopesFromProcFrameTypeInfo: PROC[info: ProcFrameTypeInfo, for: PROC[ROPE]] = BEGIN GenDiagnosticRopesFromBasicProcFrameTypeInfo[info.basicInfo, for]; END; CreateProcedureFrameInfoFromBlockList: PROC[blockList: LIST OF BTH, lmi: REF NewRMTW.LoadedModuleInfo, rmtw: RemoteMimosaTargetWorld] RETURNS[FrameComponentInfo] = { blockInfo: AnalyzedBlockList _ AnalyzeBlockList[blockList]; bthInfo: BthInfo _ GetBthInfo[blockInfo.lastBlock, rmtw]; IF bthInfo.fullProcedureFrameInfo = NIL THEN { correctBL: LIST OF BTH _ CorrectBL[blockList]; correctABL: AnalyzedBlockList _ AnalyzeBlockList[correctBL]; basicFrameInfo: BasicProcFrameTypeInfo _ CreateBasicProcedureFrameInfo[blockList.first, lmi, rmtw]; firstBTR: BTR _ MA.FetchBTR[blockList.first]; nBlocks: CARDINAL _ correctABL.nBlocks; frameInfo: ProcFrameTypeInfo _ NEW[ProcFrameTypeInfoBody[nBlocks]]; frameTypeData: REF Frames.IndirectFrameTypeData _ NEW[Frames.IndirectFrameTypeData[nBlocks]]; index: CARDINAL _ 0; FOR bl: LIST OF BTH _ correctBL, bl.rest WHILE bl # NIL DO frameInfo.nestedBlocks[index] _ [bl.first, CreateNestedBlockRecordFromBTH[bl.first, lmi.jmpi, rmtw]]; index _ index + 1; ENDLOOP; frameTypeData.enclosingContext _ basicFrameInfo.enclosingContext.type; frameTypeData.args _ CCTypes.GetIndirectType[basicFrameInfo.args.type]; frameTypeData.results _ CCTypes.GetIndirectType[basicFrameInfo.results.type]; FOR I: CARDINAL IN [0..nBlocks) DO frameTypeData.blocks[I] _ CCTypes.GetIndirectType[frameInfo.nestedBlocks[I].info.type]; ENDLOOP; frameInfo.basicInfo _ basicFrameInfo; frameInfo.frameType _ Frames.CreateIndirectFrameType[frameTypeData, rmtw.cc]; frameInfo.frameTypeData _ frameTypeData; bthInfo.fullProcedureFrameInfo _ NEW[FrameComponentInfoBody _ [NIL, frameInfo.frameType, frameInfo]]; }; RETURN[bthInfo.fullProcedureFrameInfo]}; CorrectBL: PROC [blockList: LIST OF BTH] RETURNS [LIST OF BTH] ~ { firstBTR: BTR _ MA.FetchBTR[blockList.first]; childH: BTH _ firstBTR.firstSon; childR: BTR; bestSrc: CARD _ CARD.LAST; bestChild: BTH _ NIL; IF firstBTR.localCtx#NIL THEN RETURN[blockList]; IF firstBTR.class#Scope THEN RETURN[blockList.rest]; WHILE childH#NIL DO childR _ MA.FetchBTR[childH]; IF childR.sourceIndex <= bestSrc THEN { bestSrc _ childR.sourceIndex; bestChild _ childH}; IF childR.link.which=sibling THEN childH _ childR.link.index ELSE childH _ NIL; ENDLOOP; IF bestChild#NIL THEN RETURN[CONS[bestChild, blockList.rest]]; RETURN[blockList.rest]}; AnalyzedBlockList: TYPE = RECORD[nBlocks: CARDINAL, lastBlock: BTH]; AnalyzeBlockList: PROC[blockList: LIST OF BTH] RETURNS[AnalyzedBlockList] = { nominalNBlocks: CARDINAL _ 0; lastBlock: BTH; FOR bl: LIST OF BTH _ blockList, bl.rest WHILE bl # NIL DO nominalNBlocks _ nominalNBlocks + 1; lastBlock _ bl.first; ENDLOOP; RETURN[[nominalNBlocks, lastBlock]]}; ProcFrameNodeInfo: TYPE = REF ProcFrameNodeInfoBody; ProcFrameNodeInfoBody: TYPE = RECORD[ procFrameTypeInfo: ProcFrameTypeInfo, frameMem: Mem, frameNode: Node]; GetCedarFrameDiagnosticInfo: PROC[frame: REF NewRMTW.FrameNodeInfo] RETURNS[LIST OF ROPE] = { first, last: LIST OF ROPE _ NIL; info: ProcFrameNodeInfo _ NARROW[frame.data]; append: PROC[rope: ROPE] = { cell: LIST OF ROPE _ LIST[rope]; IF first = NIL THEN first _ cell ELSE last.rest _ cell; last _ cell}; append["a Cedar Frame"]; GenDiagnosticRopesFromProcFrameTypeInfo[info.procFrameTypeInfo, append]; RETURN[first]}; BadCedarFrameInfo: TYPE = RECORD[rope: ROPE]; GetBadCedarFrameDiagnosticInfo: PROC[frame: REF NewRMTW.FrameNodeInfo] RETURNS[LIST OF ROPE] = { info: REF BadCedarFrameInfo _ NARROW[frame.data]; RETURN[LIST[info.rope]]}; ProcFrameNodeData: TYPE = REF ProcFrameNodeDataBody; ProcFrameNodeDataBody: TYPE = RECORD[ frameTypeInfo: ProcFrameTypeInfo, descriptor: ROPE, mem: Mem, rmtw: RemoteMimosaTargetWorld]; FinalBuildProcFrameNode: PROC[frameTypeInfo: ProcFrameTypeInfo, descriptor: ROPE, mem: Mem, rmtw: RemoteMimosaTargetWorld] RETURNS[Node] = { basicInfo: BasicProcFrameTypeInfo _ frameTypeInfo.basicInfo; args: Node _ CCTypes.GetIndirectCreateNode[basicInfo.args.type, mem, rmtw.cc]; results: Node _ CCTypes.GetIndirectCreateNode[basicInfo.results.type, mem, rmtw.cc]; enclosingMem: Mem _ [NIL, NIL]; enclosingContext: Node; ifd: REF Frames.IndirectFrameData _ NEW[Frames.IndirectFrameData[frameTypeInfo.nBlocks]]; SELECT TRUE FROM basicInfo.enclosingBlockList = NIL => enclosingContext _ UnknownTypeNode["enclosingBlockList = NIL", rmtw.cc]; basicInfo.enclosingBlockList.first = NIL => enclosingContext _ UnknownTypeNode["enclosingBlockList.first = NIL", rmtw.cc]; basicInfo.enclosingBlockList.first = basicInfo.rootBTH => { gfti: GlobalFrameTypeInfo _ NARROW[basicInfo.enclosingContext.typeInfo]; enclosingContext _ FinalCreateIndirectGlobalFrameNode[gfti, mem].gf; }; ENDCASE => { enclPFTI: ProcFrameTypeInfo _ NARROW[basicInfo.enclosingContext.typeInfo]; staticVarLoc: MOF.VarLoc _ basicInfo.staticLinkVarLoc; staticVarMem: Mem _ noMem; enclosingFeBase: CARD; spOffset: INT _ enclPFTI.basicInfo.spOffset; enclosingFe, enclosingFP, enclosingSP: BitAddr; IF staticVarLoc#NIL THEN staticVarMem _ SelectVarLoc[rmtw.nub, mem, staticVarLoc !CCE, CirioMemory.Error => CONTINUE]; IF staticVarMem=noMem THEN { enclosingFe _ unspecdBA; enclosingSP _ enclosingFP _ CirioTypes.PtrToBa[invalidPtr]; } ELSE { enclosingFeBase _ staticVarMem.MemRead[bitsPerPtr, zeroBA]; enclosingFe _ CirioTypes.PtrToBa[enclosingFeBase]; WITH enclPFTI.basicInfo.frameExtensionVarLoc SELECT FROM vl: REF frame MOF.VarLocBody => { enclosingFP _ CirioMemory.BaAddOffset[enclosingFe, -vl.bitOffset]; enclosingSP _ IF spOffset=0 THEN CirioTypes.PtrToBa[invalidPtr] ELSE CirioMemory.BaAddOffset[enclosingFP, spOffset]}; ENDCASE => enclosingFP _ enclosingSP _ CirioTypes.PtrToBa[invalidPtr]; }; enclosingMem _ MakeDualMem[ nub: rmtw.nub, fp: IF enclosingFP.bits=0 THEN enclosingFP.BaToPtr ELSE CCE[cirioError, "non-AU-aligned enclosing FP"], sp: IF enclosingSP.bits=0 THEN enclosingSP.BaToPtr ELSE CCE[cirioError, "non-AU-aligned enclosing SP"], fep: [enclosingFe, unspecdBA], text: MemGetLsi[mem, "text", 0], data: MemGetLsi[mem, "data", 0], bss: MemGetLsi[mem, "bss", 0], simple: [unspecdBA, unspecdBA] ]; [] _ enclosingMem.MemReadSegReg["text", 0]; --make sure it's OK IF enclosingSP#CirioTypes.PtrToBa[invalidPtr] THEN { -- lets confirm it spRegLoc: MOF.VarLoc _ NEW[MOF.VarLocBody _[32, register[30]]]; spRegMem: Mem _ SelectVarLoc[rmtw.nub, enclosingMem, spRegLoc]; nominalFP: CARD _ spRegMem.MemRead[bitsPerPtr, zeroBA]; IF nominalFP # LOOPHOLE[enclosingFP.aus] THEN enclosingMem.class.SetPtrReg[enclosingMem.data, sp, [unspecdBA, unspecdBA]]; -- confirmation failed }; enclosingContext _ FinalBuildProcFrameNode[enclPFTI, NIL, enclosingMem, rmtw]; }; ifd.procedure _ UnknownTypeNode["frame's procedures not implemented", rmtw.cc]; ifd.enclosingContext _ enclosingContext; IF CCTypes.GetRopeType[rmtw.cc]=NIL THEN { ut: CirioTypes.Type _ CedarOtherPureTypes.CreateUnknownType[rmtw.cc, "unknown type involved in final proc frame node"]; ifd.descriptor _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[ut, "final proc frame node", rmtw.cc];} ELSE ifd.descriptor _ CedarOtherPureTypes.CreateRopeNode[descriptor, rmtw.cc]; <> ifd.args _ args; ifd.results _ results; ifd.getSourcePosition _ DummyGetSourcePosition; ifd.getCallingNode _ GetCallingNode; -- this is not the recommended way to walk the stack, but is needed for compatiability purposes, specifically, to support registration mechanisms in CCTypesImpl. Further, this procedure may be implicitly assuming that the calling frame is also a (recognizable) Cedar frame. ifd.procData _ NEW[ProcFrameNodeDataBody_[ frameTypeInfo: frameTypeInfo, descriptor: descriptor, mem: mem, rmtw: rmtw]]; FOR I: CARDINAL IN [0..frameTypeInfo.nBlocks) DO blockType: Type _ frameTypeInfo.nestedBlocks[I].info.type; indBlockType: Type _ CCTypes.GetIndirectType[blockType]; ifd.blocks[I] _ CCTypes.CreateIndirectNode[indBlockType, mem, rmtw.cc]; ENDLOOP; RETURN Frames.CreateIndirectFrameNode[ifd, frameTypeInfo.frameType, rmtw.cc]}; RemoteAddrFromCard: PROC[tw: RemoteMimosaTargetWorld, card: CARD, bitOffset: CARD _ 0] RETURNS[RemoteAddress] = {RETURN[[tw.nub, card, bitOffset, FALSE, tw.nub # NIL]]}; DummyGetSourcePosition: PROC[procData: REF ANY, cc: CC] RETURNS[CirioTypes.Node] = {CCE[unimplemented]}; GetCallingNode: PROC[procData: REF ANY, cc: CC] RETURNS[CirioTypes.Node] = { data: ProcFrameNodeData _ NARROW[procData]; rmtw: RemoteMimosaTargetWorld _ data.rmtw; calleeFM: Mem _ data.mem; calleeStack: Mem _ calleeFM.MemPtrRegIndirect[sp, unspecdBA, zeroBA, FALSE]; callerPC: CARD _ calleeStack.MemRead[bitsPerPtr, CirioTypes.AusToBa[15*4]]; callerLedo: REF LSA.LoadedModuleInfo _ LSA.GetLoadedModuleInfoFromAbsPC[rmtw.lsh, callerPC, rmtw.cedarModules]; callerStack: Mem _ calleeFM.MemPtrRegIndirect[fp, unspecdBA, zeroBA, FALSE]; callerSpBa: BitAddr _ calleeFM.MemReadPtrReg[fp].start; callerSP: CARD _ IF callerSpBa.bits=0 THEN callerSpBa.BaToPtr ELSE ERROR; callerFP: CARD _ callerStack.MemRead[bitsPerPtr, CirioTypes.AusToBa[14*4]]; callerRawFrameInfo: REF NewRMTW.RawFrameInfo _ NEW[NewRMTW.RawFrameInfo_[ absPC: callerPC, framePointer: callerFP, stackPointer: callerSP]]; callerLoadedModuleInfo: REF NewRMTW.LoadedModuleInfo _ NewRMTW.GetLoadedModuleInfo[rmtw.cedarModules, callerLedo]; frameInfo: REF NewRMTW.FrameNodeInfo _ GetNodeForCedarFrame[rmtw, callerLoadedModuleInfo, callerRawFrameInfo]; RETURN[frameInfo.node]}; UnknownTypeNode: PROC[explanation: ROPE, cc: CC] RETURNS[CirioTypes.Node] = BEGIN unknownType: CirioTypes.Type _ CedarOtherPureTypes.CreateUnknownType[cc, explanation]; RETURN[CedarOtherPureTypes.CreateIndirectToAnUnknownType[unknownType, explanation, cc]]; END; GlobalFrameTypeInfo: TYPE = REF GlobalFrameTypeInfoBody; GlobalFrameTypeInfoBody: TYPE = RECORD[ rmtw: RemoteMimosaTargetWorld, jmpi: MOF.JointMobParsedInfo, rootBTH: BTH, globalFrameVarLoc: MOF.VarLoc, globalVars: FrameComponentInfo, gfType: Type]; CreateIndirectGlobalFrameInfoFromRootBTH: PROC[rootBTH: BTH, jmpi: MOF.JointMobParsedInfo, ledo: REF LSA.LoadedModuleInfo, rmtw: RemoteMimosaTargetWorld, helply: BOOL] RETURNS[FrameComponentInfo] = BEGIN globalFrameVarLoc: MOF.VarLoc _ MOF.GetGlobalFrameVarLoc[jmpi]; globalVars: FrameComponentInfo _ CreateGlobalVarsInfoFromBTH[rootBTH, globalFrameVarLoc, jmpi, ledo, rmtw, helply]; gfType: Type _ Frames.CreateIndirectGlobalFrameType[NEW[Frames.IndirectGlobalFrameTypeData_[CCTypes.GetIndirectType[globalVars.type]]], rmtw.cc]; gfInfo: GlobalFrameTypeInfo _ NEW[GlobalFrameTypeInfoBody_[ rmtw: rmtw, jmpi: jmpi, rootBTH: rootBTH, globalFrameVarLoc: globalFrameVarLoc, globalVars: globalVars, gfType: gfType]]; RETURN[NEW[FrameComponentInfoBody_[NIL, gfType, gfInfo]]]; END; CreateGlobalVarsInfoFromBTH: PROC[rootBTH: BTH, globalFrameVarLoc: MOF.VarLoc, jmpi: MOF.JointMobParsedInfo, ledo: REF LSA.LoadedModuleInfo, rmtw: RemoteMimosaTargetWorld, helply: BOOL] RETURNS[FrameComponentInfo] = { bthInfo: BthInfo _ GetBthInfo[rootBTH, rmtw]; IF bthInfo.nestedBlock = NIL THEN BEGIN btr: BTR _ MA.FetchBTR[rootBTH]; analyzedCTX: AnalyzedCTX _ AnalyzeCTX[btr.localCtx, NIL, TRUE, FALSE, FALSE, FALSE, FALSE, helply, TRUE, rmtw, CirioTypes.BitsToBa[globalFrameVarLoc.bitSize], jmpi].ctxInfo; bthInfo.nestedBlock _ NEW[FrameComponentInfoBody_[ analyzedCTX: analyzedCTX, type: analyzedCTX.recordType, typeInfo: NIL]]; END; RETURN[bthInfo.nestedBlock]}; FinalCreateIndirectGlobalFrameNode: PROC[gfTypeInfo: GlobalFrameTypeInfo, moduleMem: Mem] RETURNS[gf, gvs: Node] = { descriptor: CirioTypes.Node; rmtw: RemoteMimosaTargetWorld _ gfTypeInfo.rmtw; indirectGvsType: Type _ CCTypes.GetIndirectType[gfTypeInfo.globalVars.type]; gvMem: Mem _ SelectVarLoc[rmtw.nub, moduleMem, gfTypeInfo.globalFrameVarLoc]; data: REF Frames.IndirectGlobalFrameData; gvs _ CCTypes.CreateIndirectNode[indirectGvsType, gvMem, rmtw.cc]; <> IF CCTypes.GetRopeType[rmtw.cc]=NIL THEN { ut: CirioTypes.Type _ CedarOtherPureTypes.CreateUnknownType[rmtw.cc, "unknown type involved in final indirect global frame node"]; descriptor _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[ut, "final indirect global frame node", rmtw.cc];} ELSE descriptor _ CedarOtherPureTypes.CreateRopeNode[NIL, rmtw.cc]; data _ NEW[Frames.IndirectGlobalFrameData_[ descriptor: descriptor, globalVars: gvs]]; gf _ Frames.CreateIndirectGlobalFrameNode[data, gfTypeInfo.gfType, rmtw.cc]; RETURN}; CreateNestedBlockRecordFromBTH: PROC[bth: BTH, jmpi: MOF.JointMobParsedInfo, rmtw: RemoteMimosaTargetWorld] RETURNS[FrameComponentInfo] = BEGIN bthInfo: BthInfo _ GetBthInfo[bth, rmtw]; IF bthInfo.nestedBlock = NIL THEN BEGIN btr: BTR _ MA.FetchBTR[bth]; bthInfo.nestedBlock _ AnalyzeCTXAsBlockRecord[btr.localCtx, bth, jmpi, rmtw]; END; RETURN[bthInfo.nestedBlock]; END; AnalyzeCTXAsBlockRecord: PROC[ctxh: CTXH, bth: BTH, jmpi: MOF.JointMobParsedInfo, rmtw: RemoteMimosaTargetWorld] RETURNS[FrameComponentInfo] = { analyzedCTX: AnalyzedCTX _ AnalyzeCTX[ctxh, NIL, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, rmtw, unspecdBA, jmpi, bth].ctxInfo; RETURN[NEW[FrameComponentInfoBody_[ analyzedCTX: analyzedCTX, type: analyzedCTX.recordType, typeInfo: NIL]]] }; EqualRemoteByteAddress: PROC[a, b: RemoteAddress] RETURNS[--equalAndValid-- BOOLEAN] = BEGIN byteAddra: CARD _ a.byteAddress+a.bitOffset/8; byteAddrb: CARD _ b.byteAddress+b.bitOffset/8; RETURN[a.valid AND b.valid AND byteAddra=byteAddrb]; END; AddBitOffsetToRemoteAddress: PROC[addr: RemoteAddress, bitOffset: INT] RETURNS[RemoteAddress] = { bytes: INT _ bitOffset/8; bits: INT _ bitOffset MOD 8; RETURN[[addr.h, addr.byteAddress+bytes, addr.bitOffset+bits, addr.nil, addr.valid]]}; AddByteOffsetToRemoteAddress: PROC[addr: RemoteAddress, byteOffset: INT] RETURNS[RemoteAddress] = {RETURN[[addr.h, addr.byteAddress+byteOffset, addr.bitOffset, addr.nil, addr.valid]]}; StudyRopes: PUBLIC PROC [rmtw: RemoteMimosaTargetWorld] ~ { cc: CC ~ rmtw.cc; moduleStemName: ROPE ~ "CirioRopeHelper"; hJmpi: MOF.JointMobParsedInfo; hBth: BTH; hBtr: BTR; helperCtxh, stdCtxh: CTXH _ NIL; hac: AnalyzedCTX; ropeType: Type; rmtw.ropeStudyTime _ rmtw.unknownSymbolFlushTime; rmtw.atomRecSeh _ NIL; rmtw.atomRecRT _ NIL; { ENABLE CCE => { SystemInterface.ShowReport[IO.PutFR["StudyRopeType => CCE[, %g].\n", [rope[msg]]], $normal]; CONTINUE}; ledo: REF LoadStateAccess.LoadedModuleInfo _ LoadStateAccess.GetLoadedModuleInfoFromStemName[rmtw.lsh, moduleStemName, 0, rmtw.cedarModules]; lmi: REF NewRMTW.LoadedModuleInfo _ NewRMTW.GetLoadedModuleInfo[rmtw.cedarModules, ledo]; IF lmi#NIL AND lmi.jmpi#NIL THEN { hJmpi _ lmi.jmpi; hBth _ MA.GetRootBTH[lmi.mob]; hBtr _ MA.FetchBTR[hBth]; helperCtxh _ hBtr.localCtx; stdCtxh _ MA.MakeStdCtxh[lmi.mob]}; }; IF helperCtxh=NIL THEN { SystemInterface.ShowReport["Unable to get global frame of module CirioRopeHelper; standard types (ROPE, ATOM, BOOL, CHAR) won't be recognized as such.\n", $urgent]; RETURN}; [rmtw.atomRecSeh] _ FindHelpingSehs[helperCtxh, rmtw]; hac _ AnalyzeCTX[helperCtxh, NIL, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, rmtw, zeroBA, hJmpi, hBth].ctxInfo; ropeType _ FindType[hac, "aRope", "ROPE"]; IF ropeType # NIL THEN CCTypes.SetRopeType[cc, ropeType]; [] _ AnalyzeCTX[stdCtxh, NIL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, rmtw, zeroBA, NIL, NIL]; RETURN}; FindType: PROC[ctxInfo: AnalyzedCTX, varName, typeName: ROPE] RETURNS[Type] = { moduleName: ROPE ~ "CirioRopeHelper"; IF ctxInfo = NIL THEN RETURN[NIL]; FOR I: CARDINAL IN [0..ctxInfo.nFields) DO IF NOT Rope.Equal[ctxInfo.fields[I].name, varName] THEN LOOP; IF NOT ctxInfo.fields[I].analysisValid THEN { SystemInterface.ShowReport[IO.PutFR["Can't analyze type of global variable %g of %g; %gs will not be recognized as such.\n", [rope[varName]], [rope[moduleName]], [rope[typeName]] ], $urgent]; RETURN[NIL]}; RETURN [ctxInfo.fields[I].fieldDirectType]; ENDLOOP; SystemInterface.ShowReport[IO.PutFR["Unable to find global variable %g of %g; %gs will not be recognized as such.\n", [rope[varName]], [rope[moduleName]], [rope[typeName]] ], $urgent]; RETURN[NIL]}; GetModule: PROC [moduleScope: CirioTypes.ModuleScope, name: ROPE, nToSkip: INT] RETURNS [node: CirioTypes.Node] ~ { rmtw: RemoteMimosaTargetWorld ~ NARROW[moduleScope.data]; node _ BuildIndirectGlobalFrameNodeForNamedModule[rmtw, name, nToSkip].gvs; IF node=NIL THEN CCE[operation, IO.PutFR["Can't get loaded module info for %g skip %g", [rope[name]], [integer[nToSkip]] ]]; RETURN}; DontGetInterface: PROC [moduleScope: ModuleScope, name: ROPE] RETURNS [Node] ~ { CCE[unimplemented, "access to interface records"]}; BuildIndirectGlobalFrameNodeForNamedModule: PROC[rmtw: RemoteMimosaTargetWorld, moduleStemName: ROPE, nToSkip: INT] RETURNS[gf, gvs: Node] = { ledo: REF LoadStateAccess.LoadedModuleInfo _ LoadStateAccess.GetLoadedModuleInfoFromStemName[rmtw.lsh, moduleStemName, nToSkip, rmtw.cedarModules]; lmi: REF NewRMTW.LoadedModuleInfo _ NewRMTW.GetLoadedModuleInfo[rmtw.cedarModules, ledo]; IF lmi = NIL OR lmi.jmpi = NIL THEN RETURN[NIL, NIL]; {jmpi: MOF.JointMobParsedInfo _ lmi.jmpi; rootBTH: BTH _ MOF.GetRootBTH[jmpi]; info: FrameComponentInfo _ CreateIndirectGlobalFrameInfoFromRootBTH[rootBTH, jmpi, lmi.loadedModule, rmtw, FALSE]; targetType: Type _ info.type; gfTypeInfo: GlobalFrameTypeInfo _ NARROW[info.typeInfo]; moduleMem: Mem _ MakeDualMem[ nub: rmtw.nub, fp: invalidPtr, sp: invalidPtr, fep: [unspecdBA, unspecdBA], text: ledo.lsi[text], data: ledo.lsi[data], bss: ledo.lsi[bss], simple: [unspecdBA, unspecdBA] ]; RETURN FinalCreateIndirectGlobalFrameNode[gfTypeInfo, moduleMem]}}; GetAnalyzedCTXForGlobalVarsForNamedModule: PROC[rmtw: RemoteMimosaTargetWorld, moduleStemName: ROPE, helply: BOOL] RETURNS[ctxInfo: AnalyzedCTX, stdCtxh: MA.CTXH] = { ledo: REF LoadStateAccess.LoadedModuleInfo _ LoadStateAccess.GetLoadedModuleInfoFromStemName[rmtw.lsh, moduleStemName, 0, rmtw.cedarModules]; lmi: REF NewRMTW.LoadedModuleInfo _ NewRMTW.GetLoadedModuleInfo[rmtw.cedarModules, ledo]; IF lmi = NIL OR lmi.jmpi = NIL THEN RETURN[NIL, NIL]; {jmpi: MOF.JointMobParsedInfo _ lmi.jmpi; rootBTH: BTH _ MOF.GetRootBTH[jmpi]; info: FrameComponentInfo _ CreateIndirectGlobalFrameInfoFromRootBTH[rootBTH, jmpi, lmi.loadedModule, rmtw, helply]; targetType: Type _ info.type; gfTypeInfo: GlobalFrameTypeInfo _ NARROW[info.typeInfo]; globalVars: FrameComponentInfo _ gfTypeInfo.globalVars; ctxInfo _ globalVars.analyzedCTX; stdCtxh _ MA.MakeStdCtxh[lmi.mob]; RETURN}}; MemGetLsi: PROC [mem: Mem, segName: ROPE, segNum: INT] RETURNS [LSA.LoadedSegmentInfo] ~ { bs: BitStretch _ mem.MemReadSegReg[segName, segNum]; IF bs.start.bits#0 OR bs.size.bits#0 THEN CirioMemory.Error["non-AU-aliged segment register can't be cast as a LSA.LoadedSegmentInfo"]; RETURN[[base: bs.start.BaToPtr, size: bs.size.BaToPtr]]}; LsiGetBitStr: PROC [lsi: LSA.LoadedSegmentInfo] RETURNS [BitStretch] ~ { bs: BitStretch _ CirioMemory.unspecdBS; bs.start _ CirioMemory.PtrToBa[lsi.base]; bs.size _ CirioMemory.PtrToBa[lsi.size]; --bs.start _ CirioMemory.AusToBa[lsi.base]; --bs.size _ CirioMemory.AusToBa[lsi.size]; RETURN[bs]; }; END. 1à RMTWFrames.mesa Copyright Ó 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Sturgis, April 20, 1990 3:07 pm PDT Last changed by Theimer on November 29, 1989 11:41:00 am PST Last tweaked by Mike Spreitzer on April 24, 1992 4:00 pm PDT Coolidge, July 16, 1990 2:21 pm PDT Philip James, February 24, 1992 10:22 am PST Laurie Horton, February 24, 1992 3:30 pm PST Baran, October 21, 1991 2:14 pm PDT Katsuyuki Komatsu December 23, 1992 4:25 pm PST TargetWorlds FOR THE MOMENT, we adapt code from GetNodeForFrame and CreateIndirectFrameNodeFromMay4ExpProcedureFrameInfo fes _ [ CirioTypes.PtrToBa[rawFrameInfo.framePointer] .BaAdd[CirioTypes.BitsToBa[f.bitOffset]], CirioTypes.BitsToBa[f.bitSize] ]; fes _ [ CirioTypes.PtrToBa[rawFrameInfo.framePointer] .BaAdd[CirioTypes.BitsToBa[f2.bitOffset]], CirioTypes.BitsToBa[f2.bitSize] ]; Frames The following is very similar to an AnalyzedSEH, but because there is no disitinction between type time and node schema time for frame components, we include the node schema itself, rather than a procedure for constructing it. Ugh: direct when it's a record type, indirect when it's a frame type! (easy to clean up?) GlobalFrameTypeInfo when it's a global frame ComponentInfo; ProcFrameTypeInfo when it's a proc frame ComponentInfo; NIL when it's a nested block ComponentInfo. Mem Create a Simple Mem. Create a Mem that is both Frame and Simple. current assumed mechanism is that if bitSize <= 32 then the field is right-justified within the named register, otherwise the named register contains a pointer to the field. BTH Info We get to use the default Equal and Hash procedures, since ref equality is sufficient. some previously unknown symbols may now be known, so forget everything we thought we knew. (Later we can be less draconian, when we have time to sort things out.) Basic Procedure Frame Info These are defined by the outermost BTH of the frame, otherwise identified as a callable bth. spOffset = 0 means that it is invalid We assume that bth is callable. following computation computes the args and results type info, filling in the appropriate fields in basicInfo. I assume that this is an attempt to indicate that there are no arguments or results. This seems to occur for manufactured procedures that contain a block covered by an enable clause. A Scope's frame extension is part of the statically enclosing block's frame extention (according to experiments by MJS June 8, 1991), and the offsets found in the .mob are from the start of the enclosing frame extension. RJB Sept. 5, 1991 - This is also the case for a Catch phrase procedure - difference -- is in where to find the stand-in for the the Static Link. For a Scope, there is -- one and only one argument; for a Catch, there are 5 arguments, with the second -- argument being the stand-in for the Static Link (hence the call above to -- MDA.GetCatchPhraseStrandedStaticLinkLoc[bth, jmdi]). the following computation determines the kind and type of the enclosing context and fills in basicInfo.enclosingContext with the appropriate FrameComponentInfo Procedure Frames we assume that the first bth is callable and that the other bths are children of their immediate predecessors. ISSUES: We make the nested block types indirect. We shouldn't , but that seeems to be what the Frame Implementation wants. We should change both. Same for argument and result records. Note: if the blockList.first has an empty CTX, then we do not construct a nested block type for it. This seems to occur if a block has an enable clause. At this writing (June 7, 1989), I do not understand all of this issue. Find the local context for a Scope BTH. A few examples suggest it will be the last child. There are two ways in which procedure frame nodes get constructed: directly from a FrameMem style mem and from a May4Exp.ProcedureFrameInfo. The latter requires construction of an appropriate FrameMem style mem. The two cases also produce some what different information, such as the descriptor. This procedure constructs the frame node from the May4Exp.ProcedureFrameInfo. In fact, it appears that it can also be a global frame node. I must rearrange the procedure structure so that that decision gets made before we get here. It expects a cFrameText. Note that this text could have been partially constructed at type time. Only that part which is explictely dependent on the pc need be constructed at node time. However, it turns out to be difficult (with my current data structures) to construct this text when the first encounter with the frame type occurs as an enclosing context. Therefor, I have chosen to take in the entire text here. CreateIndirectFrameNodeFromMay4ExpProcedureFrameInfo: PROC[frameInfo: May4Exp.ProcedureFrameInfo, cFrameText: ROPE, symbols: SymbolFinding.FoundSymbols, rmtw: RemoteMimosaTargetWorld] RETURNS[REF May4Exp.FrameNodeInfo] = BEGIN cc: CC _ rmtw.cc; pc: CARD _ frameInfo.relativePC; jmpi: MOF.JointMobParsedInfo _ symbols.jmpi; blockList: LIST OF BTH _ MOF.FindNearBTHAncestorsForPC[pc, jmpi]; rootBTH: BTH _ MOF.GetRootBTH[jmpi]; SELECT TRUE FROM (blockList.first = NIL) => BEGIN frameNode: Node _ CedarOtherPureTypes.CreateRopeNode[Rope.Cat["unreadable Cedar symbols for\N", cFrameText], cc]; RETURN[NEW[May4Exp.FrameNodeInfo _ [frameNode, $Cedar, GetBadCedarFrameDiagnosticInfo, NEW[BadCedarFrameInfo_["blockList.first was NIL"]]]]]; END; blockList.first = rootBTH => BEGIN -- the frame is the global frame (probably one of the special C procedures) frameTypeInfo: FrameComponentInfo _ CreateIndirectGlobalFrameInfoFromRootBTH[blockList.first, jmpi, rmtw]; ns: NodeSchema _ frameTypeInfo.nodeSchema; targetType: Type _ frameTypeInfo.type; gfTypeInfo: GlobalFrameTypeInfo _ NARROW[ns.nsData]; ugh, I should redesign the procedure structure so we can git this info directly rather than go through this circumlocation ending with NARROW[ns.nsData]; bssBase: RemoteAddress _ RemoteAddrFromCard[rmtw, frameInfo.dotOInfo.bssReloc]; gfa: RemoteAddress _ WITH gfTypeInfo.globalFrameVarLoc SELECT FROM vl: REF frame MOF.VarLocBody => AddBitOffsetToRemoteAddress[bssBase, -vl.bitOffset], (we ought to be able to confirm this compution, since there may also be a globalFrameLink var available ) ENDCASE => InvalidRemoteAddress; frameMem: FrameMem _ NEW[FrameMemBody_[ fp: gfa, sp: InvalidRemoteAddress, fe: InvalidRemoteAddress, gfp: InvalidRemoteAddress, rawBase: RemoteAddrFromCard[rmtw, 0] ]]; frameNode: Node _ FinalCreateIndirectGlobalFrameNode[gfTypeInfo, cFrameText, [frameMem]]; RETURN[NEW[May4Exp.FrameNodeInfo _ [frameNode, $Cedar, GetBadCedarFrameDiagnosticInfo, NEW[BadCedarFrameInfo_["the frame is the global frame"]]]]]; END; ENDCASE => BEGIN -- this is the normal case (a Mesa procedure) frameTypeInfo: FrameComponentInfo _ CreateProcedureFrameInfoFromBlockList[blockList, symbols, rmtw]; ns: NodeSchema _ frameTypeInfo.nodeSchema; targetType: Type _ frameTypeInfo.type; procFrameTypeInfo: ProcFrameTypeInfo _ NARROW[ns.nsData]; ugh, I should redesign the procedure structure so we can git this info directly rather than go through this circumlocation ending with NARROW[ns.nsData]; codeBase: RemoteAddress _ RemoteAddrFromCard[rmtw, frameInfo.dotOInfo.textReloc]; bssBase: RemoteAddress _ RemoteAddrFromCard[rmtw, frameInfo.dotOInfo.bssReloc]; framePointer: RemoteAddress _ RemoteAddrFromCard[rmtw, frameInfo.framePointer]; stackPointer: RemoteAddress _ RemoteAddrFromCard[rmtw, frameInfo.stackPointer]; frameExtension: RemoteAddress _ WITH procFrameTypeInfo.basicInfo.frameExtensionVarLoc SELECT FROM f: REF frame MOF.VarLocBody => RemoteAddrFromCard[rmtw, frameInfo.framePointer+f.bitOffset/8], ENDCASE => InvalidRemoteAddress; THIS SELECTION SHOULD BE DONE AT Type time. gfVarBFS: BitFieldSchema _ procFrameTypeInfo.basicInfo.globalLinkVarBFS; rawBase: RemoteAddress _ RemoteAddrFromCard[rmtw, 0]; frameMem: FrameMem _ NEW[FrameMemBody_[ fp: framePointer, sp: stackPointer, fe: frameExtension, gfp: InvalidRemoteAddress, rawBase: rawBase ]]; frameNode: Node; frameNodeInfo: ProcFrameNodeInfo; frameMem.gfp _ gfVarBFS.procs.followPointer[gfVarBFS, [frameMem]]; frameNode _ FinalBuildProcFrameNode[procFrameTypeInfo, cFrameText, [frameMem], rmtw]; frameNodeInfo _ NEW[ProcFrameNodeInfoBody_[ procFrameTypeInfo, frameMem, frameNode]]; RETURN[NEW[May4Exp.FrameNodeInfo _ [frameNode, $Cedar, GetCedarFrameDiagnosticInfo, frameNodeInfo]]]; END; END; Remark: Perhaps this procedure should be part of a frame. Or perhaps Cirio Main should introduce the general notion of diagnostic information associated with nodes and types? This procedure expects a Frame Mem that: (1) defines the text segment; (2) defines the segments where the Cedar global vars live; (3) defines the registers needed to find the locals, args, and results. This procedure copes with a Frame Mem that fails to (2) or (3), and with a missing static link, by passing a similarly broken Mem to the frame creation procs. This requires the block record node procs to cope with broken Mems. We make broken frames, instead of eliding those frames, because the static scope nesting structure is determined at type time, and I thought it better (only in terms of error message potential) not to twist that structure. enclosingFP _ enclosingFe.BaAdd[CirioTypes.BitsToBa[-vl.bitOffset]]; enclosingSP _ IF spOffset=0 THEN CirioTypes.PtrToBa[invalidPtr] ELSE enclosingFP.BaAdd[CirioTypes.AusToBa[spOffset]]}; callerBasicInfo: LSA.BasicPCInfo _ LSA.GetBasicPCInfo[rmtw.lsh, callerPC]; Global Frames There is a serious question about what sort of Mem argument is expected by FrameComponentInfo.nodeSchema. [MJS, May 16, 1991: Looks like it depends on the kind of FrameComponentInfo we're talking about: Global: no Mem is ever given, Global vars: certainly a Simple mem for the C variable containing the Cedar global variables; this Mem may also need to know the text base, ...] Hmm: I think that this gets done too many times, it is not cached. do I really need this extra level of abstraction? This procedure expects a Frame Mem that defines the text segment and the segment where the Cedar global vars live. Enclosing Contexts First, a comment. Perhaps I should have designed Cirio Frames so that the pointer to an enclosing context looked some what like a pointer. That is, if one had an indirect on a frame, and wanted an indirect on the frame of the enclosing context, one would require three steps: select the pointer to the enclosing frame, load the pointer, extract the indirect to the enclosing context. Some where during that sequence one would have the opportunity to discover the type of the enclosing context (procedure frame, global frame), and construct an appropriate Mem. However, that is not how they were done, so we have to somehow fake it. An enclosing context will be a node that expects Mems designed for the nested procedure frame, and, among other things, constructs an appropriate Mem for the enclosing context. Thus it knows the type structure of the embedded procedure (so that it can find the global frame pointer and staticLink) as well as knows whether the enclosing context is a procedure frame or a global frame (so that it will know whether to use the global frame pointer or the staticLink pointer, and what kind of Mem to construct), and finally knowns the type structure of the enclosing context. We have two kinds of enclosing context node schema: one in which the enclosing context is a procedure frame and one in which the enclosing context is a global frame. Both of these varieties take the FrameMem of the embedded procedure and have type access to the embedded procedure. MJS, May 21, 1991: All the code in this section disappeared. Nested Block Records These are defined by their BTH Block Record Types Block Record Types are used to make the argument record, result record, nested blocks, and global frame look like Cedar Records. The fields of these records are treated individualy. It might be a local variable of the C-procedure, or it might be embedded in one of the local variables of the C-procedure. In addition, we have to worry about whether these C variables are LVars or RVars. Stuff Rope Support We have to locate enough info to mark the rope SEH We also need to get our hands on an allocator proc So we look for a helper module in the target world Note: this procedure could be used to implement calls to module procedures, but it requires symbols in the dotO. I think I can do better. following code adapted from GetNodeForCedarFrame early part of this proc follows BuildIndirectGlobalFrameNodeForNamedModule, perhaps some appropriate reorganization is appropriate. following code adapted from GetNodeForCedarFrame following is new Ê'Ì•NewlineDelimiter ™codešœ™K™HKšœ#™#K™˜jKšœ~œ˜…—šœœ œ˜$Kšœ œL˜^—šœœ œ˜%Kšœ+˜+Kšœ-˜-—Kšœœ˜—Kšœ œœœ.˜aKšœ˜Kšœ œœŸq˜Œ—K˜š  œœœ"œ œ˜`šœœ œ˜KšœPœœ˜_Kšœœœ'œ˜:Kšœœ˜Kšœœ˜—Kšœ˜—K˜—šœ™˜K™V—š œœœœ˜7Kšœœœ)˜4—K˜š  œœœœ ˜JKš˜Kšœœ*˜@šœœ˜Kš˜Kš œœœœœœ˜HKš œœ+œœŸ˜ZKšœ˜—šœJ˜PK™£Kš˜Kšœ4˜4Kšœœ˜Kšœœ˜#Kšœœ˜"Kšœ˜—Kšœ˜ Kšœ˜——K˜™K™Kšœ#œ6™\K˜Kšœœœ˜>šœœœ˜*Kšœœ˜"Kšœœ˜Kšœœœœ˜ Kšœ˜Kšœ˜KšœœÐci5˜NKšœœ˜!Kšœœ¡P˜eKšœœ˜Kšœœ¡>˜SKšœœ˜šœ œ¡>˜NKšœ%™%—Kšœ$˜$K˜—K˜š ,œœ$œœ˜cKš˜Kšœœ)œœ)˜bKšœ˜—˜Kšœ™—š  œœœœ:œ˜“Kšœ)˜)Kšœœ˜(šœ#œ˜-Kšœ˜Kšœœœ˜Kšœ$œ˜DKšœœ)˜KKšœœ˜)Kšœ˜K˜Kšœn™nšœœ˜šœœ œ˜&Kšœ œœ˜)šœœ˜šœœœ ˜šœœ˜šœ œ œ˜-šœ˜Kšœ9˜9—šœ˜Kšœ;˜;——šœœœ˜'K™·šœ˜Kšœœ˜-—šœ˜Kšœœ˜-——Kšœœ˜——Kšœœ˜——Kšœœ ˜—K˜Kšœ˜Kšœœ&˜Gšœ ˜ Kšœ3˜6—Kšœœ˜:K˜K˜šœ˜Kšœœ.˜S—šœ˜Kšœœœ$˜\Kšœœœœ3˜pšœ˜K˜——KšœÜ™ÜKšœÿ™ÿš œœœœ˜JKšœ˜KšœœœK˜uKšœ˜—K˜Kšœœ˜:Kšœœ/˜OKšœœ˜0K™šœŸ™ŸKšœ˜Kšœ œ˜!Kšœœœœ ˜?šœœœ˜!Kšœ^˜^—šœœœœ˜,Kšœd˜d—šœœœ$œ˜2Kšœ~œ˜…Kšœ˜—šœœ˜Kšœb˜bKšœ˜—Kšœ˜—K˜Kšœ,˜,Kšœ˜—Kšœ"˜(Kšœ˜—K˜š   œœœ œœ ˜—Kšœœ ˜——Kšœœ ˜—Kšœ˜—Kšœ˜——K™K™™K˜Kšœœœ˜4šœœœ˜%Kšœ"˜"Kšœ˜Kšœœ˜0šœœ œœ˜,Kšœœ˜,——K˜Kšœ œœ ˜ šœ œœ˜Kšœ˜Kšœœ˜"Kšœ ˜ Kšœ0˜0Kšœ*˜*Kšœ˜—K˜š 'œœœœ˜YKš˜KšœB˜BKšœ˜K˜K™nK™K™º—š %œœ œœœœ:œ˜¥K˜;šœ9˜9K™Kšœ*œ´™á—šœ"œœ˜.Kšœ œœœ˜.Kšœ<˜<šœ(˜(Kšœ:˜:—Kšœ œœ˜-Kšœ œ˜'Kšœœ!˜CKšœœ œ(˜]šœœ˜K˜—š œœœœœœ˜:šœ˜KšœE˜E—K˜Kšœ˜—K˜KšœF˜FKšœÏtœ˜GKšœ¢œ˜Mš œ œœœ˜"Kšœ ¢%œ$¢˜WKšœ˜—K˜Kšœ%˜%KšœM˜MKšœ(˜(K˜Kšœ!œœ#˜eKšœ˜—Kšœ"˜(—K˜š  œœ œœœœœœœ˜BK™ZKšœ œœ˜-Kšœœ˜ Kšœœ˜ Kšœ œœœ˜Kšœ œœ˜Kšœœœœ ˜0Kšœœœ˜4šœœ˜Kšœ œ˜šœœ˜'Kšœ˜Kšœ˜—šœ˜Kšœ˜Kšœ œ˜—Kšœ˜—Kš œ œœœœ˜>Kšœ˜—K˜Kš œœœ œ œ˜DK˜š  œœ œœœœ˜MKšœœ˜Kšœ œ˜š œœœœœœ˜:K˜$K˜Kšœ˜—Kšœ˜%—K˜K™©K™Kšœé™éK™Kšœ¢™¢K˜š 4œœ~œœ™ÜKš™Kšœœ ™Kšœœ™ Kšœœ"™,Kš œ œœœœ$™AKšœ œœ™$K™K™šœœ™šœœ™Kš™Kšœq™qKšœœMœ3™Kšœ™—™KšœŸK™QKšœj™jKšœ*™*Kšœ&™&šœ"œ ™4Kšœ™™™—KšœO™Ošœœœ™BšœœœB™TK™i—Kšœ™ —šœ œœ™'Kšœ™Kšœ™Kšœ™Kšœ™Kšœ(™(—KšœY™YKšœœMœ9™“Kšœ™—K™K™šœ™ KšœŸ-™3Kšœd™dKšœ*™*Kšœ&™&šœ'œ ™9Kšœ™™™—KšœQ™QKšœO™OKšœO™OKšœO™Ošœ œ2œ™aKšœœœM™^šœ™ K™+——KšœH™HKšœ5™5šœ œœ™'Kšœ™Kšœ™Kšœ™Kšœ™Kšœ™—Kšœ™K™!KšœB™BKšœU™Ušœœ™+Kšœ)™)—Kšœœ,™6Kšœ.™.—Kšœ™—K™K™K™K™Kšœ™—K˜Kšœœœ˜4šœœœ˜%Kšœ%˜%Kšœ˜Kšœ˜—K˜˜K™¯—š œœœœœœœ˜]Kš œ œœœœ˜ Kšœœ ˜-šœœœ˜Kš œœœœœ˜ Kšœ œœœ˜7Kšœ ˜ —K˜KšœH˜HKšœ ˜—K˜Kšœœœœ˜-K˜š œœœœœœœ˜`Kšœœœ ˜1Kšœœ˜—K˜Kšœœœ˜4šœœœ˜%Kšœ!˜!Kšœ œ˜Kšœ ˜ Kšœ˜—˜™(K™K™:K™G—K™Ã—š œœ/œ+œ ˜ŒKšœ<˜