<<>> <> <> <> <> <> <> <> <> <> <> DIRECTORY Basics USING [Card32FromF, FWORD], Commander USING[CommandProc, Register], CommanderOps USING[ArgumentVector, Parse], Convert USING[CardFromRope, IntFromRope, RopeFromCard], ObjectFiles USING[BracketNest, BracketPairKind, BracketProc, CGrammar, FunInfo, GlobalVarLoc, Module, ModuleInfo, NameAndNumber, NoFileSegmentPC, noFSeg, Parsed, PCRange, FileSegmentPC, Stab, StabType, SymbolProc, UnreadableObjectFile, VarLoc, VarLocBody, VersionStampInfo], ObjectFilesPrivate USING[BracketConsumer, BracketFinisher, BracketPair, BracketPairBody, FnConsumer, FnFinisher, FunHandleBody, FunStabInfo, FunStabSet, FunStabSetBody, GetTypeRefProcType, Header, HeaderBody, LineNumToPCMap, LineNumToPCMapBody, ModuleBody, ObjectFileFlavor, ParsedBody, PCtoLineNumMap, PCtoLineNumMapBody, SLineData, StabList, StabSet, TranslationTable, TranslationTableBody], IO USING[card, Close, GetChar, GetIndex, PutF, PutF1, PutFL, PutFLR, PutFR, PutFR1, PutRope, rope, SetIndex, STREAM, UnsafeGetBlock], PFS USING [PathFromRope, RopeFromPath, StreamOpen], PFSNames USING [PATH, ShortName, ComponentRope, EmptyPath, Equal], Rope USING[Cat, Concat, Equal, Fetch, Find, Index, IsEmpty, IsPrefix, Length, NewText, ROPE, Substr, Text], SGI USING [WireTables, UnPackLineNumbers], SystemInterface USING[CirioFile, CloseFileSet, CreateFileSet, FileSet, GetCirioFile, GetNameOfFile, GetStreamForFile, ReleaseStreamForFile, ShowReport]; ObjectFilesImpl: CEDAR MONITOR IMPORTS Basics, Commander, CommanderOps, Convert, IO, ObjectFiles, PFS, PFSNames, Rope, SystemInterface, SGI EXPORTS ObjectFiles, ObjectFilesPrivate = { <> PATH: TYPE ~ PFSNames.PATH; ROPE: TYPE ~ Rope.ROPE; <> <<>> Parsed: TYPE ~ REF ParsedBody; ParsedBody: PUBLIC TYPE ~ ObjectFilesPrivate.ParsedBody; Module: TYPE ~ REF ModuleBody; ModuleBody: PUBLIC TYPE ~ ObjectFilesPrivate.ModuleBody; ModuleInfo: TYPE ~ ObjectFiles.ModuleInfo; <<>> Header: TYPE ~ REF HeaderBody; HeaderBody: TYPE ~ ObjectFilesPrivate.HeaderBody; FileSegmentPC: TYPE ~ ObjectFiles.FileSegmentPC; Stab: TYPE ~ ObjectFiles.Stab; StabType: TYPE ~ ObjectFiles.StabType; StabList: TYPE ~ ObjectFilesPrivate.StabList; StabSet: TYPE ~ ObjectFilesPrivate.StabSet; BracketConsumer: TYPE ~ ObjectFilesPrivate.BracketConsumer; BracketFinisher: TYPE ~ ObjectFilesPrivate.BracketFinisher; FnConsumer: TYPE ~ ObjectFilesPrivate.FnConsumer; FnFinisher: TYPE ~ ObjectFilesPrivate.FnFinisher; <<>> <> <<>> FlavorSeq: TYPE = RECORD[SEQUENCE length: CARD OF ObjectFilesPrivate.ObjectFileFlavor]; translationTable: ObjectFilesPrivate.TranslationTable ¬ NIL; registry: REF FlavorSeq _ NEW[FlavorSeq[0]]; OFFFromStream: PUBLIC PROC[stream: IO.STREAM] RETURNS [ROPE] ~ { index: INT; ValueFromStream: PROC [num: CARD] RETURNS [val: CARD] = { val ¬ 0; IO.SetIndex[stream, translationTable[num].byteOffset]; FOR j: CARD IN [0..translationTable[num].length) DO val ¬ (val * 256) + ORD[IO.GetChar[stream]]; ENDLOOP; }; IF stream = NIL THEN RETURN["stream was NIL, so no OFF rope was returned."]; IF translationTable = NIL THEN RETURN["table of OFF's was NIL."]; index ¬ IO.GetIndex[stream]; FOR i: CARD IN [0..translationTable.length) DO IF translationTable[i].type = middle OR translationTable[i].type = last THEN LOOP; IF ValueFromStream[i] = translationTable[i].compareValue THEN { IF translationTable[i].type = point THEN { IO.SetIndex[stream, index]; RETURN[translationTable[i].format]; }; FOR cont: CARD IN [i+1..translationTable.length) DO IF ValueFromStream[cont] # translationTable[cont].compareValue THEN EXIT; IF translationTable[cont].type = last THEN { IO.SetIndex[stream, index]; RETURN[translationTable[cont].format]; }; ENDLOOP; }; ENDLOOP; IO.SetIndex[stream, index]; RETURN["No OFF rope for object File."]; }; RegisterObjectFileFlavor: PUBLIC PROC[flavor: ObjectFilesPrivate.ObjectFileFlavor, table: ObjectFilesPrivate.TranslationTable ¬ NIL] ~ { i: CARD; IF (i ¬ RetrieveObjectFileFlavorInner[flavor.formatSpecificString]) # LAST[CARD] THEN registry[i] ¬ flavor ELSE { newR: REF FlavorSeq ¬ NEW[FlavorSeq[registry.length+1]]; FOR i IN [0..registry.length) DO newR[i] ¬ registry[i]; ENDLOOP; newR[registry.length] ¬ flavor; registry ¬ newR; }; IF table # NIL THEN { newTT: ObjectFilesPrivate.TranslationTable ¬ NIL; IF translationTable = NIL THEN translationTable ¬ NEW[ObjectFilesPrivate.TranslationTableBody[table.length]] ELSE { newLen: CARD ¬ translationTable.length + table.length; newTT ¬ translationTable; translationTable ¬ NEW[ObjectFilesPrivate.TranslationTableBody[newLen]]; FOR i: CARD IN [0..newTT.length) DO translationTable[i+table.length] ¬ newTT[i]; ENDLOOP; }; FOR i: CARD IN [0..table.length) DO translationTable[i] ¬ table[i]; ENDLOOP; }; }; RetrieveObjectFileFlavor: PUBLIC PROC[formatSpecificString: ROPE] RETURNS[flavor: ObjectFilesPrivate.ObjectFileFlavor] ~ { i:CARD ¬ RetrieveObjectFileFlavorInner[formatSpecificString]; IF i # LAST[CARD] THEN RETURN [registry[i]] ELSE ERROR; }; RetrieveObjectFileFlavorInner: PROC[formatSpecificString: ROPE] RETURNS[registryIndex: CARD] ~ { FOR i: CARD IN [0 .. registry.length) DO IF Rope.Equal[formatSpecificString, registry[i].formatSpecificString] THEN RETURN [i]; ENDLOOP; RETURN[LAST[CARD]]}; <> <<>> CreateParsed: PUBLIC ENTRY PROC[f: SystemInterface.CirioFile, fs: ROPE ¬ NIL, targetData: REF ANY _ NIL] RETURNS[Parsed] = { ENABLE UNWIND => NULL; parsed: Parsed ¬ NEW[ParsedBody]; stream: IO.STREAM ¬ SystemInterface.GetStreamForFile[f]; parsed.file ¬ f; parsed.targetData ¬ targetData; IF fs = NIL THEN fs ¬ OFFFromStream[stream]; parsed.formatSpecificString ¬ fs; parsed.cGrammar ¬ RetrieveObjectFileFlavor[parsed.formatSpecificString].cGrammar; parsed.header ¬ RetrieveObjectFileFlavor[parsed.formatSpecificString].readHeaderProc[stream]; parsed.stabLimit ¬ parsed.header.nEntries; SystemInterface.ReleaseStreamForFile[f, stream]; RETURN[parsed]; <> <> }; GetObjectFile: PUBLIC PROC[whole: Parsed] RETURNS[SystemInterface.CirioFile] = {IF whole = NIL THEN RETURN[NIL] ELSE RETURN[whole.file]}; GetFormatString: PUBLIC PROC[whole: Parsed] RETURNS[ROPE] ~ { {IF whole = NIL THEN RETURN[NIL] ELSE RETURN[whole.formatSpecificString]}; }; <<>> <<>> <> <<>> GetModule: PUBLIC PROC[info: ModuleInfo] RETURNS[Module] = { IF info.whole = NIL THEN RETURN[NIL] ELSE <> FOR mods: LIST OF Module ¬ info.whole.modules, mods.rest WHILE mods # NIL DO IF PFSNames.Equal[mods.first.fileName, info.fileName] AND mods.first.instance = info.instance THEN RETURN[mods.first]; ENDLOOP; RETURN[NIL]; }; GetModuleInfo: PUBLIC PROC[module: Module] RETURNS[REF ModuleInfo] = { ENABLE UnreadableObjectFile => GOTO fails; IF module = NIL THEN RETURN[NIL]; RETURN[NEW[ModuleInfo¬[ whole: IF module.moduleWhole = NIL THEN module.whole ELSE module.moduleWhole, fileName: module.fileName, instance: module.instance ]]]; EXITS fails => RETURN[NIL]; }; <<>> <> <<>> ModuleFromParsedAndPC: PUBLIC PROC [whole: Parsed, spc: FileSegmentPC, moduleRope: ROPE ¬ NIL] RETURNS [Module] ~ { IF whole = NIL THEN RETURN[NIL] ELSE RETURN[RetrieveObjectFileFlavor[whole.formatSpecificString].moduleFromParsedAndPCProc[whole: whole, spc: spc, moduleRope: moduleRope]]; }; <> <<>> FindVersionStamp: PUBLIC PROC[module: Module] RETURNS[REF ObjectFiles.VersionStampInfo] = { IF module = NIL THEN RETURN[NIL]; InstallStaticVars[module]; RETURN[module.versionStampInfo]; }; FindGlobalFrameVar: PUBLIC PROC[module: Module] RETURNS[ObjectFiles.GlobalVarLoc] = { IF module = NIL THEN RETURN[NIL]; InstallStaticVars[module]; RETURN[module.globalFrameGvl] }; InstallStaticVars: PROC[module: Module] ~ { RetrieveObjectFileFlavor[module.whole.formatSpecificString].installStaticVarsProc[module]; }; UnreadableDotO: PUBLIC ERROR[msg: ROPE] = CODE; VarLocFromStab: PUBLIC PROC [stab: Stab] RETURNS [ObjectFiles.VarLoc ¬ NIL] ~ { RETURN[RetrieveObjectFileFlavor[stab.module.whole.formatSpecificString].varLocFromStabProc[stab]]; }; GetTypeRef: PUBLIC PROC[module: Module, sourceStream: IO.STREAM] RETURNS [ROPE]~ { RETURN[RetrieveObjectFileFlavor[module.whole.formatSpecificString].getTypeRefProc[sourceStream]]; }; MakeUnknownVarLoc: PUBLIC PROC [why: ROPE] RETURNS [ObjectFiles.VarLoc] ~ { RETURN [NEW [ObjectFiles.VarLocBody ¬ [bitSize: 8 -- should this be unspecdBitSize?? , indirect: FALSE--, where: unknown[why] ]]]}; CheckStaticVar: PUBLIC PROC[stab: Stab, namePrefix: ROPE, allowSuffix: BOOL] RETURNS [ObjectFiles.VarLoc] = { foundName: ROPE; foundStab: Stab; [foundName, foundStab] ¬ CheckStaticStab[stab, namePrefix, allowSuffix]; IF foundStab = NIL THEN RETURN[NIL]; RETURN VarLocFromStab[stab]}; <> CheckStaticStab: PROC[stab: Stab, namePrefix: ROPE, allowSuffix: BOOL] RETURNS[foundName: ROPE, foundStab: Stab] = { namePrefixLen: CARD = namePrefix.Length[]; text: ROPE ¬ ReadStabRope[stab]; length: CARD ¬ Rope.Length[text]; IF Rope.IsPrefix[namePrefix, text] THEN -- possible hit { <> FOR J: CARD IN [namePrefixLen..length) DO char: CHAR ¬ Rope.Fetch[text, J]; IF char = ': THEN -- bingo RETURN [text.Substr[len: J], stab]; IF char < '0 OR char > '9 OR NOT allowSuffix THEN EXIT; -- non digit ENDLOOP; }; RETURN[NIL, NIL]; }; <<>> <> ReadInstruction: PUBLIC PROC[module: Module, spc: FileSegmentPC] RETURNS[inst: CARD] = { IF module = NIL THEN RETURN[0] ELSE { buffer: Basics.FWORD; stream: IO.STREAM ¬ SystemInterface.GetStreamForFile[module.whole.file]; IO.SetIndex[stream, module.whole.header.text.byteOffset+spc.relPC]; TRUSTED{[] ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[LONG[@buffer]], 0, 4]]}; SystemInterface.ReleaseStreamForFile[module.whole.file, stream]; RETURN[Basics.Card32FromF[buffer]]; }; }; GetSPOffset: PUBLIC PROC[module: Module, spc: FileSegmentPC] RETURNS[INT] = { IF module = NIL THEN RETURN[0] ELSE RETURN[RetrieveObjectFileFlavor[module.whole.formatSpecificString].getSPOffsetProc[module, spc]]; }; <> ReadInitialDataAsRope: PUBLIC PROC[module: Module, fileByteOffset: CARD] RETURNS[ROPE] = { rope: ROPE; stream: IO.STREAM ¬ SystemInterface.GetStreamForFile[module.whole.file]; { ENABLE UNWIND => SystemInterface.ReleaseStreamForFile[module.whole.file, stream]; IO.SetIndex[stream, fileByteOffset]; rope ¬ ReadRope[stream]; }; SystemInterface.ReleaseStreamForFile[module.whole.file, stream]; RETURN[rope]; }; <> <<>> FunHandle: TYPE = REF FunHandleBody; FunHandleBody: PUBLIC TYPE = ObjectFilesPrivate.FunHandleBody; FunInfo: TYPE = ObjectFiles.FunInfo; <> GenFuns: PUBLIC PROC[module: Module, for: PROC[FunHandle] RETURNS[--stop-- BOOLEAN]] = { IF module = NIL THEN RETURN; InstallFunStabs[module]; FOR I: CARD IN [0..module.funStabs.nFunStabs) DO IF for[module.funStabs[I].funHandle] THEN EXIT; ENDLOOP; }; GetFunInfo: PUBLIC PROC[fun: FunHandle] RETURNS[FunInfo] = { funIndex: CARD ¬ fun.index; module: Module ¬ fun.module; stab: Stab ¬ module.funStabs[funIndex].stab; cName: ROPE ¬ CNameOfStab[stab]; firstPC: CARD ¬ stab.value; nextIndex: CARD ¬ funIndex+1; limitPC: CARD ¬ IF nextIndex = module.funStabs.nFunStabs THEN module.limitPC ELSE module.funStabs[nextIndex].stab.value; RETURN[[stab, cName, [firstPC, limitPC]]]; }; GetFunBrackets: PUBLIC PROC[fun: FunHandle] RETURNS[BracketPair] = { funIndex: CARD ¬ fun.index; module: Module ¬ fun.module; IF NOT module.funStabs[funIndex].bracketsScanned THEN InstallBracketPairsForOneFunStab[module, funIndex]; RETURN[module.funStabs[funIndex].brackets]; }; <<>> <> BracketPair: TYPE = REF BracketPairBody; BracketPairBody: PUBLIC TYPE = ObjectFilesPrivate.BracketPairBody; BracketNest: TYPE = ObjectFiles.BracketNest; BracketPairKind: TYPE = ObjectFiles.BracketPairKind; FunStabSet: TYPE = ObjectFilesPrivate.FunStabSet; FunStabSetBody: TYPE = ObjectFilesPrivate.FunStabSetBody; FunStabInfo: TYPE = ObjectFilesPrivate.FunStabInfo; SymbolProc: TYPE = ObjectFiles.SymbolProc; BracketProc: TYPE = ObjectFiles.BracketProc; <> GenOtherSymbolStabs: PUBLIC PROC[module: Module, for: SymbolProc] = {GenSymbolStabs[GetOuterBracketPair[module], for]}; GenFunBracketPairs: PUBLIC PROC[module: Module, for: BracketProc] = { IF module = NIL THEN RETURN; InstallFunStabs[module]; FOR I: CARD IN [0..module.funStabs.nFunStabs) DO InstallBracketPairsForOneFunStab[module, I]; <> IF for[module.funStabs[I].brackets] THEN EXIT; ENDLOOP; }; GetOuterBracketPair: PUBLIC PROC[module: Module] RETURNS[BracketPair] = {IF module = NIL THEN RETURN[NIL] ELSE RETURN[module.outerBracket]}; GetFunStab: PUBLIC PROC[bp: BracketPair] RETURNS[Stab] = {IF bp = NIL OR bp.kind # syntheticFun THEN RETURN[NIL] ELSE RETURN[bp.funStab]}; GetFunHandle: PUBLIC PROC[bp: BracketPair] RETURNS[FunHandle] = { InstallFunStabs[bp.module]; IF bp = NIL OR bp.kind # syntheticFun THEN RETURN[NIL] ELSE RETURN[bp.module.funStabs[bp.funIndex].funHandle]; }; GetFunHandleFromNest: PUBLIC PROC[nest: BracketNest] RETURNS[FunHandle] = {RETURN[IF nest = NIL OR nest.rest = NIL THEN NIL ELSE GetFunHandle[nest.rest.first]]}; GetBracketPairKind: PUBLIC PROC[bp: BracketPair] RETURNS[BracketPairKind] = {IF bp = NIL THEN RETURN[nil] ELSE RETURN[bp.kind]}; GetPCRange: PUBLIC PROC[bp: BracketPair] RETURNS[ObjectFiles.PCRange] = {IF bp = NIL THEN RETURN[[0, 0]] ELSE RETURN[[bp.firstPC, bp.pcLimit]]}; <> <<{IF bp = NIL THEN RETURN[[0, 0]] ELSE RETURN[[bp.firstX, bp.limitX-bp.firstX]]};>> GenSubBracketPairs: PUBLIC PROC[bp: BracketPair, for: BracketProc] = { IF bp = NIL THEN RETURN; IF (bp.kind = syntheticFun OR bp.kind = actual) AND NOT bp.module.funStabs[bp.funIndex].bracketsScanned THEN InstallBracketPairsForOneFunStab[bp.module, bp.funIndex]; FOR bps: LIST OF BracketPair ¬ bp.innerBrackets, bps.rest WHILE bps # NIL DO IF for[bps.first] THEN EXIT; ENDLOOP; }; <> GenSymbolStabs: PUBLIC PROC[bp: BracketPair, for: SymbolProc] = { IF bp = NIL THEN RETURN; {module: Module ~ bp.module; SELECT bp.kind FROM syntheticFun, actual => { IF NOT module.funStabs[bp.funIndex].bracketsScanned THEN <> UnreadableObjectFile[IO.PutFR1["unscanned actual or syntheticFun bp in %g", [rope[DescribeModule[module]]] ]]; FOR stabs: StabList ¬ bp.symbols, stabs.rest WHILE stabs # NIL DO IF for[stabs.first] THEN EXIT; ENDLOOP; RETURN}; syntheticOuter => { IF Rope.Equal[module.whole.formatSpecificString, "XCOFF"] THEN { stabX: CARD ¬ module.firstStabX; limitX: CARD ¬ module.funStabs.firstX; FOR i: CARDINAL IN [stabX-module.firstStabX .. limitX-module.firstStabX) DO stab: Stab ~ module.stabs[i]; IF stab.stabType#SLine AND for[stab] THEN RETURN; ENDLOOP; FOR fsi: CARD IN [0..module.funStabs.nFunStabs) DO funStab: Stab ¬ AlterFunStab[module, fsi]; IF for[funStab] THEN RETURN; ENDLOOP; RETURN} ELSE { stabX: CARD ¬ module.firstStabX; fsi: CARDINAL ¬ 0; WHILE stabX < module.limitStabX DO limitX, newX: CARD ¬ module.limitStabX; funStabX: CARD ¬ LAST[CARD]; funStab: Stab ¬ NIL; IF fsi> limitX ¬ module.funStabs[fsi].firstX; newX ¬ limitX + module.funStabs[fsi].count; fsi ¬ fsi.SUCC; IF fsi> stabX ¬ newX; ENDLOOP; RETURN};}; nil => ERROR--MJS August 22, 1990: there are no nil bps--; ENDCASE => ERROR; }}; AlterFunStab: PROC [module: Module, funStabX: CARD] RETURNS [Stab] ~ { IF module = NIL THEN RETURN[NIL] ELSE RETURN[RetrieveObjectFileFlavor[module.whole.formatSpecificString].alterFunStabProc[module, funStabX]]; }; GetBracketNestForPC: PUBLIC PROC[module: Module, spc: FileSegmentPC] RETURNS[BracketNest] = { IF module = NIL THEN RETURN[NIL]; InstallFunStabs[module]; FOR I: CARD IN [0..module.funStabs.nFunStabs) DO <> IF I+1 = module.funStabs.nFunStabs OR spc.relPC < module.funStabs[I+1].stab.value THEN -- we have the function {innerNest: BracketNest; InstallBracketPairsForOneFunStab[module, I]; {fsi: FunStabInfo ~ module.funStabs[I]; IF fsi.brackets=NIL THEN UnreadableObjectFile[IO.PutFLR[ "Lack (cached) of brackets for relPC %g(%xH) in %g, probably in procedure %g", LIST[[cardinal[spc.relPC]], [cardinal[spc.relPC]], [rope[PFS.RopeFromPath[module.fileName]]], [rope[IF fsi.stab#NIL THEN fsi.stab.rope ELSE "?NIL stab?"]]] ]]; innerNest ¬ FindBracketNestInBracketPair[fsi.brackets, spc]; RETURN[CONS[module.outerBracket, CONS[fsi.brackets, innerNest]]]; }}; ENDLOOP; RETURN[LIST[module.outerBracket]]; }; FindBracketNestInBracketPair: PROC[bp: BracketPair, spc: FileSegmentPC] RETURNS[BracketNest] = { FOR subBpis: LIST OF BracketPair ¬ bp.innerBrackets, subBpis.rest WHILE subBpis # NIL DO IF spc.relPC < subBpis.first.firstPC THEN RETURN[NIL]; IF spc.relPC < subBpis.first.pcLimit THEN RETURN[CONS[subBpis.first, FindBracketNestInBracketPair[subBpis.first, spc]]]; ENDLOOP; RETURN[NIL]; }; StabRecList: TYPE = LIST OF StabRec; StabRec: TYPE = RECORD[i, count, nextX: CARD, stab, firstLocal: Stab]; InsertFunStabSorted: PROCEDURE [list: StabRecList, stab: StabRec] RETURNS [StabRecList]~ { IF list = NIL THEN RETURN[LIST[stab]] ELSE IF stab.stab.value > list.first.stab.value THEN RETURN[CONS[stab, list]] ELSE RETURN[CONS[list.first, InsertFunStabSorted[list.rest, stab]]]; }; ScanModuleStructure: PUBLIC PROC [module: Module, perFn: FnConsumer] ~ { flavor: ObjectFilesPrivate.ObjectFileFlavor ~ RetrieveObjectFileFlavor[module.whole.formatSpecificString]; flavor.scanModuleStructure[module, perFn]; RETURN}; ScanFnStructure: PUBLIC PROC [ module: Module, funStab: Stab, firstLocal: Stab _ NIL, nextX: CARD, perParm: PROC [Stab] _ NIL, perBracket: BracketConsumer _ NIL ] RETURNS [limitX, limitPc: CARD] ~ { flavor: ObjectFilesPrivate.ObjectFileFlavor ~ RetrieveObjectFileFlavor[module.whole.formatSpecificString]; RETURN flavor.scanFnStructure[module, funStab, firstLocal, nextX, perParm, perBracket]}; ScanBracketStructure: PUBLIC PROC [ module: Module, funStab: Stab, first: Stab, perLocal: PROC [Stab] _ NIL, perSubBracket: BracketConsumer _ NIL ] RETURNS [limitX, firstPc, limitPc: CARD] ~ { flavor: ObjectFilesPrivate.ObjectFileFlavor ~ RetrieveObjectFileFlavor[module.whole.formatSpecificString]; RETURN flavor.scanBktStructure[module, funStab, first, perLocal, perSubBracket]}; InstallFunStabs: PROC[module: Module] = { flavor: ObjectFilesPrivate.ObjectFileFlavor ~ RetrieveObjectFileFlavor[module.whole.formatSpecificString]; fnsOrderedByStart: BOOL ~ flavor.fnsOrderedByStart; funStabs: StabRecList ¬ NIL; nFunStabs: CARD ¬ 0; index: CARD; nextX: CARD ¬ module.limitStabX; firstFunStabX: CARD ¬ LAST[CARD]; funStabSet: FunStabSet; IF module.funStabsInstalled THEN RETURN; IF flavor.scanModuleStructure=NIL THEN { privX: CARD ¬ LAST[CARD]; FOR I: CARD IN [0..module.stabs.nStabs) DO stab: Stab ¬ module.stabs[I]; IF stab.module = NIL THEN LOOP; IF stab.stabType = Fun THEN { IF firstFunStabX = LAST[CARD] THEN firstFunStabX ¬ stab.stabX; IF privX # LAST[CARD] THEN { funStabs ¬ InsertFunStabSorted[funStabs, [nFunStabs, I - privX, 0, module.stabs[privX], NIL]]; nFunStabs ¬ nFunStabs+1; }; privX ¬ I; }; ENDLOOP; IF privX # LAST[CARD] THEN { funStabs ¬ InsertFunStabSorted[funStabs, [nFunStabs, module.stabs.nStabs - privX, 0, module.stabs[privX], NIL]]; nFunStabs ¬ nFunStabs+1; }; } ELSE { NoteFn: PROC [funStab: Stab, firstLocal: Stab _ NIL, nextX: CARD] RETURNS [limitX: CARD] ~ { IF nFunStabs=0 THEN firstFunStabX _ funStab.stabX; limitX _ ScanFnStructure[module, funStab, firstLocal, nextX, NIL, NIL].limitX; funStabs _ InsertFunStabSorted[funStabs, [nFunStabs, limitX - funStab.stabX, nextX, funStab, firstLocal]]; nFunStabs ¬ nFunStabs+1; RETURN}; ScanModuleStructure[module, NoteFn]; }; funStabSet ¬ NEW[FunStabSetBody[nFunStabs]]; funStabSet.firstX ¬ firstFunStabX; index ¬ nFunStabs-1; FOR stabs: StabRecList ¬ funStabs, stabs.rest WHILE stabs # NIL DO firstX: CARD ¬ stabs.first.stab.stabX; handle: FunHandle ¬ NEW[FunHandleBody¬[module, index --stabs.first.i--]]; IF fnsOrderedByStart AND nextX <= firstX THEN UnreadableObjectFile[IO.PutFR["bug in InstallFunStabs at %g'th fun in %g", [cardinal[stabs.first.i]], [rope[DescribeModule[module]]] ]]; funStabSet[index --stabs.first.i--] ¬ [stabs.first.stab, firstX, stabs.first.count, stabs.first.firstLocal, stabs.first.nextX, handle, FALSE, NIL]; nextX ¬ firstX; index ¬ index - 1; ENDLOOP; module.funStabs ¬ funStabSet; module.funStabsInstalled ¬ TRUE; RETURN}; InstallBracketPairsForOneFunStab: PROC [module: Module, funStabIndex: CARD] ~ { flavor: ObjectFilesPrivate.ObjectFileFlavor ~ RetrieveObjectFileFlavor[module.whole.formatSpecificString]; fsi: FunStabInfo ~ module.funStabs[funStabIndex]; funStab: Stab ~ fsi.stab; fbp: BracketPair; parmsTail: StabList _ NIL; innerBracketsTail: LIST OF BracketPair _ NIL; NoteParm: PROC [stab: Stab] ~ {[fbp.symbols, parmsTail] _ AppendStabToList[stab, fbp.symbols, parmsTail]}; NoteTopBlock: PROC [first: Stab] RETURNS [limitX: CARD] ~ { bp: BracketPair; this: LIST OF BracketPair; [bp, limitX] _ MakeBracket[first]; this _ LIST[bp]; IF innerBracketsTail=NIL THEN fbp.innerBrackets _ this ELSE innerBracketsTail.rest _ this; innerBracketsTail _ this; RETURN}; MakeBracket: PROC [first: Stab] RETURNS [bp: BracketPair, limitX: CARD] ~ { localsTail: StabList _ NIL; innerTail: LIST OF BracketPair _ NIL; AddLocal: PROC [stab: Stab] ~ {[bp.symbols, localsTail] _ AppendStabToList[stab, bp.symbols, localsTail]}; AddChild: PROC [first: Stab] RETURNS [limitX: CARD] ~ { sub: BracketPair; this: LIST OF BracketPair; [sub, limitX] _ MakeBracket[first]; this _ LIST[sub]; IF innerTail#NIL THEN innerTail.rest _ this ELSE bp.innerBrackets _ this; innerTail _ this}; bp _ NEW [BracketPairBody _ [ module: module, kind: actual, firstX: first.stabX, limitX: 0, firstPC: 0, pcLimit: 0, funStab: funStab, funIndex: funStabIndex, symbols: NIL, innerBrackets: NIL]]; [bp.limitX, bp.firstPC, bp.pcLimit] _ ScanBracketStructure[module, funStab, first, AddLocal, AddChild]; RETURN [bp, bp.limitX]}; IF module.funStabs[funStabIndex].bracketsScanned THEN RETURN; module.funStabs[funStabIndex].bracketsScanned _ TRUE; -- if error occurs, then we won't do this again. IF flavor.installBracketPairsForOneFunStabProc#NIL THEN { flavor.installBracketPairsForOneFunStabProc[module, funStabIndex]; RETURN}; module.funStabs[funStabIndex].brackets _ fbp _ NEW[BracketPairBody_[ module: module, kind: syntheticFun, firstX: funStab.stabX, limitX: 0, firstPC: funStab.value, pcLimit: 0, funStab: funStab, funIndex: funStabIndex, symbols: NIL, innerBrackets: NIL]]; [fbp.limitX, fbp.pcLimit] _ ScanFnStructure[module, fsi.stab, fsi.firstLocal, fsi.nextX, NoteParm, NoteTopBlock]; IF fbp.innerBrackets#innerBracketsTail --more than one bracket-- THEN { tbp: BracketPair ~ NEW[BracketPairBody_[ module: module, kind: actual, firstX: fbp.innerBrackets.first.firstX, limitX: innerBracketsTail.first.limitX, firstPC: fbp.innerBrackets.first.firstPC, pcLimit: innerBracketsTail.first.pcLimit, funStab: funStab, funIndex: funStabIndex, symbols: NIL, innerBrackets: fbp.innerBrackets]]; fbp.innerBrackets _ LIST[tbp]}; RETURN}; AppendStabToList: PROC [elt: Stab, head, tail: StabList] RETURNS [StabList, StabList] ~ { this: StabList ~ LIST[elt]; IF tail#NIL THEN tail.rest _ this ELSE head _ this; RETURN [head, this]}; <> ScanSymbolStabs: PUBLIC PROC[module: Module, firstX: CARD, head, tail: StabList] RETURNS[--nextX-- CARD, --head, tail of collected symbols-- StabList, StabList] = {x: CARD ¬ firstX; WHILE x < module.limitStabX DO stab: Stab ¬ ReadStab[module, x]; IF stab = NIL THEN LOOP; SELECT stab.stabType FROM LBrac, RBrac, Fun, GSym, STSym, LCSym => RETURN[x, head, tail]; SLine => NULL; -- we ignore SLines ENDCASE => { -- we simply collect all others as potentially interesting to our clients symbol: StabList ¬ LIST[stab]; IF head#NIL AND stab=head.first THEN ERROR; IF head = NIL THEN head ¬ symbol ELSE tail.rest ¬ symbol; tail ¬ symbol}; x ¬ x+1; ENDLOOP; <> RETURN[x, head, tail]}; <<>> <> LineNumToPCMap: TYPE ~ ObjectFilesPrivate.LineNumToPCMap; LineNumToPCMapBody : TYPE ~ ObjectFilesPrivate.LineNumToPCMapBody; <> <<>> PCtoLineNumMap: TYPE ~ REF PCtoLineNumMapBody; PCtoLineNumMapBody: TYPE ~ ObjectFilesPrivate.PCtoLineNumMapBody; <> SLineData: TYPE = ObjectFilesPrivate.SLineData; <> <> <> <> <> <> <> <> <<>> <> <> <> <<>> <, that the compiler is processing CLine, and that its "nextPC" variable is PC. It may be that no instructions are actually generated until we get to another CLine.>> GetPCForLineNum: PUBLIC PROC[module: Module, cLineNum: CARD] RETURNS[FileSegmentPC] = TRUSTED BEGIN map: LineNumToPCMap; IF module = NIL THEN RETURN[ObjectFiles.NoFileSegmentPC]; IF module.lineNumToPC = NIL THEN { IF Rope.Equal[module.whole.formatSpecificString, "SGI"] THEN { <> stream: IO.STREAM ¬ SystemInterface.GetStreamForFile [module.whole.file]; parsed: Parsed ¬ LOOPHOLE[module.whole, Parsed]; wireTables: SGI.WireTables ¬ NARROW[parsed.privateInfo, SGI.WireTables]; SGI.UnPackLineNumbers[stream, module, wireTables]; } ELSE ERROR; }; map ¬ module.lineNumToPC; FOR I: CARDINAL IN [0..map.nSlines) DO IF map[I].cLineNum >= cLineNum THEN RETURN[map[I].parsedRelPC]; ENDLOOP; IF map.nSlines # 0 THEN RETURN[[ObjectFiles.noFSeg, module.limitPC]]; RETURN[ObjectFiles.NoFileSegmentPC]; -- probably no dbx stabs END; <> <> GetLineNumForPC: PUBLIC PROC[module: Module, spc: FileSegmentPC] RETURNS[CARD] = TRUSTED BEGIN map: PCtoLineNumMap; IF module = NIL THEN RETURN[0]; IF module.pcToLineNum = NIL THEN { IF Rope.Equal[module.whole.formatSpecificString, "SGI"] THEN { <> stream: IO.STREAM ¬ SystemInterface.GetStreamForFile [module.whole.file]; parsed: Parsed ¬ LOOPHOLE[module.whole, Parsed]; wireTables: SGI.WireTables ¬ NARROW[parsed.privateInfo, SGI.WireTables]; SGI.UnPackLineNumbers[stream, module, wireTables]; } ELSE ERROR; }; map ¬ module.pcToLineNum; FOR I: CARDINAL DECREASING IN [0..map.nSlines) DO IF map[I].parsedRelPC.relPC <= spc.relPC THEN RETURN[map[I].cLineNum]; ENDLOOP; IF map.nSlines # 0 THEN RETURN[map[0].cLineNum]; RETURN[0]; -- probably no dbx stabs END; <<>> <> <<>> <> ReadStab: PUBLIC PROC[module: Module, stabX: CARD] RETURNS[Stab] = { IF module=NIL THEN RETURN[NIL]; IF stabX >= module.limitStabX THEN ObjectFiles.UnreadableObjectFile[IO.PutFR["Attempt to fetch stab (%g) beyond limit (%g) from %g", [cardinal[stabX]], [cardinal[module.limitStabX]], [rope[PFS.RopeFromPath[module.fileName]]] ]]; RETURN[module.stabs[stabX- module.firstStabX]]; }; <<>> ReadStabRope: PUBLIC ENTRY PROC [stab: Stab] RETURNS [rope: ROPE] ~ { ENABLE UNWIND => NULL; IF stab=NIL THEN RETURN[NIL] ELSE RETURN[stab.rope]}; CNameOfStab: PUBLIC PROC[stab: Stab] RETURNS[rope: ROPE] = { ENABLE UNWIND => NULL; rope: ROPE ¬ ReadStabRope[stab]; SELECT stab.stabType FROM Fun, PSym, LSym, RSym, GSym, LCSym, STSym => { colPos: INT ¬ Rope.Find[rope, ":"]; IF colPos < 0 THEN RETURN[rope] ELSE RETURN[Rope.Substr[rope, 0, colPos]]; }; ENDCASE => RETURN[rope]; }; CGrammarOfStab: PUBLIC PROC[stab: Stab] RETURNS[ObjectFiles.CGrammar] ~ { IF stab # NIL AND stab.module # NIL AND stab.module.whole # NIL THEN RETURN[stab.module.whole.cGrammar] ELSE RETURN [UNKNOWN] }; <> <<>> RopeBufferSize: CARD = 100; RopeBuffer: REF PACKED ARRAY [0..RopeBufferSize) OF CHAR ¬ NEW[PACKED ARRAY [0..RopeBufferSize) OF CHAR]; <> ReadRope: PROC[s: IO.STREAM] RETURNS[rope: ROPE] = BEGIN ENABLE UNWIND => NULL; rope: ROPE ¬ NIL; WHILE TRUE DO start: CARD ¬ 0; end: CARD ¬ RopeBufferSize; -- tentative nChars: CARD; rt: Rope.Text; TRUSTED{[] ¬ IO.UnsafeGetBlock[s, [LOOPHOLE[@RopeBuffer­], 0, RopeBufferSize]]}; <> <<>> <> IF NOT rope.IsEmpty AND RopeBuffer[0] = '\000 THEN EXIT; <> FOR I: CARD IN [0..RopeBufferSize) DO IF RopeBuffer[I] = '\000 THEN LOOP ELSE {start ¬ I; EXIT}; ENDLOOP; <> FOR I: CARD IN [start..RopeBufferSize) DO IF RopeBuffer[I] = '\000 THEN {end ¬ I; EXIT}; ENDLOOP; nChars ¬ end - start; rt ¬ Rope.NewText[nChars]; FOR I: CARD IN [0..nChars) DO rt[I] ¬ RopeBuffer[start + I] ENDLOOP; rope ¬ IF rope = NIL THEN (IF nChars = 0 THEN "" ELSE rt) ELSE (IF nChars = 0 THEN rope ELSE Rope.Concat[rope, rt]); IF end < RopeBufferSize THEN EXIT; ENDLOOP; RETURN[rope]; END; <<>> <> <<{>> < NULL;>> <> <> <> <> <<>> <> <<>> <> <> <> <<>> RopeForBracketPair: PUBLIC PROC[bp: BracketPair] RETURNS[ROPE] = {IF bp = NIL THEN RETURN[NIL] ELSE RETURN[Rope.Cat["<", Convert.RopeFromCard[bp.firstX], ", ", Convert.RopeFromCard[bp.limitX], ">"]]}; <<>> <> <> <> PrintModule: Commander.CommandProc = { args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; name: ROPE ¬ args[1]; type: ROPE ¬ IF args.argc < 4 THEN NIL ELSE args[3]; path: PATH ¬ PFS.PathFromRope[name]; outPath: PATH ¬ PrintFileName[path]; outFile: IO.STREAM ¬ PFS.StreamOpen[outPath, create]; fileSet: SystemInterface.FileSet ¬ SystemInterface.CreateFileSet[]; { ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; file: SystemInterface.CirioFile ¬ SystemInterface.GetCirioFile[fileSet, path]; whole: Parsed ¬ CreateParsed[file, type]; relativePC: CARD ¬ IF args.argc < 3 THEN 0 ELSE Convert.CardFromRope[args[2]]; <> <> module: Module ¬ ModuleFromParsedAndPC[whole, [[0, ""], relativePC]]; IO.PutF[outFile, "Module details for %g embedding at relative pc: %g\N\N", IO.rope[name], IO.card[relativePC]]; IO.PutF[outFile, "textSize: %g, nEntries: %g\N", IO.card[whole.header.text.byteLength], IO.card[whole.header.nEntries]]; IO.PutF1[cmd.out, "\Ndetails being written to %g\N\N", IO.rope[PFS.RopeFromPath[outPath]]]; FOR x: CARD IN [0..module.stabs.nStabs) DO stab: Stab; rope: ROPE; fields: ROPE; stab ¬ ReadStab[module, module.firstStabX+x]; IF stab = NIL THEN LOOP; rope ¬ ReadStabRope[stab]; fields ¬ RopeForStabFields[stab]; IO.PutF1[outFile, "%g\N", IO.rope[fields]]; IF Rope.Length[rope] # 0 THEN IO.PutF1[outFile, " %g\N", IO.rope[rope]]; IO.PutRope[outFile, "\N"]; ENDLOOP; }; SystemInterface.CloseFileSet[fileSet]; IO.Close[outFile]; IO.PutF1[cmd.out, "\Ndetails written to %g\N\N", IO.rope[PFS.RopeFromPath[outPath]]]; }; RopeForStabFields: PROC[stab: Stab] RETURNS[ROPE] = { fields: ROPE ¬ NIL; fields ¬ Rope.Concat[fields, IO.PutFR1["stabX: %g, ", IO.card[stab.stabX]]]; fields ¬ Rope.Concat[fields, IO.PutFR1["stabType: %g, ", IO.rope[RopeForStabType[stab.stabType]]]]; fields ¬ Rope.Concat[fields, IO.PutFR1["size: %g, ", IO.card[stab.size]]]; fields ¬ Rope.Concat[fields, IO.PutFR1["value: %g, ", IO.card[stab.value]]]; <> RETURN[fields]; }; RopeForStabType: PUBLIC PROC[stabType: StabType] RETURNS[ROPE] = { RETURN[SELECT stabType FROM BIncl => "BIncl", EIncl => "EIncl", Excl => "Excl", Fun => "Fun", GSym => "GSym", Invalid => "Invalid", LBrac => "LBrac", LCSym => "LCSym", LSym => "LSym", Main => "Main", PSym => "PSym", RBrac => "RBrac", RSym => "RSym", SLine => "SLine", SO => "SO", SOL => "SOL", STSym => "STSym", Unspecified => "Unspecified", ENDCASE => ""]; }; PrintFileName: PROC[filePath: PATH] RETURNS[PATH] = { stemRope: ROPE ¬ filePath.ShortName.ComponentRope; length: INT ¬ Rope.Length[stemRope]; firstDot: INT ¬ Rope.Find[stemRope, ".", 1]; RETURN[PFS.PathFromRope[Rope.Concat[Rope.Substr[stemRope, 0, firstDot], ".ObjectFileDetails"]]]; }; <> <<(note: stab indices are only approx plus or minus 1)>> <<>> ShowModuleFunctions: Commander.CommandProc = { args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; path: PATH ¬ PFS.PathFromRope[args[1]]; type: ROPE ¬ IF args.argc < 4 THEN NIL ELSE args[3]; fileSet: SystemInterface.FileSet ¬ SystemInterface.CreateFileSet[]; { ENABLE { UNWIND => SystemInterface.CloseFileSet[fileSet]; SystemInterface.ShowReport => { cmd.out.PutF["%g: %g\n", [atom[priority]], [rope[msgText]] ]; RESUME}; }; file: SystemInterface.CirioFile ¬ SystemInterface.GetCirioFile[fileSet, path]; whole: Parsed ¬ CreateParsed[file, type]; relativePC: CARD ¬ IF args.argc < 3 THEN 0 ELSE Convert.CardFromRope[args[2]]; module: Module ¬ ModuleFromParsedAndPC[whole, [[0, NIL], relativePC]]; ShowOne: PROC[fun: FunHandle] RETURNS[--stop-- BOOLEAN] = { info: FunInfo ¬ GetFunInfo[fun]; bp: BracketPair ¬ GetFunBrackets[fun]; IO.PutFL[cmd.out, "%g\N\Tx: [%g..%g), pc: [%g..%g)\N", LIST[IO.rope[info.cName], IO.card[bp.firstX], IO.card[bp.limitX], IO.card[bp.firstPC], IO.card[bp.pcLimit]] ]; RETURN[FALSE]; }; IO.PutF[cmd.out, "Module functions for %g embedding at relative pc = %g\N\N", IO.rope[PFS.RopeFromPath[path]], IO.card[relativePC]]; GenFuns[module, ShowOne]; }; }; <> <<(note: stab indices are only approx plus or minus 1, depending on whether one is dealing with a synthetic fun bracket or a real bracket. Recall that the symbols stabs are not even between the brackets anyway, so no one should be looking at these values.)>> ShowOneModuleFunction: Commander.CommandProc = { args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; path: PATH ¬ PFS.PathFromRope[args[1]]; type: ROPE ¬ IF args.argc < 4 THEN NIL ELSE args[3]; fileSet: SystemInterface.FileSet ¬ SystemInterface.CreateFileSet[]; BEGIN ENABLE { UNWIND => SystemInterface.CloseFileSet[fileSet]; SystemInterface.ShowReport => { cmd.out.PutF["%g: %g\n", [atom[priority]], [rope[msgText]] ]; RESUME}; }; file: SystemInterface.CirioFile ¬ SystemInterface.GetCirioFile[fileSet, path]; whole: Parsed ¬ CreateParsed[file, type]; relativePC: CARD ¬ IF args.argc < 3 THEN 0 ELSE Convert.CardFromRope[args[2]]; module: Module ¬ ModuleFromParsedAndPC[whole, [[0, ""], relativePC]]; bn: BracketNest ¬ GetBracketNestForPC[module, [[0, ""], relativePC]]; funbp: BracketPair ¬ bn.rest.first; IO.PutF[cmd.out, "\NOne Module function for %g embedding at relative pc = %g\N\N", IO.rope[PFS.RopeFromPath[path]], IO.card[relativePC]]; IO.PutF1[cmd.out, "%g\N", IO.rope[CNameOfStab[funbp.funStab]]]; Showbps[cmd.out, 5, funbp]; END; }; Showbps: PROC[on: IO.STREAM, depth: INT, bp: BracketPair] = { tab: PROC[plus: CARD] = {FOR I: CARD IN [0..depth+plus) DO IO.PutRope[on, " "] ENDLOOP}; tab[0]; IO.PutFL[on, "{ x: [%g..%g), pc: [%g..%g)\N", LIST[IO.card[bp.firstX], IO.card[bp.limitX], IO.card[bp.firstPC], IO.card[bp.pcLimit]] ]; FOR symbols: StabList ¬ bp.symbols, symbols.rest WHILE symbols # NIL DO ShowStab[on, depth, symbols.first]; ENDLOOP; FOR innerbps: LIST OF BracketPair ¬ bp.innerBrackets, innerbps.rest WHILE innerbps # NIL DO Showbps[on, depth+5, innerbps.first]; ENDLOOP; tab[0]; IO.PutRope[on, "}\N\N"]; }; ShowStab: PROC[on: IO.STREAM, depth: CARD, stab: Stab] = { fields: ROPE ¬ RopeForStabFields[stab]; text: ROPE ¬ ReadStabRope[stab]; FOR I: CARD IN [0..depth) DO IO.PutRope[on, " "] ENDLOOP; IO.PutF1[on, "%g\N", IO.rope[fields]]; IF Rope.Length[text] # 0 THEN { FOR I: CARD IN [0..depth+2) DO IO.PutRope[on, " "] ENDLOOP; IO.PutF1[on, "%g\N", IO.rope[text]]; }; IO.PutRope[on, "\N"]; }; <> <<>> ShowModuleGlobalStabs: Commander.CommandProc = { args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; path: PATH ¬ PFS.PathFromRope[args[1]]; type: ROPE ¬ IF args.argc < 4 THEN NIL ELSE args[3]; fileSet: SystemInterface.FileSet ¬ SystemInterface.CreateFileSet[]; { ENABLE { UNWIND => SystemInterface.CloseFileSet[fileSet]; SystemInterface.ShowReport => { cmd.out.PutF["%g: %g\n", [atom[priority]], [rope[msgText]] ]; RESUME}; }; file: SystemInterface.CirioFile ¬ SystemInterface.GetCirioFile[fileSet, path]; whole: Parsed ¬ CreateParsed[file, type]; relativePC: CARD ¬ IF args.argc < 3 THEN 0 ELSE Convert.CardFromRope[args[2]]; module: Module ¬ ModuleFromParsedAndPC[whole, [[0, ""], relativePC]]; ReportStab: PROC [stab: Stab] RETURNS [--stop-- BOOLEAN] ~ { IF stab.module#NIL THEN ShowStab[cmd.out, 5, stab]; RETURN [FALSE]}; IO.PutF[cmd.out, "\NModule global stabs for %g embedding at relative pc = %g\N\N", IO.rope[PFS.RopeFromPath[path]], IO.card[relativePC]]; InstallFunStabs[module]; GenOtherSymbolStabs[module, ReportStab]; }; }; CheckModuleBrackets: Commander.CommandProc = { args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; path: PATH ¬ PFS.PathFromRope[args[1]]; type: ROPE ¬ IF args.argc < 4 THEN NIL ELSE args[3]; fileSet: SystemInterface.FileSet ¬ SystemInterface.CreateFileSet[]; { ENABLE { UNWIND => SystemInterface.CloseFileSet[fileSet]; SystemInterface.ShowReport => { cmd.out.PutF["%g: %g\n", [atom[priority]], [rope[msgText]] ]; RESUME}; }; file: SystemInterface.CirioFile ¬ SystemInterface.GetCirioFile[fileSet, path]; whole: Parsed ¬ CreateParsed[file, type]; relativePC: CARD ¬ IF args.argc < 3 THEN 0 ELSE Convert.CardFromRope[args[2]]; module: Module ¬ ModuleFromParsedAndPC[whole, [[0, ""], relativePC]]; CheckOne: PROC[fun: FunHandle] RETURNS[--stop-- BOOLEAN] = { info: FunInfo ¬ GetFunInfo[fun]; funBPI: BracketPair ¬ GetFunBrackets[fun]; RETURN[FALSE]; }; IO.PutF[cmd.out, "\Nchecking Module brackets for %g embedding at relative pc = %g\N\N", IO.rope[PFS.RopeFromPath[path]], IO.card[relativePC]]; GenFuns[module, CheckOne]; }; }; <> <> <> <> <<>> UnreadableObjectFile: PUBLIC ERROR[msg: ROPE] = CODE; RaiseUnreadableObjectFileForFun: PUBLIC PROC[msg: ROPE, module: Module, fun: Stab] = { funName: ROPE ¬ IF fun = NIL THEN NIL ELSE CNameOfStab[fun]; UnreadableObjectFile[IO.PutFR["%g in function: %g of %g", [rope[msg]], [rope[funName]], [rope[DescribeModule[module]]] ]]; }; RaiseUnreadableObjectFileForModule: PROC[msg: ROPE, stabX: CARD, module: Module] = { UnreadableObjectFile[IO.PutFR["%g at stabX: %g in %g", [rope[msg]], [cardinal[stabX]], [rope[DescribeModule[module]]] ]]; }; DescribeModule: PUBLIC PROC [module: Module] RETURNS [ROPE] ~ { moduleName: PATH ~ IF module = NIL THEN PFSNames.EmptyPath ELSE module.fileName; wholeName: PATH ~ IF module = NIL OR module.whole = NIL OR module.whole.file = NIL THEN PFSNames.EmptyPath ELSE SystemInterface.GetNameOfFile[module.whole.file]; RETURN IO.PutFR["module: %g of objectFile: %g", [rope[PFS.RopeFromPath[moduleName]]], [rope[PFS.RopeFromPath[wholeName]]] ]}; <<>> <
> <<>> Commander.Register["PrintModule", PrintModule, "usage:\N\TPrintModule name relPC [format]\N\Twhere\N\T\Tname is file name of the containing whole object file\N\T\TrelPC is a containingWhole-relative PC within the module\N\T\Tformat is XCOFF or SunADotOut"]; Commander.Register["ShowModuleFunctions", ShowModuleFunctions, "usage:\N\TShowModuleFunctions name relPC [format]\N\Twhere\N\T\Tname is file name of the containing whole object file\N\T\TrelPC is a containingWhole-relative PC within the module\N\T\Tformat is XCOFF or SunADotOut"]; Commander.Register["ShowOneModuleFunction", ShowOneModuleFunction, "usage:\N\TShowOneModuleFunction name relPC [format]\N\Twhere\N\T\Tname is file name of the containing whole object file\N\T\TrelPC is a containingWhole-relative PC within the module\N\T\Tformat is XCOFF or SunADotOut"]; Commander.Register["ShowModuleGlobalStabs", ShowModuleGlobalStabs, "usage:\N\TShowModuleGlobalStabs name relPC [format]\N\Twhere\N\T\Tname is file name of containing whole object file\N\T\TrelPC is a containingWhole-relative PC within the module\N\T\Tformat is XCOFF or SunADotOut"]; Commander.Register["CheckModuleBrackets", CheckModuleBrackets, "usage:\N\TCheckModuleBrackets name relPC [format]\N\Twhere\N\T\Tname is file name of containing whole object file\N\T\TrelPC is a containingWhole-relative PC within the module\N\T\Tformat is XCOFF or SunADotOut"]; <<>> }..