-- File ModuleSymbolsImpl.mesa -- Last edited by Lewis on 5-Jan-82 19:46:02 -- Last edited by Satterthwaite, December 27, 1982 9:44 am DIRECTORY BcdDefs USING [FTIndex, FTNull, FTSelf, MTIndex, SGIndex, SGNull, VersionStamp], CIFS: TYPE USING [OpenFile, GetFC], Environment USING [PageCount, wordsPerPage], Error USING [ErrorFile, WrongSymbolsVersion], FileTable USING [Build, Destroy, HandleForFile, UnknownFile], ModuleSymbols USING [], PackageSymbols, PackagerDefs USING [globalData], PrincOps USING [BytePC], SourceBcd USING [ bcdBases, bcdHeader, EnumerateModules, ModuleNum, ModuleNumForMti], Space: TYPE USING [ Handle, nullHandle, virtualMemory, CopyIn, Create, Delete, LongPointer, Map], String USING [SubString], SymbolPack, Symbols USING [HTIndex, HTNull, HTRecord], SymbolSegment USING [STHeader, VersionID], SymbolTable USING [Base], Table USING [Base]; ModuleSymbolsImpl: PROGRAM IMPORTS CIFS, Error, FileTable, PackagerDefs, SourceBcd, Space, ownSymbolPack: SymbolPack EXPORTS ModuleSymbols = BEGIN OPEN ModuleSymbols; InvalidSymbols: PUBLIC ERROR = CODE; SymbolsProblem: PUBLIC SIGNAL = CODE; symSeg: Space.Handle ← Space.nullHandle; symSegSize: Environment.PageCount ← 0; header: LONG POINTER TO SymbolSegment.STHeader ← NIL; symbolPackStarted: BOOL ← FALSE; nullFile: CIFS.OpenFile = NIL; SymbolInfoMap: TYPE = RECORD [ SEQUENCE length: CARDINAL OF KnownSymbolsInfo]; KnownSymbolsInfo: TYPE = RECORD [ loadedBefore: BOOL, file: CIFS.OpenFile, base, pages: CARDINAL]; knownSymbols: LONG POINTER TO SymbolInfoMap ← NIL; -- NB: the REFs here are protected by FileTableImpl outerPackArray: PUBLIC LONG DESCRIPTOR FOR ARRAY OF PackageSymbols.OuterPackRecord; innerPackArray: PUBLIC LONG DESCRIPTOR FOR ARRAY OF PackageSymbols.InnerPackRecord; constArray: PUBLIC LONG DESCRIPTOR FOR ARRAY OF PackageSymbols.ConstRecord; loadCodeOffsetTable: PUBLIC PackageSymbols.PCSeq; loadCodeByteOffsetTable: PUBLIC PackageSymbols.PCSeq; jumpIndirectTable: PUBLIC PackageSymbols.JISeq; Load: PUBLIC PROC [mti: BcdDefs.MTIndex] = { ENABLE UNWIND => Unload[]; sgi: BcdDefs.SGIndex = SourceBcd.bcdBases.mtb[mti].sseg; fti: BcdDefs.FTIndex = SourceBcd.bcdBases.mtb[mti].file; mNum: SourceBcd.ModuleNum; -- known information about module mti base, pSymPages: CARDINAL; file: CIFS.OpenFile; codeVersion: BcdDefs.VersionStamp; PagesForWords: PROC [nWords: CARDINAL] RETURNS [Environment.PageCount] = INLINE BEGIN RETURN [(nWords + (Environment.wordsPerPage-1))/Environment.wordsPerPage] END; SELECT fti FROM BcdDefs.FTNull => {SIGNAL SymbolsProblem; RETURN}; BcdDefs.FTSelf => codeVersion ← SourceBcd.bcdHeader.version; ENDCASE => codeVersion ← SourceBcd.bcdBases.ftb[fti].version; IF sgi = BcdDefs.SGNull THEN {SIGNAL SymbolsProblem; RETURN}; mNum ← SourceBcd.ModuleNumForMti[mti]; [base: base, pages: pSymPages, file: file] ← knownSymbols[mNum]; IF pSymPages > symSegSize THEN GrowSeg[minPages: pSymPages]; symSeg.CopyIn[window: [file: file.GetFC, base: base]]; IF ~knownSymbols[mNum].loadedBefore THEN { IF header.version # codeVersion THEN { Error.WrongSymbolsVersion[ class: error, module: mti, requiredVersion: codeVersion, actualVersion: header.version]; Unload[]; ERROR InvalidSymbols}; pSymPages ← PagesForWords[header.constBlock.offset + header.constBlock.size]; IF pSymPages > symSegSize THEN GrowSeg[minPages: pSymPages]; symSeg.CopyIn[window: [file: file.GetFC, base: base]]; knownSymbols[mNum].pages ← pSymPages; knownSymbols[mNum].loadedBefore ← TRUE}; InstallTable[ownSymbolPack ! ANY => Unload[]]}; Unload: PUBLIC PROC = { outerPackArray ← NIL; innerPackArray ← NIL; constArray ← NIL; loadCodeOffsetTable ← NIL; loadCodeByteOffsetTable ← NIL; jumpIndirectTable ← NIL}; InstallTable: PROC [base: SymbolTable.Base] = { b: LONG POINTER = LOOPHOLE[header]; tB: Table.Base = LOOPHOLE[b]; pCard: LONG POINTER TO CARDINAL; IF header.versionIdent # SymbolSegment.VersionID THEN ERROR InvalidSymbols; base.cacheInfo ← NIL; base.hashVec ← b + header.hvBlock.offset; base.ht ← DESCRIPTOR[ b + header.htBlock.offset, header.htBlock.size/SIZE[Symbols.HTRecord]]; base.ssb ← b + header.ssBlock.offset; base.stHandle ← header; base.sourceFile ← NIL; base.notifier ← base.NullNotifier; outerPackArray ← DESCRIPTOR[ b + header.outerPackBlock.offset, (header.outerPackBlock.size / SIZE[PackageSymbols.OuterPackRecord])]; innerPackArray ← DESCRIPTOR[ b + header.innerPackBlock.offset, (header.innerPackBlock.size / SIZE[PackageSymbols.InnerPackRecord])]; pCard ← LOOPHOLE[b + header.constBlock.offset]; constArray ← DESCRIPTOR[pCard+1, pCard↑]; loadCodeOffsetTable ← LOOPHOLE[pCard + 1 + pCard↑ * SIZE[PackageSymbols.ConstRecord]]; loadCodeByteOffsetTable ← LOOPHOLE[loadCodeOffsetTable + 1 + loadCodeOffsetTable.length * SIZE[PrincOps.BytePC]]; jumpIndirectTable ← LOOPHOLE[loadCodeByteOffsetTable + 1 + loadCodeByteOffsetTable.length * SIZE[PrincOps.BytePC]]}; FindProc: PUBLIC PROC [ ss: String.SubString] RETURNS [opi: PackageSymbols.OPIndex] = { hti: Symbols.HTIndex = ownSymbolPack.FindString[ss]; l, u, i: PackageSymbols.OPIndex; IF hti = Symbols.HTNull THEN RETURN[PackageSymbols.OPNull]; l ← 1; u ← (LENGTH[outerPackArray] - 1); WHILE l <= u DO i ← CARDINAL[l+u]/2; SELECT outerPackArray[i].hti FROM > hti => u ← i-1; < hti => l ← i+1; ENDCASE => RETURN[i]; ENDLOOP; RETURN[PackageSymbols.OPNull]}; Initialize: PUBLIC PROC [nModules: CARDINAL] = { FillInKnowledge: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOL←FALSE] = { mNum: SourceBcd.ModuleNum = SourceBcd.ModuleNumForMti[mti]; sgi: BcdDefs.SGIndex; base: CARDINAL; file: CIFS.OpenFile ← nullFile; IF SourceBcd.bcdBases.mtb[mti].tableCompiled THEN -- ignore any symbols knownSymbols[mNum] ← [loadedBefore: FALSE, file: nullFile, base: 0, pages: 0] ELSE { sgi ← SourceBcd.bcdBases.mtb[mti].sseg; base ← SourceBcd.bcdBases.sgb[sgi].base; file ← FileTable.HandleForFile[SourceBcd.bcdBases.sgb[sgi].file ! FileTable.UnknownFile => { Error.ErrorFile[ error, "was needed for symbols but could not be found"L, fti]; CONTINUE} ]; knownSymbols[mNum] ← [loadedBefore: FALSE, file: file, base: base, pages: 1]}; RETURN}; FileTable.Build[]; CreateSeg[]; knownSymbols ← PackagerDefs.globalData.zone.NEW[SymbolInfoMap[nModules]]; SourceBcd.EnumerateModules[FillInKnowledge]; IF ~symbolPackStarted THEN {START ownSymbolPack; symbolPackStarted ← TRUE}}; Finalize: PUBLIC PROC = { Unload[]; IF knownSymbols # NIL THEN { FOR i: CARDINAL IN [0..knownSymbols.length) DO knownSymbols[i].file ← nullFile; ENDLOOP; PackagerDefs.globalData.zone.FREE[@knownSymbols]}; FileTable.Destroy[]; DestroySeg[]}; -- Input segment operations CreateSeg: PROC = { IF symSeg # Space.nullHandle THEN ERROR SymbolsProblem; symSegSize ← 30; symSeg ← Space.Create[size: symSegSize, parent: Space.virtualMemory]; -- file: NIL, release: [], -- fileBase: 0, pages: symSegSize, swapInfo: [uniform[size: 3]]]; symSeg.Map[]; header ← symSeg.LongPointer}; GrowSeg: PROC [minPages: Environment.PageCount] = { Space.Delete[symSeg]; symSegSize ← ((minPages+2)/3 * 3); symSeg ← Space.Create[size: symSegSize, parent: Space.virtualMemory]; -- MSegment.Reset[ -- segment: symSeg, pages: symSegSize, swapInfo: [uniform[size: 4]]]; symSeg.Map[]; header ← symSeg.LongPointer}; DestroySeg: PROC = { IF symSeg # Space.nullHandle THEN { Space.Delete[symSeg]; symSeg ← Space.nullHandle; symSegSize ← 0; header ← NIL}}; END.