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