-- 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.