-- DSymTab.Mesa Edited by: -- Bruce June 10, 1980 6:58 PM -- Sandman May 5, 1980 6:02 PM DIRECTORY BcdDefs USING [ Base, BCD, FTNull, FTSelf, MTIndex, NullVersion, SGIndex, SGNull, VersionID, VersionStamp], BcdOps USING [ BcdBase, FTHandle, MTHandle, NameString, ProcessModules, SGHandle], ComData, CompilerUtil USING [PassIndex, PrefillSymbols], Copier, DebugOps, DI USING [ResetLongs], DOutput USING [Blanks, Char, Text], DSyms, Frames USING [Invalid], Gf USING [Check, File, Frame, GFI, Name, Original], LiteralOps USING [Initialize], LoadStateOps USING [ AcquireBcd, ConfigIndex, InputLoadState, LoadStateInvalid, MapRealToConfig, NullConfig, ReleaseBcd, ReleaseLoadState], Lookup, MachineDefs, Pc, SegmentDefs USING [ DefaultAccess, DeleteFileSegment, FileError, FileNameError, FileHandle, FileSegmentHandle, FileSegmentAddress, MoveFileSegment, NewFile, NewFileSegment, OldFileOnly, PageNumber, Read, SwapIn, SwapOut, Unlock, VMtoFileSegment], Storage: FROM "storage", String USING [ AppendString, AppendSubString, SubString, SubStringDescriptor], SymbolOps USING [EnterString, Initialize, Reset], SymbolPack, Symbols USING [ BTIndex, HTIndex, HTNull, IncludedCTXNull, MDIndex, MDNull, mdType, MDRecord, OwnMdi, RootBti], SymbolSegment: FROM "symbolsegment", SymbolTable: FROM "symboltable" USING [Base, Missing], Table: FROM "table", TreeOps: FROM "TreeOps" USING [Initialize]; DSymTab: PROGRAM IMPORTS BcdOps, data: ComData, CompilerUtil, Copier, DebugOps, DI, DOutput, Frames, Gf, LiteralOps, LoadStateOps, Lookup, SegmentDefs, Storage, String, SymbolOps, SymbolPack, SymbolTable, Table, TreeOps EXPORTS CompilerUtil, DSyms = BEGIN OPEN DSyms, MachineDefs; Head: Item _ NIL; s: STRING _ NIL; NoFGT: PUBLIC ERROR = CODE; CantAttach: ERROR = CODE; SymbolTableProblem: ERROR = CODE; MakeSwappable: PUBLIC PROC[module:PROGRAM, pass:CompilerUtil.PassIndex]={}; FreeItems: PUBLIC PROCEDURE = BEGIN OPEN SegmentDefs, SymbolTable; syms, next: Item; FOR syms _ Head, next UNTIL syms = NIL DO next _ syms.link; Storage.Free[syms]; ENDLOOP; Copier.CopierReset[]; Copier.FileReset[]; Copier.FileInit["XDebug"L, BcdDefs.NullVersion]; Copier.CopierInit[FALSE]; Copier.CreateFileTable[16]; Head _ NIL; END; CleanItems: PUBLIC PROCEDURE = BEGIN syms, next, prev: Item; prev _ NIL; FOR syms _ Head, next UNTIL syms = NIL DO next _ syms.link; IF syms.table = NIL THEN BEGIN IF prev = NIL THEN Head _ next ELSE prev.link _ next; Storage.Free[syms]; END ELSE prev _ syms; ENDLOOP; END; Enumerate: PUBLIC PROC [proc: PROCEDURE [Item] RETURNS [BOOLEAN]] RETURNS [syms: Item] = BEGIN last: Item; FOR syms _ Head, syms.link UNTIL syms = NIL DO IF proc[syms] THEN BEGIN IF syms = Head THEN RETURN; last.link _ syms.link; syms.link _ Head; Head _ syms; RETURN END; last _ syms; ENDLOOP; END; FindMod: PUBLIC PROC [name: HTIndex] RETURNS [Item] = BEGIN OPEN Symbols; mdb: Table.Base; length: CARDINAL; mdi: MDIndex; [mdb,length] _ Table.Bounds[Symbols.mdType]; FOR mdi _ OwnMdi, mdi+SIZE[MDRecord] UNTIL LOOPHOLE[mdi,CARDINAL] = length DO IF mdb[mdi].moduleId = name THEN RETURN[FindMdi[mdi]]; ENDLOOP; RETURN[NIL]; END; FindMdi: PUBLIC PROC [mdi: MDIndex] RETURNS [Item] = BEGIN Find: PROC [d: Item] RETURNS[BOOLEAN] = BEGIN WITH sym: d SELECT FROM hash => RETURN[FALSE]; mod => RETURN[mdi = sym.mdi]; ENDCASE => ERROR; END; RETURN[Enumerate[Find]]; END; FindFrame: PUBLIC PROC [gf: MachineDefs.GFHandle] RETURNS [i: Item] = BEGIN Find: PROC [d: Item] RETURNS[BOOLEAN] = {RETURN[gf = d.gf]}; RETURN[Enumerate[Find]]; END; ModuleMdi: PUBLIC PROC [hti: HTIndex, fgt: BOOLEAN _ FALSE] RETURNS [MDIndex] = BEGIN syms: Item; gf: GFHandle _ NIL; mod: STRING _ [40]; Lookup.HtiToString[hti,mod]; gf _ Gf.Frame[mod ! Lookup.Fail => CONTINUE]; IF (syms _ FindMod[hti]) = NIL THEN BEGIN IF gf = NIL THEN {AttachSyms[gf,mod]; syms _ FindMod[hti]} ELSE syms _ AddItem[hti,gf]; END; SetSegment[syms,fgt]; WITH syms SELECT FROM mod => RETURN[mdi]; ENDCASE => ERROR SymbolTable.Missing[NIL]; END; GFrameMdi: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN _ FALSE] RETURNS [MDIndex] = BEGIN syms: Item; Gf.Check[gf]; IF (syms _ FindFrame[gf]) = NIL THEN syms _ AddItem[Symbols.HTNull,gf]; SetSegment[syms,fgt]; WITH syms SELECT FROM mod => RETURN[mdi]; ENDCASE => ERROR SymbolTable.Missing[NIL]; END; Stopping: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN _ FALSE] RETURNS [BOOLEAN] = BEGIN syms: Item; Gf.Check[gf]; IF (syms _ FindFrame[gf]) = NIL THEN syms _ AddItem[Symbols.HTNull,gf]; SetSegment[syms,fgt]; RETURN[syms.stopping]; END; CrossJumped: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN _ FALSE] RETURNS [BOOLEAN] = BEGIN syms: Item; Gf.Check[gf]; IF (syms _ FindFrame[gf]) = NIL THEN syms _ AddItem[Symbols.HTNull,gf]; SetSegment[syms,fgt]; RETURN[syms.crossJumped]; END; GFrameHti: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN _ FALSE] RETURNS [HTIndex] = BEGIN mdi: MDIndex _ Symbols.MDNull; i: Item; mdi _ GFrameMdi[gf,fgt !SymbolTable.Missing => CONTINUE]; IF mdi # Symbols.MDNull THEN RETURN[Table.Bounds[Symbols.mdType].base[mdi].moduleId]; i _ FindFrame[gf]; WITH i SELECT FROM hash => RETURN[hti]; ENDCASE => ERROR SymbolTableProblem; END; ModuleToHti: PUBLIC PROC [s: STRING] RETURNS [hti: Symbols.HTIndex] = BEGIN mod: STRING _ [40]; desc: String.SubStringDescriptor; String.AppendString[mod,s]; StripExtension[mod]; desc _ [base: mod, offset: 0, length: mod.length]; RETURN[SymbolOps.EnterString[@desc]]; END; HtiFromLoadState: PROC [gf: GFHandle] RETURNS [Symbols.HTIndex] = BEGIN name: STRING _ [40]; Gf.Name[name,gf]; RETURN[ModuleToHti[name]]; END; mdb: Table.Base; Notify: Table.Notifier = {mdb _ base[Symbols.mdType]}; AddItem: PROC [hti: HTIndex, gf: GFHandle] RETURNS [syms: Item] = BEGIN version: BcdDefs.VersionStamp; seg: FSHandle; jumped, fgt: BOOLEAN; [version: version, seg: seg, fgt: fgt, jumped:jumped] _ SymbolSegForFrame[gf]; syms _ CacheItem[ hti:hti, gf:gf, version:version, seg:seg, fgt:fgt, jumped:jumped]; END; CacheItem: PROC [ hti: HTIndex, gf: GFHandle, version: BcdDefs.VersionStamp, seg: FSHandle, fgt, jumped: BOOLEAN] RETURNS [syms: Item] = BEGIN mdi: Symbols.MDIndex; syms _ Storage.Node[SIZE[ItemObject]]; IF seg = NIL THEN BEGIN syms^ _ [link: Head, gf: gf, table: seg, fgtAvailable: fgt, symbol: hash[HtiFromLoadState[gf]], outerCtx: Symbols.IncludedCTXNull, directoryCtx: Symbols.IncludedCTXNull, importCtx: Symbols.IncludedCTXNull, crossJumped:jumped, stopping:]; Head _ syms; ERROR SymbolTable.Missing[NIL]; END ELSE BEGIN mdi _ Copier.EnterFileSegment[hti,version,seg]; syms^ _ [link: Head, gf: gf, table:seg, fgtAvailable:fgt, symbol: mod[mdi], outerCtx: Symbols.IncludedCTXNull, directoryCtx: Symbols.IncludedCTXNull, importCtx: Symbols.IncludedCTXNull, crossJumped:jumped, stopping:]; Head _ syms; END; Copier.Outer[mdi,EnterContexts]; Table.AddNotify[Notify]; mdb[mdi].shared _ TRUE; IF mdb[mdi].moduleId = Symbols.HTNull THEN BEGIN ssd: String.SubStringDescriptor; IF s = NIL THEN ERROR SymbolTableProblem ELSE ssd _ [base: s, length: s.length, offset: 0]; mdb[mdi].moduleId _ SymbolOps.EnterString[@ssd]; s _ Storage.FreeStringNil[s]; END; [] _ Copier.EnterFileSegment[mdb[mdi].moduleId,version,seg]; Table.DropNotify[Notify]; syms.outerCtx _ Copier.FindExternalCtx[mdi,syms.outerCtx]; syms.directoryCtx _ Copier.FindExternalCtx[mdi,syms.directoryCtx]; syms.importCtx _ Copier.FindExternalCtx[mdi,syms.importCtx]; RETURN END; SetSegment: PROC [syms: Item, fgt: BOOLEAN] = BEGIN IF ~fgt OR syms.fgtAvailable THEN RETURN; WITH syms SELECT FROM hash => ERROR SymbolTable.Missing[NIL]; mod => ERROR NoFGT; ENDCASE; END; EnterContexts: PROC [base: SymbolTable.Base] = BEGIN mdb: Table.Base _ Table.Bounds[Symbols.mdType].base; ssd: String.SubStringDescriptor; ss: String.SubString = @ssd; Head.outerCtx _ base.mainCtx; Head.directoryCtx _ base.stHandle.directoryCtx; Head.importCtx _ base.stHandle.importCtx; Head.stopping _ base.bb[Symbols.RootBti].stopping; WITH Head SELECT FROM mod => IF mdb[mdi].moduleId # Symbols.HTNull THEN RETURN; ENDCASE => ERROR SymbolTableProblem; base.SubStringForHash[ss,base.mdb[Symbols.OwnMdi].moduleId]; IF s # NIL THEN ERROR SymbolTableProblem; s _ Storage.String[ss.length]; String.AppendSubString[s,ss]; END; AttachSyms: PUBLIC PROC [gf: GFHandle, file: STRING] = BEGIN syms: Item; mod: STRING _ [40]; version: BcdDefs.VersionStamp; fgt, jumped: BOOLEAN; seg: MachineDefs.FSHandle; fh: FileHandle; String.AppendString[mod,file]; StripExtension[mod]; String.AppendString[mod,".bcd"L]; fh _ SegmentDefs.NewFile[mod,SegmentDefs.Read,SegmentDefs.OldFileOnly ! SegmentDefs.FileNameError => {SIGNAL Lookup.Fail[mod]; CONTINUE}]; IF gf # NIL AND (syms _ FindFrame[gf]) # NIL THEN {syms.table _ NIL; CleanItems[]}; [version:version, seg:seg, jumped:jumped, fgt:fgt] _ CompilerSeg[gf,fh ! CantAttach => BEGIN OPEN DOutput; Blanks[1]; Text[mod]; Text[" is a definitions file!"L]; GOTO bad END]; [] _ CacheItem[ hti:Symbols.HTNull, gf:gf, version:version, seg:seg, fgt:fgt, jumped:jumped ! SymbolTable.Missing => BEGIN OPEN DOutput; Blanks[1]; Text[mod]; Text[" does not have a valid symbol table!"L]; CONTINUE END]; DebugOps.InvalidateFileCache[]; EXITS bad => NULL END; CompilerSeg: PROC [gf: GFHandle, file: FileHandle] RETURNS [ version: BcdDefs.VersionStamp, seg: FSHandle, fgt,jumped: BOOLEAN] = BEGIN OPEN SegmentDefs; sgh: BcdOps.SGHandle; mth: BcdOps.MTHandle; sSeg: BcdDefs.SGIndex; bcdPages: CARDINAL _ 1; bcd: BcdOps.BcdBase; headerSeg: FSHandle _ NewFileSegment[file, 1, bcdPages, Read]; DO SwapIn[headerSeg]; bcd _ FileSegmentAddress[headerSeg]; IF bcd.versionIdent # BcdDefs.VersionID THEN {CleanupSeg[headerSeg]; RETURN[BcdDefs.NullVersion,NIL,FALSE,FALSE]}; IF bcdPages = bcd.nPages THEN EXIT; bcdPages _ bcd.nPages; Unlock[headerSeg]; SwapOut[headerSeg]; MoveFileSegment[headerSeg, 1, bcdPages]; ENDLOOP; IF bcd.nConfigs # 0 THEN {CleanupSeg[headerSeg]; RETURN[BcdDefs.NullVersion,NIL,FALSE,FALSE]}; IF bcd.definitions AND gf # NIL THEN {CleanupSeg[headerSeg]; ERROR CantAttach}; mth _ @LOOPHOLE[bcd+bcd.mtOffset,Table.Base][FIRST[BcdDefs.MTIndex]]; sSeg _ mth.sseg; jumped _ mth.crossJumped; sgh _ @LOOPHOLE[bcd+bcd.sgOffset,Table.Base][sSeg]; IF sSeg=BcdDefs.SGNull OR sgh.pages = 0 OR sgh.file # BcdDefs.FTSelf THEN {CleanupSeg[headerSeg]; RETURN[BcdDefs.NullVersion,NIL,FALSE,FALSE]}; version _ bcd.version; seg _ NewFileSegment[file, sgh.base, sgh.pages+sgh.extraPages, Read]; fgt _ sgh.extraPages # 0; CleanupSeg[headerSeg]; END; SymbolSegForFrame: PROCEDURE [f: GFHandle] RETURNS [ version: BcdDefs.VersionStamp, seg: FSHandle, fgt,jumped: BOOLEAN] = BEGIN OPEN LoadStateOps, SegmentDefs, BcdDefs, BcdOps; cgfi: GFTIndex; config: LoadStateOps.ConfigIndex; bcd: BcdBase; cdesc, segdesc: SGIndex; FindModule: PROCEDURE [mth: MTHandle, mti: MTIndex] RETURNS [BOOLEAN] = BEGIN IF cgfi IN [mth.gfi..mth.gfi+mth.ngfi) THEN BEGIN cdesc _ mth.code.sgi; segdesc _ mth.sseg; jumped _ mth.crossJumped; RETURN[TRUE]; END; RETURN[FALSE]; END; BEGIN f _ Gf.Original[f]; [] _ InputLoadState[ ! LoadStateInvalid => GOTO nil]; [cgfi,config] _ MapRealToConfig[Gf.GFI[f]]; IF config = NullConfig THEN ERROR Frames.Invalid[f ! UNWIND => ReleaseLoadState[]]; bcd _ AcquireBcd[config]; [] _ BcdOps.ProcessModules[bcd, FindModule]; [version: version, seg:seg, fgt: fgt] _ FindSeg[f, bcd, segdesc, cdesc ! FileNameError, FileError => {Cleanup[bcd]; GOTO nil}; UNWIND => Cleanup[bcd]]; Cleanup[bcd]; EXITS nil => RETURN[BcdDefs.NullVersion,NIL,FALSE,FALSE]; END; RETURN END; FindSeg: PROCEDURE [ frame: GFHandle, bcd: BcdOps.BcdBase, syms, code: BcdDefs.SGIndex] RETURNS [version: BcdDefs.VersionStamp, seg: FSHandle, fgt: BOOLEAN] = BEGIN OPEN SegmentDefs, BcdDefs, BcdOps; ss: String.SubStringDescriptor; tempssb: NameString; name: STRING _ [40]; file: FileHandle; symsbcd: BcdOps.BcdBase; bcdseg: FSHandle _ VMtoFileSegment[bcd]; sgb: Base _ LOOPHOLE[bcd+bcd.sgOffset]; sgh: SGHandle _ @sgb[syms]; f: FTHandle = @LOOPHOLE[bcd+bcd.ftOffset, Base][sgh.file]; BEGIN SELECT sgh.file FROM FTNull => RETURN[BcdDefs.NullVersion,NIL,FALSE]; FTSelf => BEGIN version _ f.version; seg _ NewFileSegment[bcdseg.file, sgh.base, sgh.pages+sgh.extraPages, Read]; fgt _ sgh.extraPages # 0; RETURN; END; sgb[code].file => IF (file _ Gf.File[frame]) # NIL THEN GOTO found; ENDCASE; tempssb _ LOOPHOLE[bcd+bcd.ssOffset]; ss _ [@tempssb.string, f.name, tempssb.size[f.name]]; String.AppendSubString[name, @ss]; CheckExtension[name]; file _ DebugOps.CacheNewFile[name, DefaultAccess]; EXITS found => NULL; END; seg _ NewFileSegment[file, 1, 1, Read]; SwapIn[seg]; symsbcd _ FileSegmentAddress[seg]; IF symsbcd.version # f.version THEN BEGIN IF name.length = 0 THEN DebugOps.FileName[name, file]; Unlock[seg]; DeleteFileSegment[seg]; IncorrectVersion[name]; RETURN[BcdDefs.NullVersion,NIL,FALSE]; END; Unlock[seg]; MoveFileSegment[seg, sgh.base, sgh.pages+sgh.extraPages]; version _ f.version; fgt _ sgh.extraPages # 0; RETURN; END; IncorrectVersion: PROC [name: STRING] = BEGIN OPEN DOutput; Char[' ]; Text[name]; Text[" referenced in different versions! "L]; END; StripExtension: PUBLIC PROCEDURE [name: STRING] = BEGIN i: CARDINAL; FOR i DECREASING IN [1..name.length) DO IF name[i] = '. THEN {name.length _ i; RETURN}; ENDLOOP; END; CheckExtension: PROCEDURE [s: STRING] = BEGIN i: CARDINAL; FOR i DECREASING IN [1..s.length) DO IF s[i] = '. THEN RETURN; ENDLOOP; String.AppendString[s,".bcd"L]; END; CleanupSeg: PROCEDURE [seg: FSHandle] = BEGIN SegmentDefs.Unlock[seg]; SegmentDefs.DeleteFileSegment[seg]; END; Cleanup: PROCEDURE [bcd: BcdOps.BcdBase] = BEGIN LoadStateOps.ReleaseBcd[bcd]; LoadStateOps.ReleaseLoadState[]; RETURN END; SymbolTablePages: CARDINAL = 20; SymbolTableSize: CARDINAL = SymbolTablePages*MachineDefs.PageSize; bounds: ARRAY SymbolSegment.Tables OF CARDINAL; Initialize: PUBLIC PROCEDURE = BEGIN i: Table.Selector; weights: ARRAY SymbolSegment.Tables OF CARDINAL _ ALL[1]; Table.Create[[origin: LOOPHOLE[ Storage.Pages[SymbolTablePages],CARDINAL], size: SymbolTableSize], DESCRIPTOR[weights]]; START SymbolPack; data.bodyRoot _ FIRST[Symbols.BTIndex]; data.definitionsOnly _ FALSE; SymbolOps.Initialize[]; LiteralOps.Initialize[]; TreeOps.Initialize[]; CompilerUtil.PrefillSymbols[]; Copier.FileInit["XDebug"L, BcdDefs.NullVersion]; Copier.CopierInit[FALSE]; Copier.CreateFileTable[16]; FOR i IN SymbolSegment.Tables DO bounds[i] _ Table.Bounds[i].size; ENDLOOP; END; Prune: PUBLIC PROCEDURE = BEGIN i: Table.Selector; DI.ResetLongs[]; FOR i IN SymbolSegment.Tables DO Table.Trim[i, bounds[i]]; ENDLOOP; SymbolOps.Reset[]; END; END...