<<>> <> <> <> <> <> <> <> <> <> DIRECTORY Basics USING[BITXOR, LongNumber], CCTypes USING[CCError, CCErrorCase], CirioTypes USING[bitsPerPtr, zeroBA], Commander USING[CommandProc, Register], CommandTool USING[ArgumentVector, Parse], Convert USING[CardFromRope], IO USING[card, int, Put, PutF, PutFR, rope, STREAM], MobAccess USING[BlockDesc, BodySE, BTH, BTR, BTRExtension, ConstVal, CreateMobCookie, CTXH, CTXR, FetchBTR, FetchCTXR, FetchSER, FieldDesc, GenCallableBodies, GetCodedBTIFromBTH, GetCodedSeiFromSEH, GetParentOfBTH, GetRootBTH, IsLost, MakeSEHFromCodedSei, MobCookie, SEH, SER, TypeDesc, TypeInfoConsSE], MobObjectAccessPrivate, MobObjectFiles USING[VarLoc, VarLocBody], ObjectFiles USING[BracketNest, BracketPair, CreateParsed, FindGlobalFrameVar, FunHandle, FunInfo, GenFunBracketPairs, GenFuns, GenSubBracketPairs, GenSymbolStabs, GetBracketNestForPC, GetFunBrackets, GetFunHandleFromNest, GetFunInfo, GetPCRange, GetSPOffset, IndirectVarLoc, Module, ModuleFromParsedAndPC, NameAndNumber, Parsed, ParseNameRope, PCRange, Stab, StabType, VarLoc, VarLocBody, VarLocCase, VarLocFromStab], PBasics USING[bitsPerByte], PFS USING [PathFromRope], PFSNames USING [PATH], RefTab USING[Create, Fetch, Insert, Key, Ref], Rope USING[Concat, Equal, Length, ROPE], SystemInterface USING[CirioFile, CloseFileSet, CreateFileSet, FileSet, GetCirioFile, ShowReport]; <<>> MobObjectFilesImpl: CEDAR PROGRAM IMPORTS Basics, CCTypes, Commander, CommandTool, Convert, IO, MobAccess, ObjectFiles, PFS, RefTab, Rope, SystemInterface EXPORTS MobObjectFiles = BEGIN OPEN ObjF:ObjectFiles, MA:MobAccess, MOF:MobObjectFiles, MobObjectAccessPrivate; <> <<>> <<1) Given a pc, delivers the bth of the block most tightly enclosing the given pc. (Actually, the most tightly enclosing recognized block.) In addition, ensures that an association between bracket pairs and bths is constructed for the result bth and for all enclosing bths. (In so far as the association can be constructed from the dotO and mob.)>> <<>> <<2) Given a bth and the seh for a variable occurring in the context of the bth, returns the field offset information for that variable. (This works only for blocks for which the bracket-pair-bth association has been constructed.) [Not yet installed]>> <<>> <<>> BTH: TYPE = MA.BTH; BTR: TYPE = MA.BTR; CTXH: TYPE = MA.CTXH; CTXR: TYPE = MA.CTXR; SEH: TYPE = MA.SEH; SER: TYPE = MA.SER; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError; JointMobParsedInfo: TYPE = REF JointMobParsedInfoBody; JointMobParsedInfoBody: PUBLIC TYPE = MobObjectAccessPrivate.JointMobParsedInfoBody; CreateJointMobParsedInfo: PUBLIC PROC[mob: MA.MobCookie, whole: ObjF.Parsed, module: ObjF.Module] RETURNS[JointMobParsedInfo] = BEGIN jmpi: JointMobParsedInfo _ NEW[JointMobParsedInfoBody_[ mob, whole, module, CreateBTHashTable[], CreateBTHashTable[], CreateVarHashTable[], CreateBpHashTable[] <> <> <> ]]; <> AnalyzeCallableBodySet[jmpi]; RETURN[jmpi]; END; <> GetSPOffset: PUBLIC PROC[callableBTH: BTH, jmpi: JointMobParsedInfo] RETURNS[INT] = { entryRelativePC: CARD _ GetEntryPCofCallableBTH[callableBTH, jmpi]; spOffset: INT _ ObjF.GetSPOffset[jmpi.module, [[0, ""], entryRelativePC]]; RETURN[spOffset]; }; <<>> <> <> <> GetVarLoc: PUBLIC PROC[seh: SEH, bth: BTH, jmpi: JointMobParsedInfo] RETURNS[MOF.VarLoc] = BEGIN IF seh = NIL THEN RETURN[NullVarLoc["GetVarLoc[NIL]"]] ELSE BEGIN varKey: RefTab.Key _ CreateVarKeyFromSEH[seh]; vi: VarInfo _ NARROW[RefTab.Fetch[jmpi.vars.table, varKey].val]; IF vi = NIL THEN -- perhaps the appropriate analysis has not been done BEGIN ancestors: LIST OF BTH _ GetNearInclusiveAncestorBTHList[bth, jmpi]; cbi: CallableBodyInfo _ GetCBIForBth[jmpi, ancestors.first]; IF cbi # NIL THEN AnalyzeOneCallableBody[cbi]; vi _ NARROW[RefTab.Fetch[jmpi.vars.table, varKey].val]; END; IF vi # NIL THEN RETURN[GetVarLocFromVarInfo[vi]] ELSE RETURN[NullVarLoc["GetVarLoc: no vi"]]; END; END; FindNearBTHAncestorsForPC: PUBLIC PROC[pc: CARD, jmpi: JointMobParsedInfo] RETURNS[LIST OF BTH] = BEGIN nest: ObjF.BracketNest _ ObjF.GetBracketNestForPC[jmpi.module, [[0, ""], pc]]; fun: ObjF.FunHandle _ ObjF.GetFunHandleFromNest[nest]; GetAnalyzedCBIForFun: PROC RETURNS[CallableBodyInfo] = BEGIN result: CallableBodyInfo _ GetCBIForFun[jmpi, fun]; IF result # NIL AND result.bi = NIL THEN AnalyzeOneCallableBody[result]; RETURN[result]; END; cbi: CallableBodyInfo _ IF fun = NIL THEN NIL ELSE GetAnalyzedCBIForFun[]; FindTightestRecognizedBP: PROC[subNest: ObjF.BracketNest] RETURNS[BPInfo] = BEGIN tentative: BPInfo _ IF subNest.rest = NIL THEN NIL ELSE FindTightestRecognizedBP[subNest.rest]; IF tentative # NIL THEN RETURN[tentative]; tentative _ NARROW[RefTab.Fetch[jmpi.bracketPairs.table, subNest.first].val]; IF tentative # NIL AND tentative.associatedBody # NIL THEN RETURN[tentative] ELSE RETURN[NIL]; END; tightestRecognizedBP: BPInfo _ FindTightestRecognizedBP[nest]; <<(maybe I should do FindTightestRecognizedBP[nest.rest.rest??)>> <<>> <<>> tightestRecognizedBth: MA.BTH _ IF tightestRecognizedBP # NIL THEN tightestRecognizedBP.associatedBody.bth ELSE IF cbi#NIL THEN cbi.bth ELSE NIL; IF tightestRecognizedBth=NIL THEN RETURN [NIL]; RETURN[GetNearInclusiveAncestorBTHList[tightestRecognizedBth, jmpi]]; END; FindNearBTHAncestorsForBlock: PUBLIC PROC[block: BTH, jmpi: JointMobParsedInfo] RETURNS[LIST OF BTH] = BEGIN parent: BTH _ MA.GetParentOfBTH[block]; RETURN[GetNearInclusiveAncestorBTHList[parent, jmpi]]; END; GetRootBTH: PUBLIC PROC[jmpi: JointMobParsedInfo] RETURNS[BTH] = {RETURN[MA.GetRootBTH[jmpi.mob]]}; GetEntryPCofCallableBTH: PUBLIC PROC[callableBTH: BTH, jmpi: JointMobParsedInfo] RETURNS[CARD] = BEGIN cbi: CallableBodyInfo _ GetCBIForBth[jmpi, callableBTH]; fun: ObjF.FunHandle _ IF cbi = NIL THEN NIL ELSE cbi.fun; funInfo: ObjF.FunInfo _ IF fun = NIL THEN CCE[cirioError] ELSE ObjF.GetFunInfo[fun]; IF funInfo.stab.stabType # Fun THEN CCE[cirioError]; RETURN[funInfo.stab.value]; END; GetNearInclusiveAncestorBTHList: PROC[tightestBth: BTH, jmpi: JointMobParsedInfo] RETURNS[LIST OF BTH] = BEGIN rootBTH: BTH _ MA.GetRootBTH[jmpi.mob]; list: LIST OF BTH _ LIST[tightestBth]; DO IF list.first = rootBTH THEN RETURN[list]; IF RefTab.Fetch[jmpi.callableBodies.table, CreateBTKeyFromBTH[list.first]].val # NIL THEN RETURN[list]; list _ CONS[MA.GetParentOfBTH[list.first], list]; ENDLOOP; END; <> <<>> GetLocalFrameExtensionVar: PUBLIC PROC[bth: BTH, jmpi: JointMobParsedInfo] RETURNS[SEH] = BEGIN cbi: CallableBodyInfo _ GetCBIForBth[jmpi, bth]; IF cbi = NIL THEN RETURN[NIL]; AnalyzeOneCallableBody[cbi]; IF cbi.frameExtension = NIL THEN RETURN[NIL]; RETURN[cbi.frameExtension.seh]; END; GetGlobalLinkVar: PUBLIC PROC[bth: BTH, jmpi: JointMobParsedInfo] RETURNS[SEH] = BEGIN cbi: CallableBodyInfo _ GetCBIForBth[jmpi, bth]; IF cbi = NIL THEN RETURN[NIL]; AnalyzeOneCallableBody[cbi]; IF cbi.globalLink = NIL THEN RETURN[NIL]; RETURN[cbi.globalLink.seh]; END; <<>> GetStaticLinkVar: PUBLIC PROC[bth: BTH, jmpi: JointMobParsedInfo] RETURNS[SEH] = BEGIN cbi: CallableBodyInfo _ GetCBIForBth[jmpi, bth]; IF cbi = NIL THEN RETURN[NIL]; AnalyzeOneCallableBody[cbi]; IF cbi.staticLink = NIL THEN RETURN[NIL]; RETURN[cbi.staticLink.seh]; END; GetStrandedStaticLinkLoc: PUBLIC PROC[bth: BTH, jmpi: JointMobParsedInfo] RETURNS[MOF.VarLoc] ~ { cbi: CallableBodyInfo _ GetCBIForBth[jmpi, bth]; IF cbi = NIL THEN RETURN[NIL]; AnalyzeOneCallableBody[cbi]; IF cbi.staticLink=NIL AND cbi.topStabs#NIL AND cbi.topStabs.rest=NIL AND cbi.bi.btr.class=Scope THEN RETURN ObjF.VarLocFromStab[cbi.topStabs.first]; <> RETURN[NIL]}; GetCatchPhraseStrandedStaticLinkLoc: PUBLIC PROC[bth: BTH, jmpi: JointMobParsedInfo] RETURNS[MOF.VarLoc] ~ { cbi: CallableBodyInfo _ GetCBIForBth[jmpi, bth]; IF cbi = NIL THEN RETURN[NIL]; AnalyzeOneCallableBody[cbi]; IF cbi.staticLink=NIL AND cbi.topStabs#NIL AND cbi.bi.btr.class=Catch THEN BEGIN count: CARD _ 0; last: ObjF.Stab _ NIL; prev: ObjF.Stab; FOR x: LIST OF ObjF.Stab _ cbi.topStabs, x.rest WHILE x#NIL DO count _ count + 1; prev _ last; last _ x.first; ENDLOOP; IF count=5 THEN RETURN ObjF.VarLocFromStab[prev]; END; <> RETURN[NIL]}; GetGlobalFrameVarLoc: PUBLIC PROC[jmpi: JointMobParsedInfo] RETURNS[MOF.VarLoc] = {RETURN [ObjF.FindGlobalFrameVar[jmpi.module]]}; NullVarLoc: PROC [why: Rope.ROPE _] RETURNS[MOF.VarLoc] = {RETURN[NEW[ObjF.VarLocBody _ [0, unknown[why]]]]}; <> <<>> <> <> <> <<>> <> <<>> <> <<>> <> <<>> <> <> <> <> <> <> <> <> <<>> BodyInfo: TYPE = REF BodyInfoBody; BodyInfoBody: TYPE = RECORD[ bth: BTH, codedBti: CARD, btr: BTR, callable: BOOLEAN, jmpi: JointMobParsedInfo, parent: REF ANY, -- either BodyInfo or CallableBodyInfo. (It will be CallableBodyInfo exactly when this bti is callable, in which case it will be the CallableBodyInfo for this bti.) callableAncestor: CallableBodyInfo, -- will be for this bti when this bti is callable. associatedBps: LIST OF BPInfo, -- will be used for printing, bad situation if none or if more than one vars: LIST OF VarInfo, subBodies: LIST OF BodyInfo, invalid: BOOLEAN _ FALSE, bodyOccurredTwice: BOOLEAN _ FALSE]; VarInfo: TYPE = REF VarInfoBody; VarInfoBody: TYPE = RECORD[ seh: SEH, codedSei: CARD, idBody: REF id MA.BodySE, name: Rope.ROPE, containingBody: REF ANY, -- either BodyInfo or CallableBodyInfo. (It will be CallableBodyInfo exactly when this is an arg or result.) associatedStabs: LIST OF StabInfo, correctedByteOffset: INT, -- this field can be removed when we go to a future Sun C compiler that does not make the offset error following multi word parameters. This field is only used for argument vars. varLoc: MOF.VarLoc, invalid: BOOLEAN _ FALSE, varOccuredTwice: BOOLEAN _ FALSE]; StabInfo: TYPE = RECORD[stab: ObjF.Stab, owningBp: ObjF.BracketPair]; BPInfo: TYPE = REF BPInfoBody; BPInfoBody: TYPE = RECORD[ bp: ObjF.BracketPair, associatedBody: BodyInfo, thereAreOtherAssociatedBodies: BOOLEAN -- TRUE if this bp associates with more than one BodyInfo. (A BAD situation.) ]; <<>> <<>> AnalyzeOneCallableBody: PROC[cbi: CallableBodyInfo] = { jmpi: JointMobParsedInfo _ cbi.jmpi; <> <> <> VisitOneVarSeh: PROC[containingBody: REF ANY, seh: SEH, ser: SER, idBody: REF id MA.BodySE] RETURNS[VarInfo] = { codedSei: CARD _ MA.GetCodedSeiFromSEH[seh]; varKey: REF CARD _ NEW[CARD_codedSei]; vi: VarInfo _ NEW[VarInfoBody_[ seh: seh, codedSei: codedSei, idBody: idBody, name: idBody.hash, containingBody: containingBody, associatedStabs: NIL, correctedByteOffset: 0, varLoc: NIL]]; IF NOT RefTab.Insert[jmpi.vars.table, varKey, vi] THEN BEGIN oldVi: VarInfo _ NARROW[RefTab.Fetch[jmpi.vars.table, varKey].val]; oldVi.varOccuredTwice _ oldVi.invalid _ TRUE; SystemInterface.ShowReport[IO.PutFR["seh with coded sei = %g occurred more than once", IO.card[codedSei]], $debug]; END; <<>> <<(other cases probably should be added)>> <<(should I test for multiple instances?)>> SELECT idBody.special FROM globalLink => cbi.globalLink _ vi; staticLink => cbi.staticLink _ vi; frameExtension => cbi.frameExtension _ vi; ENDCASE => NULL; RETURN[vi]}; <> <> <> VisitAllVarSehsInAContext: PROC[containingBody: REF ANY, ctxh: CTXH] RETURNS[LIST OF VarInfo] = { ctxr: CTXR _ MA.FetchCTXR[ctxh]; seh: SEH _ IF ctxr = NIL THEN NIL ELSE ctxr.seList; results: LIST OF VarInfo _ NIL; lastResult: LIST OF VarInfo _ NIL; WHILE seh # NIL DO ser: SER _ MA.FetchSER[seh]; WITH ser.body SELECT FROM idBody: REF id MA.BodySE => BEGIN vi: VarInfo _ VisitOneVarSeh[containingBody, seh, ser, idBody]; viCell: LIST OF VarInfo _ LIST[vi]; IF results = NIL THEN results _ viCell ELSE lastResult.rest _ viCell; lastResult _ viCell; seh _ idBody.ctxLink; END ENDCASE => ERROR; ENDLOOP; RETURN[results]}; VisitAllVarSehsInArgsOrResults: PROC[containingBody: REF ANY, seh: SEH] RETURNS[LIST OF VarInfo] = { IF seh = NIL THEN RETURN[NIL] ELSE { underSeh: SEH _ UnderTypeSeh[seh]; 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[VisitAllVarSehsInAContext[containingBody, ti.fieldCtx]]; ENDCASE => CCE[cirioError]; ENDCASE => CCE[cirioError]; }; }; <<(0) we exit if the analysis has already been done>> IF cbi.bi # NIL THEN RETURN; <<(1) we begin by creating VarInfos for the args and results>> BEGIN btr: BTR _ MA.FetchBTR[cbi.bth]; 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 => { cbi.args _ VisitAllVarSehsInArgsOrResults[cbi, transfer.typeIn]; cbi.results _ VisitAllVarSehsInArgsOrResults[cbi, transfer.typeOut]}; basic: REF basic MA.TypeInfoConsSE => { <> cbi.args _ NIL; cbi.results _ NIL}; ENDCASE => CCE[cirioError]; ENDCASE => CCE[cirioError]}; ENDCASE => CCE[cirioError]; END; <<(2) we walk the body tree, creating appropriate BodyInfo and VarInfo entries>> { <> VisitOneBody: PROC[parent: BodyInfo, bth: BTH, alwaysRecord: BOOLEAN] RETURNS[BodyInfo] = { bodyKey: RefTab.Key _ CreateBTKeyFromBTH[bth]; codedBti: CARD _ NARROW[bodyKey, REF CARD]^; btr: MA.BTR _ MA.FetchBTR[bth]; biIsCallable: BOOLEAN _ WITH btr.extension SELECT FROM callable: REF Callable MA.BTRExtension => TRUE, other: REF Other MA.BTRExtension => FALSE, ENDCASE => ERROR; bi: BodyInfo _ NEW[BodyInfoBody_[ bth: bth, btr: btr, callable: biIsCallable, codedBti: codedBti, jmpi: jmpi, parent: parent, callableAncestor: cbi, associatedBps: NIL, vars: NIL, subBodies: NIL]]; IF alwaysRecord OR NOT bi.callable THEN -- examine its details { <> IF NOT RefTab.Insert[jmpi.bodies.table, bodyKey, bi] THEN { oldBi: BodyInfo _ NARROW[RefTab.Fetch[jmpi.bodies.table, bodyKey].val]; oldBi.bodyOccurredTwice _ oldBi.invalid _ TRUE; SystemInterface.ShowReport[IO.PutFR["body with coded bti = %g occured more than once", IO.card[codedBti]], $debug]; }; <> bi.vars _ VisitAllVarSehsInAContext[bi, btr.localCtx]; <> { subBth: BTH _ btr.firstSon; lastSubBody: LIST OF BodyInfo _ NIL; WHILE subBth # NIL DO subBtr: BTR _ MA.FetchBTR[subBth]; sub: BodyInfo _ VisitOneBody[bi, subBth, FALSE]; subCell: LIST OF BodyInfo _ LIST[sub]; IF bi.subBodies = NIL THEN bi.subBodies _ subCell ELSE lastSubBody.rest _ subCell; lastSubBody _ subCell; subBth _ IF subBtr.link.which = parent THEN NIL ELSE subBtr.link.index; ENDLOOP; }; }; <<>> RETURN[bi]; }; cbi.bi _ VisitOneBody[NIL, cbi.bth, TRUE]; }; <<>> <<>> <<(3) we walk the Fun, creating BPInfo entries and constructing associations between BPIs and BodyInfos; because Mimosa erroneously puts all static links in the null Context, this is also where we find the static links for the callable body.>> { <> <> <> <> <> cumByteOffset: CARD _ 0; somePSymsSeen: BOOLEAN _ FALSE; ViewSubBracketPair: PROC[bp: ObjF.BracketPair] RETURNS[--stop--BOOLEAN] = { ViewOneBracketPair[bp, FALSE]; RETURN[FALSE]}; ViewOneBracketPair: PROC[bp: ObjF.BracketPair, top: BOOL] = { <> <> NoteBpBtiAssociation: PROC[containingBody: REF ANY] = { WITH containingBody SELECT FROM bi: BodyInfo => { info: BPInfo _ NARROW[RefTab.Fetch[bi.jmpi.bracketPairs.table, bp].val]; alreadyRecordedInBi: BOOLEAN _ FALSE; -- tentative IF info = NIL THEN { info _ NEW[BPInfoBody_[bp, bi, FALSE]]; IF NOT RefTab.Insert[bi.jmpi.bracketPairs.table, bp, info] THEN CCE[cirioError]; }; IF info.associatedBody # bi THEN { pcRange: ObjF.PCRange _ ObjF.GetPCRange[bp]; SystemInterface.ShowReport[IO.PutFR["warning: multiple Mesa block associations for the CBlock containing (ContainingDotO) relative PCs: [%g..%g)", IO.card[pcRange.first], IO.card[pcRange.limit]], $debug]; info.thereAreOtherAssociatedBodies _ TRUE; }; FOR knownBPIs: LIST OF BPInfo _ bi.associatedBps, knownBPIs.rest WHILE knownBPIs # NIL DO IF knownBPIs.first = info THEN {alreadyRecordedInBi _ TRUE; EXIT}; ENDLOOP; IF NOT alreadyRecordedInBi THEN { IF bi.associatedBps # NIL THEN SystemInterface.ShowReport[IO.PutFR["warning: Mesa block with codedBti = %g has multiple associated CBlocks", IO.card[bi.codedBti]], $debug]; bi.associatedBps _ CONS[info, bi.associatedBps]; }; }; cbi: CallableBodyInfo => NULL; -- we needn't record this association (We shall handle PCs outside the outermost C block of a function by going to the Fun, then the CallableBodyInfo, then the associated cbi.) ENDCASE => ERROR; }; ViewOneStab: PROC[stab: ObjF.Stab] RETURNS[--stop-- BOOLEAN] = { IF stab.stabType = LSym OR stab.stabType = PSym OR stab.stabType = RSym THEN { varKey: RefTab.Key _ CreateVarKeyFromVarStab[stab]; codedSei: CARD _ IF varKey = NIL THEN 0 ELSE NARROW[varKey, REF CARD]^; vi: VarInfo _ IF varKey = NIL THEN NIL ELSE NARROW[RefTab.Fetch[jmpi.vars.table, varKey].val]; IF stab.stabType = PSym AND NOT somePSymsSeen THEN { -- for correcting param byte offsets due to errors in C compiler somePSymsSeen _ TRUE; cumByteOffset _ StabValueAsInt[stab]; }; IF varKey#NIL AND vi=NIL AND (cbi.staticLink=NIL OR cbi.globalLink=NIL OR cbi.frameExtension=NIL) THEN { seh: SEH _ MA.MakeSEHFromCodedSei[jmpi.mob, codedSei, NIL]; IF seh#NIL AND MA.IsLost[seh] THEN { ser: SER _ MA.FetchSER[seh]; WITH MA.FetchSER[seh].body SELECT FROM idser: REF id MA.BodySE => IF (SELECT idser.special FROM staticLink => cbi.staticLink=NIL, globalLink => cbi.globalLink=NIL, frameExtension => cbi.frameExtension=NIL, ENDCASE => FALSE) THEN { [] _ VisitOneVarSeh[cbi, seh, ser, idser]; vi _ NARROW[RefTab.Fetch[jmpi.vars.table, varKey].val]}; ENDCASE => NULL; }; }; IF vi # NIL THEN { vi.associatedStabs _ CONS[[stab, bp], vi.associatedStabs]; IF vi.containingBody= NIL THEN ERROR; IF vi.idBody.special # staticLink THEN NoteBpBtiAssociation[vi.containingBody]; <> <> <> <> IF stab.stabType = PSym THEN vi.correctedByteOffset _ cumByteOffset; <> } ELSE cbi.unMatchedStabs _ CONS[stab, cbi.unMatchedStabs]; IF top THEN cbi.topStabs _ CONS[stab, cbi.topStabs]; IF stab.stabType = PSym THEN cumByteOffset _ cumByteOffset + 4; <> <> }; RETURN[FALSE]}; ObjF.GenSymbolStabs[bp, ViewOneStab]; ObjF.GenSubBracketPairs[bp, ViewSubBracketPair]; RETURN}; fun: ObjF.FunHandle _ cbi.fun; brackets: ObjF.BracketPair _ ObjF.GetFunBrackets[fun]; [] _ ViewOneBracketPair[brackets, TRUE]; }; <<>> }; <> UnderTypeSeh: PROC[seh: SEH] RETURNS[SEH] = BEGIN ser: MA.SER _ MA.FetchSER[seh]; WITH ser.body SELECT FROM id: REF id MA.BodySE => BEGIN <> WITH id.idInfoAndValue SELECT FROM idInfo: REF MA.TypeDesc => RETURN[UnderTypeSeh[idInfo.seh]]; ENDCASE => ERROR; END; cons: REF cons MA.BodySE => RETURN[seh]; ENDCASE => ERROR; END; <> <<(Are there other cases of embedded fields? e.g., return values? why don't I handle them?)>> <<>> <> <<>> <> GetVarLocFromVarInfo: PROC[vi: VarInfo] RETURNS[MOF.VarLoc] = { IF vi.varLoc = NIL THEN {-- we have better build one mobFD: REF MA.FieldDesc _ NIL; -- tentative WITH vi.idBody.idInfoAndValue SELECT FROM fd: REF MA.FieldDesc => mobFD _ fd; ENDCASE => NULL; IF mobFD = NIL THEN -- unexpected situation, seh is not a var? vi.varLoc _ NullVarLoc["mobFD = NIL"] ELSE IF vi.idBody.flags.valid AND vi.idBody.flags.upLevel THEN -- known to be in frame extension vi.varLoc _ NEW[ObjF.VarLocBody_[bitSize: mobFD.bitSize, where: frameExtension[bitOffset: mobFD.bitOffset]]] ELSE IF vi.associatedStabs # NIL THEN {-- it is represented as a C var FOR stabs: LIST OF StabInfo _ vi.associatedStabs, stabs.rest WHILE stabs # NIL DO stab: ObjF.Stab _ stabs.first.stab; IF vi.varLoc # NIL THEN {-- we have seeen at least one previous stab <<(We assume that the stabs are ordered as they appear in the dotO, hence the PSym will occur before any modifying RSym.)>> baseCase: ObjF.VarLocCase ~ WITH vi.varLoc SELECT FROM x: ObjF.IndirectVarLoc => x.base.case, ENDCASE => vi.varLoc.case; SELECT TRUE FROM baseCase = register => NULL; -- let it stand baseCase # register AND stab.stabType = RSym => {-- overwrite it bitSize: CARD16 _ BitsForBytes[stab.size]; newVarLoc: ObjF.VarLoc; IF bitSize > 32 THEN newVarLoc _ NEW[ObjF.VarLocBody _ [ bitSize: bitSize, where: indirect[ base: NEW[ObjF.VarLocBody _ [ bitSize: CirioTypes.bitsPerPtr, where: register[regNum: stab.value]]], offset: CirioTypes.zeroBA]]] ELSE newVarLoc _ NEW[ObjF.VarLocBody _ [ bitSize: bitSize, where: register[regNum: stab.value]]]; vi.varLoc _ newVarLoc; }; ENDCASE => CCE[cirioError] -- I dont think this is supposed to happen } ELSE { -- we have seen no previouis stabs SELECT TRUE FROM stab.stabType = RSym => { bitSize: CARD16 _ BitsForBytes[stab.size]; IF bitSize>32 THEN vi.varLoc _ NEW[ObjF.VarLocBody _ [ bitSize: bitSize, where: indirect[ base: NEW[ObjF.VarLocBody _ [ bitSize: CirioTypes.bitsPerPtr, where: register[regNum: stab.value]]], offset: CirioTypes.zeroBA]]] ELSE vi.varLoc _ NEW[ObjF.VarLocBody _ [ bitSize: bitSize, where: register[regNum: stab.value]]]; }; <> stab.stabType = PSym => { bitSize: CARD16 _ BitsForBytes[stab.size]; IF bitSize>32 THEN vi.varLoc _ NEW[ObjF.VarLocBody _ [ bitSize: bitSize, where: indirect[ base: NEW[ObjF.VarLocBody _ [ bitSize: CirioTypes.bitsPerPtr, where: frame[bitOffset: BitsForBytes[vi.correctedByteOffset]]]], offset: CirioTypes.zeroBA]]] ELSE vi.varLoc _ NEW[ObjF.VarLocBody _ [ bitSize: bitSize, where: frame[bitOffset: BitsForBytes[vi.correctedByteOffset]]]]; }; stab.stabType = LSym => { bitSize: CARD16 _ BitsForBytes[stab.size]; vi.varLoc _ NEW[ObjF.VarLocBody _ [ bitSize: bitSize, where: frame[bitOffset: BitsForBytes[StabValueAsInt[stab]]]]]; }; ENDCASE => NULL; -- ignore it }; ENDLOOP; IF vi.varLoc = NIL THEN -- nothing filled it in vi.varLoc _ NullVarLoc["not in any associated stab"]; } ELSE -- hmm... perhaps the mob forgot to mark it as uplevel (this issue should go away eventually) So, we use exactly the same code as the above uplevel case. vi.varLoc _ NEW[ObjF.VarLocBody_[bitSize: mobFD.bitSize, where: frameExtension[bitOffset: mobFD.bitOffset]]]; IF vi.varLoc.bitSize#0 AND mobFD#NIL AND vi.varLoc.bitSize#mobFD.bitSize THEN CCE[cirioError, IO.PutFR["mob and .o disagree on bit size of \"%q\" (codedSei=%g=%xH)", [rope[vi.name]], [cardinal[vi.codedSei]], [cardinal[vi.codedSei]] ]]; <> }; RETURN[vi.varLoc]}; BitsForBytes: PROC[bytes: INT] RETURNS[INT] = {RETURN[PBasics.bitsPerByte*bytes]}; StabValueAsInt: PROC[stab: ObjF.Stab] RETURNS[INT] = TRUSTED {RETURN[LOOPHOLE[stab.value, INT]]}; <<>> FullShowOneAnalyzedCBI: PROC[cbi: CallableBodyInfo, depth: CARD, on: IO.STREAM] = BEGIN Tab: PROC[added: CARD] = {FOR I: CARD IN [0..depth+added) DO IO.PutF[on, " "] ENDLOOP}; Tab[0]; IO.PutF[on, "arguments\N"]; FOR vis: LIST OF VarInfo _ cbi.args, vis.rest WHILE vis # NIL DO ShowOneVI[vis.first, depth+5, on]; ENDLOOP; IO.PutF[on, "\N"]; Tab[0]; IO.PutF[on, "results\N"]; FOR vis: LIST OF VarInfo _ cbi.results, vis.rest WHILE vis # NIL DO ShowOneVI[vis.first, depth+5, on]; ENDLOOP; IO.PutF[on, "\N"]; IF cbi.globalLink = NIL THEN {Tab[0]; IO.PutF[on, "(no global link var)\N"]} ELSE {Tab[0]; IO.PutF[on, "global link var coded sei = %g\N", IO.card[cbi.globalLink.codedSei]]}; IF cbi.staticLink = NIL THEN {Tab[0]; IO.PutF[on, "(no static link var)\N"]} ELSE {Tab[0]; IO.PutF[on, "static link var coded sei = %g\N", IO.card[cbi.staticLink.codedSei]]}; IF cbi.frameExtension = NIL THEN {Tab[0]; IO.PutF[on, "(no frame extension var)\N"]} ELSE {Tab[0]; IO.PutF[on, "frame extension var coded sei = %g\N", IO.card[cbi.frameExtension.codedSei]]}; FullShowOneBI[cbi.bi, depth, on, TRUE]; IF cbi.unMatchedStabs # NIL THEN BEGIN Tab[0]; IO.PutF[on, "unmatched stabs\N"]; ShowStabList[on, depth+5, cbi.unMatchedStabs]; IO.PutF[on, "\N"]; END; IF cbi.topStabs # NIL THEN BEGIN Tab[0]; IO.PutF[on, "top-level stabs\N"]; ShowStabList[on, depth+5, cbi.topStabs]; IO.PutF[on, "\N"]; END; END; <<>> <> FullShowOneBI: PROC[bi: BodyInfo, depth: CARD, on: IO.STREAM, alwaysShowDetails: BOOLEAN] = BEGIN Tab: PROC[added: CARD] = {FOR I: CARD IN [0..depth+added) DO IO.PutF[on, " "] ENDLOOP}; Tab[0]; IO.PutF[on, "body for coded bti = %g\N", IO.card[bi.codedBti]]; IF bi.invalid THEN BEGIN Tab[0]; IO.PutF[on, "invalid"]; IF bi.bodyOccurredTwice THEN IO.PutF[on, " bodyOccurredTwice"]; IO.PutF[on, "\N"]; END; Tab[5]; WITH bi.btr.extension SELECT FROM c: REF Callable MA.BTRExtension => BEGIN idSer: SER _ MA.FetchSER[c.id]; IF idSer # NIL THEN WITH idSer.body SELECT FROM id: REF id MA.BodySE => IO.PutF[on, "name: %g", IO.rope[id.hash]]; cons: REF cons MA.BodySE => IO.PutF[on, "(c.id is not an id)"]; ENDCASE => IO.PutF[on, "(c.id is impossible)"] ELSE IO.PutF[on, "(c.id is NIL)"]; IO.PutF[on, ", bodyKind: %g, ", IO.rope[SELECT c.kind FROM Outer => "Outer", Inner => "Inner", Catch => "Catch", Other => "Other", ENDCASE => "impossible"]]; END; o: REF Other MA.BTRExtension => NULL; ENDCASE => ERROR; IO.PutF[on, "level: %g", IO.card[bi.btr.level]]; IO.PutF[on, "\N"]; Tab[5]; SELECT bi.btr.link.which FROM sibling => IO.PutF[on, "sibling: %g", IO.card[MA.GetCodedBTIFromBTH[bi.btr.link.index]]]; parent => IO.PutF[on, "parent: %g", IO.card[MA.GetCodedBTIFromBTH[bi.btr.link.index]]]; ENDCASE => ERROR; IO.PutF[on, "\N"]; IF bi.associatedBps = NIL AND (alwaysShowDetails OR NOT bi.callable) THEN {Tab[5]; IO.PutF[on, "WARNING: no associated CBlocks\N"]} ELSE IF bi.associatedBps # NIL AND bi.associatedBps.rest # NIL THEN {Tab[5]; IO.PutF[on, "WARNING: multiple associated CBlocks\N"]}; IF bi.associatedBps # NIL THEN BEGIN Tab[5]; IO.PutF[on, "associated CBlock PC ranges\N"]; FOR knownBPIs: LIST OF BPInfo _ bi.associatedBps, knownBPIs.rest WHILE knownBPIs # NIL DO pcRange: ObjF.PCRange _ ObjF.GetPCRange[knownBPIs.first.bp]; Tab[7]; IO.PutF[on, "[%g..%g)\N", IO.card[pcRange.first], IO.card[pcRange.limit]]; ENDLOOP; END; IF alwaysShowDetails OR NOT bi.callable THEN BEGIN Tab[5]; IO.PutF[on, "BEGIN\N"]; FOR vis: LIST OF VarInfo _ bi.vars, vis.rest WHILE vis # NIL DO ShowOneVI[vis.first, depth+5, on]; ENDLOOP; FOR bis: LIST OF BodyInfo _ bi.subBodies, bis.rest WHILE bis # NIL DO IO.PutF[on, "\N"]; FullShowOneBI[bis.first, depth+5, on, FALSE]; ENDLOOP; Tab[5]; IO.PutF[on, "END\N"]; END; END; ShowOneVI: PROC[vi: VarInfo, depth: CARD, on: IO.STREAM] = BEGIN Tab: PROC[added: CARD] = {FOR I: CARD IN [0..depth+added) DO IO.PutF[on, " "] ENDLOOP}; Tab[0]; IO.PutF[on, "var for codedSei = %g\N", IO.card[vi.codedSei]]; Tab[2]; IO.PutF[on, "mob reports:\N"]; IF Rope.Length[vi.name] = 0 THEN {Tab[4]; IO.PutF[on, "(unnamed)\N"]} ELSE {Tab[4]; IO.PutF[on, "name = %g\N", IO.rope[vi.name]]}; IF vi.idBody.extended THEN {Tab[4]; IO.PutF[on, "extended\N"]}; IF vi.idBody.public THEN {Tab[4]; IO.PutF[on, "public\N"]}; IF vi.idBody.immutable THEN {Tab[4]; IO.PutF[on, "immutable\N"]}; IF vi.idBody.constant THEN {Tab[4]; IO.PutF[on, "constant\N"]}; IF vi.idBody.linkSpace THEN {Tab[4]; IO.PutF[on, "linkSpace\N"]}; IF vi.idBody.flags.valid THEN BEGIN IF vi.idBody.flags.used THEN {Tab[4]; IO.PutF[on, "used\N"]}; IF vi.idBody.flags.addressed THEN {Tab[4]; IO.PutF[on, "addressed\N"]}; IF vi.idBody.flags.assigned THEN {Tab[4]; IO.PutF[on, "assigned\N"]}; IF vi.idBody.flags.upLevel THEN {Tab[4]; IO.PutF[on, "upLevel\N"]}; IF vi.idBody.flags.sized THEN {Tab[4]; IO.PutF[on, "sized\N"]}; IF vi.idBody.flags.spare1 THEN {Tab[4]; IO.PutF[on, "spare1\N"]}; IF vi.idBody.flags.spare2 THEN {Tab[4]; IO.PutF[on, "spare2\N"]}; END; IF vi.idBody.special # normal THEN BEGIN text: Rope.ROPE _ SELECT vi.idBody.special FROM globalLink => "globalLink", staticLink => "staticLink", frameExtension => "frameExtension", memoryLink => "memoryLink", returnLink => "returnLink", argLink => "argLink", returnVar => "returnVar", argVar => "argVar", globalVar => "globalVar", extensionVar=> "extensionVar", invalid => "invalid", ENDCASE => IO.PutFR["specialKind = %g", IO.card[ORD[vi.idBody.special]]]; Tab[4]; IO.PutF[on, "%g\N", IO.rope[text]]; END; WITH vi.idBody.idInfoAndValue SELECT FROM fd: REF MA.FieldDesc => {Tab[4]; IO.PutF[on, "(bitSize: %g, bitOffset: %g)\N", IO.card[fd.bitSize], IO.int[fd.bitOffset]]}; td: REF MA.TypeDesc => {Tab[4]; IO.PutF[on, "(TypeDesc)\N"]}; bd: REF MA.BlockDesc => {Tab[4]; IO.PutF[on, "(BlockDesc)\N"]}; cv: REF MA.ConstVal => {Tab[4]; IO.PutF[on, "cv = %g\N", IO.card[cv.value]]}; ENDCASE => {Tab[4]; IO.PutF[on, "(unexpected idInfoAndValue)\N"]}; Tab[2]; IO.PutF[on, "correctedByteOffset: %g\N", IO.int[vi.correctedByteOffset]]; [] _ GetVarLocFromVarInfo[vi]; IF vi.varLoc = NIL THEN {Tab[2]; IO.PutF[on, "(no varLoc)\N"]} ELSE BEGIN Tab[2]; IO.PutF[on, "varLoc[bitSize: %g, ", IO.card[vi.varLoc.bitSize]]; WITH vi.varLoc SELECT FROM reg: REF register MOF.VarLocBody => IO.PutF[on, "register[regNum: %g]]]\N", IO.card[reg.regNum]]; frm: REF frame MOF.VarLocBody => IO.PutF[on, "frame[bitOffset: %g]]]\N", IO.int[frm.bitOffset]]; frmExt: REF frameExtension MOF.VarLocBody => IO.PutF[on, "frameExtension[bitOffset: %g]]]\N", IO.int[frmExt.bitOffset]]; seg: REF fSegment MOF.VarLocBody => BEGIN kindRope: Rope.ROPE _ seg.fSeg.fSegName; <> < "patch",>> < "text",>> < "data",>> < "bss",>> < "common",>> < "ILLEGAL";>> IO.PutF[on, "segment[kind: %g, bitOffset: %g]]]\N", IO.rope[kindRope], IO.int[seg.bitOffset]]; END; unk: REF unknown MOF.VarLocBody => IO.PutF[on, "unknown[]]]\N"]; ENDCASE => IO.PutF[on, "ILLEGAL]]\N"]; END; IF vi.associatedStabs # NIL THEN BEGIN Tab[2]; IO.PutF[on, "stabs\N"]; ShowStabInfoList[on, depth+4, vi.associatedStabs]; END; IO.PutF[on, "\N"]; END; ShowStabList: PROC[on: IO.STREAM, depth: CARD, stabs: LIST OF ObjF.Stab] = BEGIN Tab: PROC[added: CARD] = {FOR I: CARD IN [0..depth+added) DO IO.PutF[on, " "] ENDLOOP}; FOR ss: LIST OF ObjF.Stab _ stabs, ss.rest WHILE ss # NIL DO stab: ObjF.Stab _ ss.first; stabRope: Rope.ROPE _ stab.rope; fieldsRope: Rope.ROPE _ RopeForStabFields[stab]; Tab[0]; IO.PutF[on, "%g\N", IO.rope[fieldsRope]]; Tab[2]; IO.PutF[on, "%g\N", IO.rope[stabRope]]; ENDLOOP; END; ShowStabInfoList: PROC[on: IO.STREAM, depth: CARD, list: LIST OF StabInfo] = BEGIN Tab: PROC[added: CARD] = {FOR I: CARD IN [0..depth+added) DO IO.PutF[on, " "] ENDLOOP}; FOR ss: LIST OF StabInfo _ list, ss.rest WHILE ss # NIL DO stabInfo: StabInfo _ ss.first; stabRope: Rope.ROPE _ stabInfo.stab.rope; fieldsRope: Rope.ROPE _ RopeForStabFields[stabInfo.stab]; pcRange: ObjF.PCRange _ ObjF.GetPCRange[stabInfo.owningBp]; Tab[0]; IO.PutF[on, "stab: %g\N", IO.rope[fieldsRope]]; Tab[2]; IO.PutF[on, "OwningBPI-PCRange: [%g..%g)\N", IO.card[pcRange.first], IO.card[pcRange.limit]]; Tab[2]; IO.PutF[on, "%g\N", IO.rope[stabRope]]; ENDLOOP; END; RopeForStabFields: PROC[stab: ObjF.Stab] RETURNS[Rope.ROPE] = BEGIN fields: Rope.ROPE _ NIL; fields _ Rope.Concat[fields, IO.PutFR["stabX: %g, ", IO.card[stab.stabX]]]; fields _ Rope.Concat[fields, IO.PutFR["stabType: %g, ", IO.rope[RopeForStabType[stab.stabType]]]]; fields _ Rope.Concat[fields, IO.PutFR["size: %g, ", IO.card[stab.size]]]; fields _ Rope.Concat[fields, IO.PutFR["value: %g, ", IO.card[stab.value]]]; RETURN[fields]; END; RopeForStabType: PROC[stabType: ObjF.StabType] RETURNS[Rope.ROPE] = BEGIN RETURN[SELECT stabType FROM LBrac => "LBrac", RBrac => "RBrac", SLine => "SLine", Fun => "Fun", PSym => "PSym", LSym => "LSym", RSym => "RSym", ENDCASE => ""]; END; <<>> <> <<>> <> <<>> CallableBodyInfo: TYPE = REF CallableBodyInfoBody; CallableBodyInfoBody: TYPE = RECORD[ bth: BTH, codedBti: CARD, jmpi: JointMobParsedInfo, fun: ObjF.FunHandle, bi: BodyInfo _ NIL, -- will be filled in when needed args: LIST OF VarInfo _ NIL, -- filled in when bi is filled in results: LIST OF VarInfo _ NIL, -- filled in when bi is filled in globalLink: VarInfo _ NIL, -- filled in when bi is filled in staticLink: VarInfo _ NIL, -- filled in when bi is filled in frameExtension: VarInfo _ NIL, -- filled in when bi is filled in unMatchedStabs, topStabs: LIST OF ObjF.Stab _ NIL, invalid: BOOLEAN _ FALSE, multiFuns: BOOLEAN _ FALSE, bodyOccurredTwice: BOOLEAN _ FALSE]; <<>> AnalyzeCallableBodySet: PROC[jmpi: JointMobParsedInfo] = BEGIN <> BEGIN SeeOneBody: PROC[callableBody: BTH] = BEGIN key: RefTab.Key _ CreateBTKeyFromBTH[callableBody]; codedBti: CARD _ NARROW[key, REF CARD]^; cbi: CallableBodyInfo _ NEW[CallableBodyInfoBody_[callableBody, codedBti, jmpi, NIL]]; IF NOT RefTab.Insert[jmpi.callableBodies.table, key, cbi] THEN BEGIN oldCbi: CallableBodyInfo _ NARROW[RefTab.Fetch[jmpi.callableBodies.table, key].val]; oldCbi.bodyOccurredTwice _ oldCbi.invalid _ TRUE; SystemInterface.ShowReport[IO.PutFR["callable body with coded bti = %g occured more than once", IO.card[codedBti]], $debug]; END; END; MA.GenCallableBodies[jmpi.mob, SeeOneBody]; END; <<>> <> BEGIN SeeOneFun: PROC[fun: ObjF.FunHandle] RETURNS[--stop-- BOOLEAN] = BEGIN cbi: CallableBodyInfo _ GetCBIForFun[jmpi, fun]; IF cbi # NIL THEN BEGIN IF cbi.fun = NIL THEN cbi.fun _ fun ELSE BEGIN cbi.multiFuns _ cbi.invalid _ TRUE; SystemInterface.ShowReport[IO.PutFR["callable body with coded bti = %g has more than one corresponding fun", IO.card[cbi.codedBti]], $debug]; END; END; RETURN[FALSE] END; ObjF.GenFuns[jmpi.module, SeeOneFun]; END; END; <> <> GetCBIForBth: PROC[jmpi: JointMobParsedInfo, bth: BTH] RETURNS[CallableBodyInfo] = BEGIN key: RefTab.Key _ CreateBTKeyFromBTH[bth]; RETURN[NARROW[RefTab.Fetch[jmpi.callableBodies.table, key].val]]; END; <> <> GetCBIForFun: PROC[jmpi: JointMobParsedInfo, fun: ObjF.FunHandle] RETURNS[CallableBodyInfo] = BEGIN key: RefTab.Key _ CreateBTKeyFromFun[fun]; IF key # NIL THEN RETURN[NARROW[RefTab.Fetch[jmpi.callableBodies.table, key].val]] ELSE RETURN[NIL]; END; GetBiFromCbi: PROC[cbi: CallableBodyInfo] RETURNS[bi: BodyInfo] = BEGIN IF cbi.bi = NIL THEN AnalyzeOneCallableBody[cbi]; RETURN[cbi.bi]; END; ShowOneCallableBody: PROC[jmpi: JointMobParsedInfo, callableBody: BTH, on: IO.STREAM] = BEGIN cbi: CallableBodyInfo _ GetCBIForBth[jmpi, callableBody]; IF cbi # NIL THEN BEGIN IO.PutF[on, "\Nfor codedBti = %g we have:\N", IO.card[cbi.codedBti]]; IF cbi.fun = NIL THEN IO.PutF[on, "\Tno Fun\N"] ELSE BEGIN info: ObjF.FunInfo _ ObjF.GetFunInfo[cbi.fun]; IO.PutF[on, "\T Fun CName = %g\N", IO.rope[info.cName]]; END; IF cbi.invalid THEN BEGIN IO.PutF[on, "\Tinvalid = TRUE"]; IF cbi.multiFuns THEN IO.PutF[on, "\TmultiFuns = TRUE"]; IF cbi.bodyOccurredTwice THEN IO.PutF[on, "\TbodyOccuredTwice = TRUE"]; END; END ELSE BEGIN key: RefTab.Key _ CreateBTKeyFromBTH[callableBody]; codedBti: CARD _ NARROW[key, REF CARD]^; IO.PutF[on, "\Nfound NO cbi for coded bti = %g\N", IO.card[codedBti]]; END; END; ShowCallableBodiesInfo: PROC[jmpi: JointMobParsedInfo, on: IO.STREAM] = BEGIN badFunHeaderPrinted: BOOLEAN _ FALSE; -- initial value ShowOneBody: PROC[callableBody: BTH] = {ShowOneCallableBody[jmpi, callableBody, on]}; CheckOneFun: PROC[fun: ObjF.FunHandle] RETURNS[--stop-- BOOLEAN] = BEGIN cbi: CallableBodyInfo _ GetCBIForFun[jmpi, fun]; IF cbi = NIL THEN BEGIN info: ObjF.FunInfo _ ObjF.GetFunInfo[fun]; IF NOT badFunHeaderPrinted THEN BEGIN badFunHeaderPrinted _ TRUE; IO.PutF[on, "Following Funs have no cbi:\N"]; END; IO.PutF[on, "\T%g\N", IO.rope[info.cName]]; END; RETURN[FALSE] END; MA.GenCallableBodies[jmpi.mob, ShowOneBody]; ObjF.GenFuns[jmpi.module, CheckOneFun]; IF NOT badFunHeaderPrinted THEN IO.PutF[on, "All Funs have corresponding cbis. This is unexpected.\N"]; END; <> <<>> <> CreateBTHashTable: PROC RETURNS[BTHashTable] = {RETURN[NEW[BTHashTableBody _ [RefTab.Create[equal: BTKeyEqualProc, hash: BTKeyHashProc]]]]}; CreateBTKeyFromCodedBTI: PROC[codedBti: CARD] RETURNS[RefTab.Key] = BEGIN RETURN[NEW[CARD _ codedBti]]; END; <> CreateBTKeyFromFun: PROC[fun: ObjF.FunHandle]RETURNS[RefTab.Key] = BEGIN info: ObjF.FunInfo _ ObjF.GetFunInfo[fun]; funStab: ObjF.Stab _ info.stab; nameAndNumber: ObjF.NameAndNumber _ ObjF.ParseNameRope[funStab]; IF nameAndNumber.valid AND nameAndNumber.char # 'L AND nameAndNumber.number >= 0 THEN BEGIN codedBti: CARD _ nameAndNumber.number; key: RefTab.Key _ NEW[CARD _ codedBti]; RETURN[key]; END ELSE RETURN[NIL] END; CreateBTKeyFromBTH: PROC[bth: BTH] RETURNS[RefTab.Key] = BEGIN codedBti: CARD _ MA.GetCodedBTIFromBTH[bth]; RETURN[NEW[CARD _ codedBti]]; END; BTKeyEqualProc: PROC[key1, key2: RefTab.Key] RETURNS [BOOL] = BEGIN codedBti1Ref: REF CARD _ NARROW[key1]; codedBti2Ref: REF CARD _ NARROW[key2]; RETURN[codedBti1Ref^ = codedBti2Ref^]; END; BTKeyHashProc: PROC[key: RefTab.Key] RETURNS [CARDINAL] = BEGIN codedBtiRef: REF CARD _ NARROW[key]; asLongNumber: Basics.LongNumber _ LOOPHOLE[codedBtiRef^]; RETURN[Basics.BITXOR[asLongNumber.lo, asLongNumber.hi]]; END; <> <<>> <> CreateVarHashTable: PROC RETURNS[VarHashTable] = {RETURN[NEW[VarHashTableBody _ [RefTab.Create[equal: VarKeyEqualProc, hash: VarKeyHashProc]]]]}; CreateVarKeyFromCodedSEI: PROC[codedSei: CARD] RETURNS[RefTab.Key] = BEGIN RETURN[NEW[CARD _ codedSei]]; END; <> CreateVarKeyFromVarStab: PROC[stab: ObjF.Stab]RETURNS[RefTab.Key] = BEGIN nameAndNumber: ObjF.NameAndNumber _ ObjF.ParseNameRope[stab]; <> IF nameAndNumber.valid AND (nameAndNumber.char = 'v OR nameAndNumber.char = 'c) AND nameAndNumber.number > 0 THEN BEGIN codedSei: CARD _ nameAndNumber.number; key: RefTab.Key _ NEW[CARD _ codedSei]; RETURN[key]; END ELSE RETURN[NIL] END; CreateVarKeyFromSEH: PROC[seh: SEH] RETURNS[RefTab.Key] = BEGIN codedSei: CARD _ MA.GetCodedSeiFromSEH[seh]; RETURN[NEW[CARD _ codedSei]]; END; VarKeyEqualProc: PROC[key1, key2: RefTab.Key] RETURNS [BOOL] = BEGIN codedSei1Ref: REF CARD _ NARROW[key1]; codedSei2Ref: REF CARD _ NARROW[key2]; RETURN[codedSei1Ref^ = codedSei2Ref^]; END; VarKeyHashProc: PROC[key: RefTab.Key] RETURNS [CARDINAL] = BEGIN codedSeiRef: REF CARD _ NARROW[key]; asLongNumber: Basics.LongNumber _ LOOPHOLE[codedSeiRef^]; RETURN[Basics.BITXOR[asLongNumber.lo, asLongNumber.hi]]; END; <<>> <<>> <> <<>> <> CreateBpHashTable: PROC RETURNS[BPHashTable] = {RETURN[NEW[BPHashTableBody _ [RefTab.Create[]]]]}; <<>> <<>> <> PerformJMDITest: PUBLIC PROC[what: Rope.ROPE, jmpi: JointMobParsedInfo, out: IO.STREAM] = BEGIN ENABLE ShowOff => {IO.Put[out, IO.rope[msg]]; RESUME}; SELECT TRUE FROM Rope.Equal[what, "CallableBodies"] => ShowAllCallableBodies[jmpi]; ENDCASE => CCE[cirioError]; END; ShowAllCallableBodies: PROC[jmpi: JointMobParsedInfo] = BEGIN showOne: PROC[callableBody: BTH] = BEGIN btr: MA.BTR _ MA.FetchBTR[callableBody]; ShowOff[IO.PutFR["\Tbti = %g, at source pos %g\N", IO.card[MA.GetCodedBTIFromBTH[callableBody]], IO.int[btr.sourceIndex]]]; END; ShowOff[IO.PutFR["\N\Nall Callable Bodies\N"]]; MA.GenCallableBodies[jmpi.mob, showOne]; ShowOff[IO.PutFR["\N"]]; END; <<>> <> GenInterestingPCs: PUBLIC PROC[module: ObjF.Module, for: PROC[bp: ObjF.BracketPair, pc: CARD]] = BEGIN lowestFunPC: CARD _ LAST[CARD]; SeeOneFunBracket: PROC[bp: ObjF.BracketPair] RETURNS[--stop-- BOOLEAN] = BEGIN pcRange: ObjF.PCRange _ ObjF.GetPCRange[bp]; IF pcRange.first < lowestFunPC THEN lowestFunPC _ pcRange.first; GenInterestingPCsWithinABracket[bp, for]; RETURN[FALSE]; END; ObjF.GenFunBracketPairs[module, SeeOneFunBracket]; IF lowestFunPC > 0 THEN for[NIL, lowestFunPC-1]; END; <> GenInterestingPCsWithinABracket: PROC[bp: ObjF.BracketPair, for: PROC[bp: ObjF.BracketPair, pc: CARD]] = BEGIN pcRange: ObjF.PCRange _ ObjF.GetPCRange[bp]; tentative: CARD _ pcRange.first; SeeOneSubBracket1: PROC[bp: ObjF.BracketPair] RETURNS[--stop-- BOOLEAN] = BEGIN subRange: ObjF.PCRange _ ObjF.GetPCRange[bp]; IF subRange.first <= tentative THEN {tentative _ subRange.limit; RETURN[FALSE]} ELSE RETURN[TRUE]; END; SeeOneSubBracket2: PROC[bp: ObjF.BracketPair] RETURNS[--stop-- BOOLEAN] = {GenInterestingPCsWithinABracket[bp, for]; RETURN[FALSE]}; ObjF.GenSubBracketPairs[bp, SeeOneSubBracket1]; IF tentative < pcRange.limit THEN for[bp, tentative]; ObjF.GenSubBracketPairs[bp, SeeOneSubBracket2]; END; <> <> <> <> << ELSE>> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> < RETURN["\T\Toutermost pair"];>> < >> <> <> <> <> < >> <> <> <> <> <> <> <> <> <> < CCE[cirioError];>> <> <<>> <<>> ShowOff: SIGNAL[msg: Rope.ROPE] = CODE; ShowMob: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; mobPath: PFSNames.PATH _ PFS.PathFromRope[args[1]]; wholePath: PFSNames.PATH _ PFS.PathFromRope[args[2]]; relativePC: CARD _ IF args.argc < 4 THEN 0 ELSE Convert.CardFromRope[args[3]]; type: Rope.ROPE _ IF args.argc < 5 THEN "SunADotOut" ELSE args[4]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; mobFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, mobPath]; wholeFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, wholePath]; mob: MA.MobCookie _ MA.CreateMobCookie[mobFile]; whole: ObjF.Parsed _ ObjF.CreateParsed[wholeFile, type]; module: ObjF.Module _ ObjF.ModuleFromParsedAndPC[whole, [[0, ""], relativePC]]; jmpi: JointMobParsedInfo _ CreateJointMobParsedInfo[mob, whole, module]; <> <> IO.PutF[cmd.out, "\NCallableBodies\N"]; PerformJMDITest["CallableBodies", jmpi, cmd.out]; <> <> <> <> END; SystemInterface.CloseFileSet[fileSet]; END; ShowCallableBodies: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; mobPath: PFSNames.PATH _ PFS.PathFromRope[args[1]]; wholePath: PFSNames.PATH _ PFS.PathFromRope[args[2]]; relativePC: CARD _ IF args.argc < 4 THEN 0 ELSE Convert.CardFromRope[args[3]]; type: Rope.ROPE _ IF args.argc < 5 THEN "SunADotOut" ELSE args[4]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; mobFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, mobPath]; wholeFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, wholePath]; mob: MA.MobCookie _ MA.CreateMobCookie[mobFile]; whole: ObjF.Parsed _ ObjF.CreateParsed[wholeFile, type]; module: ObjF.Module _ ObjF.ModuleFromParsedAndPC[whole, [[0, ""], relativePC]]; jmpi: JointMobParsedInfo _ CreateJointMobParsedInfo[mob, whole, module]; ShowCallableBodiesInfo[jmpi, cmd.out]; END; SystemInterface.CloseFileSet[fileSet]; END; ShowOneBody: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; mobPath: PFSNames.PATH _ PFS.PathFromRope[args[1]]; wholePath: PFSNames.PATH _ PFS.PathFromRope[args[2]]; relativePC: CARD _ Convert.CardFromRope[args[3]]; codedBti: CARD _ Convert.CardFromRope[args[4]]; type: Rope.ROPE _ IF args.argc < 6 THEN "SunADotOut" ELSE args[5]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; mobFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, mobPath]; wholeFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, wholePath]; mob: MA.MobCookie _ MA.CreateMobCookie[mobFile]; whole: ObjF.Parsed _ ObjF.CreateParsed[wholeFile, type]; module: ObjF.Module _ ObjF.ModuleFromParsedAndPC[whole, [[0, ""], relativePC]]; jmpi: JointMobParsedInfo _ CreateJointMobParsedInfo[mob, whole, module]; BEGIN btKey: RefTab.Key _ NEW[CARD _ codedBti]; cbi: CallableBodyInfo _ NARROW[RefTab.Fetch[jmpi.callableBodies.table, btKey].val]; bi: BodyInfo _ GetBiFromCbi[cbi]; -- forces the analysis of cbi?? FullShowOneAnalyzedCBI[cbi, 0, cmd.out]; END; END; SystemInterface.CloseFileSet[fileSet]; END; CheckAllCallableBodies: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; mobPath: PFSNames.PATH _ PFS.PathFromRope[args[1]]; wholePath: PFSNames.PATH _ PFS.PathFromRope[args[2]]; relativePC: CARD _ IF args.argc < 4 THEN 0 ELSE Convert.CardFromRope[args[3]]; type: Rope.ROPE _ IF args.argc < 5 THEN "SunADotOut" ELSE args[4]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; mobFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, mobPath]; wholeFile: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, wholePath]; mob: MA.MobCookie _ MA.CreateMobCookie[mobFile]; whole: ObjF.Parsed _ ObjF.CreateParsed[wholeFile, type]; module: ObjF.Module _ ObjF.ModuleFromParsedAndPC[whole, [[0, ""], relativePC]]; jmpi: JointMobParsedInfo _ CreateJointMobParsedInfo[mob, whole, module]; CheckOneCallableBody: PROC[callableBody: BTH] = BEGIN ShowOneCallableBody[jmpi, callableBody, cmd.out]; <> BEGIN cbi: CallableBodyInfo _ GetCBIForBth[jmpi, callableBody]; bi: BodyInfo _ GetBiFromCbi[cbi]; -- forces the analysis of cbi?? END; END; MA.GenCallableBodies[mob, CheckOneCallableBody]; END; SystemInterface.CloseFileSet[fileSet]; END; <
> Commander.Register["ShowMob", ShowMob, "usage:\N\TShowMob fullPathMobName fullPathDotOName relPC [format]\N\Twhere\N\T\TfullPathMobName is the mob\N\T\TfullPathDotOName is name of the containing whole\N\T\TrelPC is a containingDotO-relative PC within the desired embeddedd DotO\N\T\Tformat is XCOFF or SunADotOut"]; <sturgis>cirio>SymbolFindingImpl.mob [Menhir-ux]sturgis>cirio>sun4>SymbolFindingImpl.c2c.o 0>> <<>> Commander.Register["ShowCallableBodies", ShowCallableBodies, "usage:\N\TShowCallableBodies fullPathMobName fullPathDotOName relPC [format]\N\Twhere\N\T\TfullPathMobName is the mob\N\T\TfullPathDotOName is name of the containing whole\N\T\TrelPC is a containingDotO-relative PC within the desired embeddedd DotO\N\T\Tformat is XCOFF or SunADotOut"]; <StackCirioImpl.c2c.o 0>> <<>> Commander.Register["ShowOneCallableBody", ShowOneBody, "usage:\N\TShowOneCallableBody fullPathMobName fullPathDotOName relPC codedBti [format]\N\Twhere\N\T\TfullPathMobName is the mob\N\T\TfullPathDotOName is name of the containing whole\N\T\TrelPC is a containingDotO-relative PC within the desired embeddedd DotO\N\T\TcodedBti is the codedBti of a callable block\N\T\Tformat is XCOFF or SunADotOut"]; <StackCirioImpl.c2c.o 0 xxx>> <<>> Commander.Register["CheckAllCallableBodies", CheckAllCallableBodies, "usage:\TCheckAllCallableBodies fullPathMobName fullPathDotOName relPC [format]\N\Twhere\N\T\TfullPathMobName is the mob\N\T\TfullPathDotOName is name of the containing whole\N\T\TrelPC is a containingDotO-relative PC within the desired embeddedd DotO\N\T\Tformat is XCOFF or SunADotOut"]; <StackCirioImpl.c2c.o 0>> <<>> END..