<<>> <> <> <> <> <> <> <> <> <> <> DIRECTORY Atom USING[MakeAtom], BasicTime USING[GMT, Pack, Update], CardTab USING[Create, Fetch, Insert, Ref], CirioNubAccess USING[CreateRemoteNub, DestroyNub, FileEntry, GetFileEntry, Handle, LookupMatchingSymEntryByName, LookupMatchingSymEntryByValue, LookupSymEntryByID, ModuleType, PCInfo, PCtoInfo, Read32BitsAsCard, SymEntry, TextType], CirioTargets USING [Target], Commander USING[CommandProc, Register], CommandTool USING[ArgumentVector, Parse], Convert USING[CardFromRope, RopeFromCard], ObjectFiles USING[CreateParsed, GetFormatString, GetModuleInfo, Module, ModuleFromParsedAndPC, ModuleInfo, Parsed], ObjectFilesPrivate USING[StabRange], IO USING[card, PutChar, PutF, PutFR, PutRope, rope, RopeFromROS, ROS, STREAM, time], LoadStateAccess USING[BasicPCInfo, LoadedModuleInfo, LoadedSegmentsInfo], PFS USING [RopeFromPath, PathFromRope], PFSNames USING [PATH, Equal], RefTab USING[Create, Fetch, Insert, Ref], Rope USING[Cat, Equal, ROPE], SunADotOut USING[ModuleFromParsedAndStabRange], SymTab USING[Create, Fetch, Insert, Ref], SystemInterface USING[CirioFile, CirioFileInfo, CloseFileSet, CreateFileSet, FileSet, GetCirioFileFromDebuggee, GetFileInfo, GetNameOfFile, ShowReport]; <> <> <> <> <> <<>> <> <<>> <<>> <<>> LoadStateAccessImpl: CEDAR MONITOR LOCKS lsh USING lsh: LoadStateHandle IMPORTS Atom, BasicTime, CardTab, CirioNubAccess, Commander, CommandTool, Convert, IO, ObjectFiles, PFS, PFSNames, RefTab, Rope, SunADotOut, SymTab, SystemInterface EXPORTS LoadStateAccess = BEGIN OPEN ObjF: ObjectFiles; ROPE: TYPE ~ Rope.ROPE; PATH: TYPE ~ PFSNames.PATH; CirioFile: TYPE = SystemInterface.CirioFile; LoadedSegmentsInfo: TYPE = LoadStateAccess.LoadedSegmentsInfo; <<>> LoadStateHandle: TYPE = REF LoadStateHandleBody; LoadStateHandleBody: PUBLIC TYPE = MONITORED RECORD[ serverName: Rope.ROPE, nub: CirioNubAccess.Handle, fileSet: SystemInterface.FileSet, objHash: ObjectFileHashTable, addrHash: LoadedObjectFileHashTable, nameHash: ModuleNameHashTable]; CreateLoadStateHandle: PUBLIC PROC[serverName: Rope.ROPE, nub: CirioNubAccess.Handle, fileSet: SystemInterface.FileSet] RETURNS[LoadStateHandle] = BEGIN objHash: ObjectFileHashTable _ CreateObjectFileHashTable[]; addrHash: LoadedObjectFileHashTable _ CreateLoadedFileHashTable[]; nameHash: ModuleNameHashTable _ CreateNameHashTable[]; RETURN[NEW[LoadStateHandleBody_[ , serverName, nub, fileSet, objHash, addrHash, nameHash]]]; END; LoadedModule: TYPE = REF LoadedModuleBody; LoadedModuleBody: TYPE = RECORD[ loadedFile: LoadedFile, module: ObjectFiles.Module, moduleRelativeBaseAddr: CARD, -- relative to the loadedFile info: REF LoadStateAccess.LoadedModuleInfo]; LoadedFile: TYPE = REF LoadedFileBody; LoadedFileBody: TYPE = RECORD[ lsh: LoadStateHandle, loadedFileInfo: CirioNubAccess.FileEntry, packagedFile: PackagedFile, lsi: LoadedSegmentsInfo, basicInfo: REF LoadStateAccess.BasicPCInfo]; GetLoadedModuleInfoFromAbsPC: PUBLIC ENTRY PROC[lsh: LoadStateHandle, absPC: CARD, targetData: REF ANY _ NIL] RETURNS[REF LoadStateAccess.LoadedModuleInfo] = BEGIN ENABLE UNWIND => NULL; loadedModule: LoadedModule _ FindLoadedModuleFromAbsPC[lsh, absPC, targetData]; IF loadedModule = NIL THEN RETURN[NIL] ELSE RETURN[loadedModule.info]; END; <> GetLoadedModuleInfoFromStemName: PUBLIC ENTRY PROC[lsh: LoadStateHandle, moduleName: ROPE, nToSkip: CARD, targetData: REF ANY _ NIL] RETURNS[REF LoadStateAccess.LoadedModuleInfo] = { ENABLE UNWIND => NULL; target: CirioTargets.Target _ NARROW[lsh.nub.target]; moduleRope: Rope.ROPE _ moduleName; namedObjectFiles: CardTab.Ref--symID -> loadedModule-- _ NARROW[SymTab.Fetch[lsh.nameHash.table, moduleRope].val]; lookUpPattern: Rope.ROPE _ Rope.Cat[moduleRope, ".*"]; moduleEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupMatchingSymEntryByName[lsh.nub, 0, lookUpPattern, FALSE, ModuleType, 0, nToSkip]; loadedModule: LoadedModule; IF moduleEntry#NIL AND moduleEntry.symID=noSymId THEN ERROR--we said this couldn't happen--; IF namedObjectFiles = NIL THEN IF NOT SymTab.Insert[lsh.nameHash.table, moduleRope, namedObjectFiles _ CardTab.Create[3]] THEN ERROR; IF moduleEntry#NIL THEN { loadedModule _ NARROW[namedObjectFiles.Fetch[moduleEntry.symID].val]; IF loadedModule=NIL THEN BEGIN loadedFileInfo: CirioNubAccess.FileEntry _ CirioNubAccess.GetFileEntry[lsh.nub, moduleEntry.fileSeqNum]; <> nominalAbsPC: CARD _ moduleEntry.value; loadedFile: LoadedFile _ FindLoadedFile[lsh, nominalAbsPC, loadedFileInfo, targetData]; loadedModule _ GetLoadedModuleFromLoadedFile[loadedFile, nominalAbsPC + moduleEntry.size - 1, LIST[PFS.PathFromRope[moduleRope]], moduleRope]; <> <> IF NOT namedObjectFiles.Insert[moduleEntry.symID, loadedModule] THEN ERROR; END; } ELSE IF Rope.Equal[target.opSys, "SunOS5"] --AND moduleEntry=NIL-- THEN { installRope: Rope.ROPE _ Rope.Cat[target.CNameToLoaderName[target, "XR_install_"], moduleRope]; moduleEntry _ CirioNubAccess.LookupMatchingSymEntryByName[lsh.nub, 0, installRope, FALSE, TextType, 0, nToSkip]; IF moduleEntry#NIL THEN { loadedModule _ NARROW[namedObjectFiles.Fetch[moduleEntry.symID].val]; IF loadedModule=NIL THEN { loadedFileInfo: CirioNubAccess.FileEntry _ CirioNubAccess.GetFileEntry[lsh.nub, moduleEntry.fileSeqNum]; <> nominalAbsPC: CARD _ moduleEntry.value; loadedFile: LoadedFile _ FindLoadedFile[lsh, nominalAbsPC, loadedFileInfo, targetData]; loadedModule _ GetLoadedModuleFromLoadedFile[loadedFile, nominalAbsPC - 1, LIST[PFS.PathFromRope[moduleRope]], moduleRope]; <> <> IF NOT namedObjectFiles.Insert[moduleEntry.symID, loadedModule] THEN ERROR; }; }; }; IF loadedModule = NIL THEN { IF nToSkip = 0 THEN SystemInterface.ShowReport[IO.PutFR["LoadStateAccessImpl reports no loaded files with name %g", IO.rope[moduleRope]], $urgent] ELSE SystemInterface.ShowReport[IO.PutFR["LoadStateAccessImpl reports fewer than %g loaded files with name %g", IO.card[nToSkip+1], IO.rope[moduleRope]], $urgent]; RETURN[NIL]} ELSE RETURN[loadedModule.info]; }; GetRopeListForLoadedModuleInfo: PUBLIC PROC[info: REF LoadStateAccess.LoadedModuleInfo] RETURNS[LIST OF Rope.ROPE] = BEGIN IF info = NIL THEN RETURN[LIST["MISSING"]] ELSE BEGIN loadedFile: Rope.ROPE _ PFS.RopeFromPath[SystemInterface.GetNameOfFile[info.loadedFile]]; loadedFileBase: Rope.ROPE _ IO.PutFR[" loaded at %g", IO.card[info.lsi[text].base]]; moduleFiles: Rope.ROPE _ "containing"; moduleBase: Rope.ROPE _ IO.PutFR[" loaded at (object file relative) %g", IO.card[info.moduleRelativeBaseAddr]]; IF info.possibleModuleFileNames = NIL THEN moduleFiles _ Rope.Cat[moduleFiles, " an unknown file"] ELSE BEGIN moreThanOne: BOOLEAN _ FALSE; FOR names: LIST OF PATH _ info.possibleModuleFileNames, names.rest WHILE names # NIL DO IF moreThanOne THEN moduleFiles _ Rope.Cat[moduleFiles, " or"]; moduleFiles _ Rope.Cat[moduleFiles, IO.PutFR[" %g", IO.rope[PFS.RopeFromPath[names.first]]]]; moreThanOne _ TRUE; ENDLOOP; END; RETURN[LIST[loadedFile, moduleBase, moduleFiles, moduleBase]]; END; END; GetRopeListForLoadedFileContainingLoadedModule: PUBLIC PROC[info: REF LoadStateAccess.LoadedModuleInfo] RETURNS[LIST OF Rope.ROPE] = BEGIN IF info = NIL THEN RETURN[LIST["MISSING"]] ELSE BEGIN loadedFileName: Rope.ROPE _ PFS.RopeFromPath[SystemInterface.GetNameOfFile[info.loadedFile]]; stats: Rope.ROPE _ IO.PutFR["\Ts: %g, mtime: %g", IO.card[info.sizeOfLoadedFile], IO.time[info.createTimeOfLoadedFile]]; RETURN[LIST[loadedFileName, stats]]; END; END; FindLoadedModuleFromAbsPC: PROC[lsh: LoadStateHandle, absPC: CARD, targetData: REF ANY _ NIL] RETURNS[LoadedModule] = BEGIN fullInfo: FullPCInfo _ GetFullPCInfo[lsh, absPC]; pcInfo: CirioNubAccess.PCInfo _ fullInfo.pcInfo; loadedFileInfo: CirioNubAccess.FileEntry _ fullInfo.loadedFileInfo; loadedFile: LoadedFile _ FindLoadedFile[lsh, absPC, loadedFileInfo, targetData]; IF fullInfo.basicInfo = NIL THEN BEGIN SystemInterface.ShowReport[IO.PutFR["LoadStateAccessImpl reports no basic information available for absPC = %g", IO.card[absPC]], $urgent]; RETURN[NIL] END ELSE RETURN[GetLoadedModuleFromLoadedFile[loadedFile, absPC, fullInfo.basicInfo.possibleModuleNames]]; END; FullPCInfo: TYPE = RECORD[ basicInfo: REF LoadStateAccess.BasicPCInfo, pcInfo: CirioNubAccess.PCInfo, loadedFileInfo: CirioNubAccess.FileEntry]; FindLoadedFile: PROC[lsh: LoadStateHandle, absPC: CARD, fileInfo: CirioNubAccess.FileEntry, targetData: REF ANY _ NIL] RETURNS[LoadedFile] = BEGIN IF fileInfo=NIL THEN RETURN[NIL]; IF absPC < fileInfo.textReloc OR fileInfo.textReloc + fileInfo.textSize <= absPC THEN BEGIN SystemInterface.ShowReport[IO.PutFR["LoadStateAccessImpl reports that absPC = %g is possibly in some breakpoint patch area", IO.card[absPC]], $normal]; <> RETURN[NIL] END ELSE BEGIN loadedFile: LoadedFile _ NARROW[CardTab.Fetch[lsh.addrHash.table, fileInfo.textReloc].val]; -- what about zero length files?? IF loadedFile = NIL THEN -- we havn't seen it before, so we have to make it BEGIN packagedFile: PackagedFile _ FindFile[lsh, fileInfo, targetData]; basicInfo: REF LoadStateAccess.BasicPCInfo _ GetFullPCInfo[lsh, absPC].basicInfo; loadedFile _ NEW[LoadedFileBody_[lsh, fileInfo, packagedFile, LoadedSegmentsInfoFromFileEntry[fileInfo], basicInfo]]; IF NOT CardTab.Insert[lsh.addrHash.table, fileInfo.textReloc, loadedFile] THEN ERROR; END; RETURN[loadedFile]; END; END; GetBasicPCInfo: PUBLIC ENTRY PROC[lsh: LoadStateHandle, absPC: CARD] RETURNS[REF LoadStateAccess.BasicPCInfo] = {ENABLE UNWIND => NULL; RETURN[GetFullPCInfo[lsh, absPC].basicInfo]}; ModuleType: CARD = CirioNubAccess.ModuleType; TextType: CARD = CirioNubAccess.TextType; GetFullPCInfo: PROC[lsh: LoadStateHandle, absPC: CARD] RETURNS[FullPCInfo] = BEGIN pcInfo: CirioNubAccess.PCInfo _ CirioNubAccess.PCtoInfo[lsh.nub, absPC]; IF pcInfo=NIL THEN { SystemInterface.ShowReport[IO.PutFR["LoadStateAccessImpl reports no PCInfo for abs PC = %g; perhaps the incremental loader lock could not be acquired", IO.card[absPC]], $urgent]; RETURN [[NIL, NIL, NIL]]}; IF pcInfo.fileSeqNum = 0 THEN { SystemInterface.ShowReport[IO.PutFR["LoadStateAccessImpl reports no PCInfo for abs PC = %g", IO.card[absPC]], $urgent]; RETURN [[NIL, NIL, NIL]]}; {fileInfo: CirioNubAccess.FileEntry _ CirioNubAccess.GetFileEntry[lsh.nub, pcInfo.fileSeqNum]; nominalEmbeddedEntry: CirioNubAccess.SymEntry; procEntry: CirioNubAccess.SymEntry; <> IF pcInfo.guessedEmbeddedFileSymID # 0 THEN nominalEmbeddedEntry _ CirioNubAccess.LookupSymEntryByID[lsh.nub, pcInfo.guessedEmbeddedFileSymID]; procEntry _ CirioNubAccess.LookupSymEntryByID[lsh.nub, pcInfo.procSymID]; <> IF pcInfo.guessedEmbeddedFileSymID = 0 OR nominalEmbeddedEntry = NIL THEN BEGIN SystemInterface.ShowReport[IO.PutFR["LoadStateAccessImpl reports no guessedEmbeddedFile for abs PC = %g", IO.card[absPC]], $normal]; RETURN[[NIL, pcInfo, fileInfo]]; END; <> BEGIN basicInfo: REF LoadStateAccess.BasicPCInfo _ NEW[LoadStateAccess.BasicPCInfo_[ loadedFileName: pcInfo.fileName, lsi: LoadedSegmentsInfoFromFileEntry[fileInfo], possibleModuleNames: LIST[pcInfo.guessedEmbeddedFileName], -- for now moduleRelativeBaseAddr: nominalEmbeddedEntry.value-fileInfo.textReloc, procedureName: pcInfo.procName, procedureModuleRelativeBaseAddr: IF procEntry = NIL THEN 0 ELSE procEntry.value-nominalEmbeddedEntry.value]]; prevEntrySymId: CARD _ nominalEmbeddedEntry.symID; <> IF nominalEmbeddedEntry.type = CirioNubAccess.ModuleType OR nominalEmbeddedEntry.type = CirioNubAccess.ModuleType+1 THEN basicInfo.possibleModuleNames _ AddAName[PFS.PathFromRope[nominalEmbeddedEntry.name], basicInfo.possibleModuleNames] ELSE <> BEGIN anEarlierEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupMatchingSymEntryByValue[lsh.nub, prevEntrySymId, nominalEmbeddedEntry.value, ModuleType, 0, 0]; IF anEarlierEntry # NIL AND anEarlierEntry.value = nominalEmbeddedEntry.value THEN BEGIN basicInfo.possibleModuleNames _ AddAName[PFS.PathFromRope[anEarlierEntry.name], basicInfo.possibleModuleNames]; prevEntrySymId _ anEarlierEntry.symID; END; END; <> DO anEarlierEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupMatchingSymEntryByValue[lsh.nub, prevEntrySymId, nominalEmbeddedEntry.value, ModuleType, 0, -1]; IF anEarlierEntry = NIL OR anEarlierEntry.value # nominalEmbeddedEntry.value THEN EXIT; basicInfo.possibleModuleNames _ AddAName[PFS.PathFromRope[anEarlierEntry.name], basicInfo.possibleModuleNames]; prevEntrySymId _ anEarlierEntry.symID; ENDLOOP; <> prevEntrySymId _ nominalEmbeddedEntry.symID; DO aLaterEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupMatchingSymEntryByValue[lsh.nub, prevEntrySymId, nominalEmbeddedEntry.value, ModuleType, 0, 1]; IF aLaterEntry = NIL OR aLaterEntry.value # nominalEmbeddedEntry.value THEN EXIT; basicInfo.possibleModuleNames _ AddAName[PFS.PathFromRope[aLaterEntry.name], basicInfo.possibleModuleNames]; prevEntrySymId _ aLaterEntry.symID; ENDLOOP; RETURN[[basicInfo, pcInfo, fileInfo]]; END; }END; GetRopeForBasicPCInfo: PUBLIC PROC[info: REF LoadStateAccess.BasicPCInfo, absPC: CARD, ctr, pc, mo, la: BOOL] RETURNS[Rope.ROPE] = { IF info = NIL THEN RETURN["unreadable frame"]; {to: IO.STREAM ~ IO.ROS[]; to.PutRope[info.procedureName]; to.PutRope[" ("]; IF pc THEN to.PutF["pc=%xH, ", [cardinal[absPC - (info.lsi[text].base+info.moduleRelativeBaseAddr) ]] ]; to.PutRope["from"]; IF info.possibleModuleNames = NIL THEN to.PutRope[" an unknown module file"] ELSE BEGIN moreThanOne: BOOLEAN _ FALSE; FOR names: LIST OF PATH _ info.possibleModuleNames, names.rest WHILE names # NIL DO IF moreThanOne THEN to.PutRope[" or"]; to.PutChar[' ]; to.PutRope[PFS.RopeFromPath[names.first]]; moreThanOne _ TRUE; ENDLOOP; END; IF mo THEN to.PutF[" with code offset %xH", [cardinal[info.moduleRelativeBaseAddr]] ]; IF ctr THEN { to.PutRope[" in "]; to.PutRope[PFS.RopeFromPath[info.loadedFileName]]; IF la THEN to.PutF[", code loaded at %08xH", [cardinal[info.lsi[text].base]] ]}; to.PutRope[")"]; RETURN[IO.RopeFromROS[to]]}}; GetRopeListForBasicPCInfo: PUBLIC PROC[info: REF LoadStateAccess.BasicPCInfo] RETURNS[LIST OF Rope.ROPE] = BEGIN IF info = NIL THEN RETURN[LIST["unreadable frame"]] ELSE BEGIN loadedFile: Rope.ROPE _ IO.PutFR["object file %g loaded at %g", IO.rope[PFS.RopeFromPath[info.loadedFileName]], IO.card[info.lsi[text].base]]; moduleFiles: Rope.ROPE _ "containing"; loadedAt: Rope.ROPE _ IO.PutFR[" loaded at (object file relative) %g", IO.card[info.moduleRelativeBaseAddr]]; procedure: Rope.ROPE _ IO.PutFR["calling %g at (module relative) %g", IO.rope[info.procedureName], IO.card[info.procedureModuleRelativeBaseAddr]]; IF info.possibleModuleNames = NIL THEN moduleFiles _ Rope.Cat[moduleFiles, " an unknown module file"] ELSE BEGIN moreThanOne: BOOLEAN _ FALSE; FOR names: LIST OF PATH _ info.possibleModuleNames, names.rest WHILE names # NIL DO IF moreThanOne THEN moduleFiles _ Rope.Cat[moduleFiles, " or"]; moduleFiles _ Rope.Cat[moduleFiles, IO.PutFR[" %g", IO.rope[PFS.RopeFromPath[names.first]]]]; moreThanOne _ TRUE; ENDLOOP; END; RETURN[LIST[loadedFile, moduleFiles, loadedAt, procedure]]; END; END; PackagedFile: TYPE = REF PackagedFileBody; PackagedFileBody: TYPE = RECORD[ mtime: CARD, size: CARD, createTime: BasicTime.GMT, parsedFile: CirioFile, parsed: ObjectFiles.Parsed]; LoadedSegmentsInfoFromFileEntry: PROC [fileInfo: CirioNubAccess.FileEntry] RETURNS [LoadedSegmentsInfo] ~ { RETURN [[ <> text: [fileInfo.textReloc, fileInfo.textSize], data: [fileInfo.dataReloc, fileInfo.dataSize], bss: [fileInfo.bssReloc, fileInfo.bssSize] <> ]]}; FindFile: PROC[lsh: LoadStateHandle, loadedFileInfo: CirioNubAccess.FileEntry, targetData: REF ANY _ NIL] RETURNS[PackagedFile] ~ { key: ATOM _ CreateLoadedFileKey[PFS.RopeFromPath[loadedFileInfo.fileName], loadedFileInfo.mtime, loadedFileInfo.size]; packagedFile: PackagedFile _ NARROW[RefTab.Fetch[lsh.objHash.table, key].val]; mTimeAsGMT: BasicTime.GMT _ GMTFromSunTime[loadedFileInfo.mtime]; IF packagedFile = NIL THEN {--we havn't seen it before, so we have to go looking for it file: CirioFile _ SystemInterface.GetCirioFileFromDebuggee[lsh.fileSet, loadedFileInfo.fileName, lsh.serverName, [egmt: [mTimeAsGMT]] ]; parsed: ObjectFiles.Parsed _ NIL; checkedFile: CirioFile _ NIL; IF file#NIL THEN { fileInfo: SystemInterface.CirioFileInfo _ SystemInterface.GetFileInfo[file]; ConditionalCheckFile: PROC RETURNS [CirioFile] = { IF loadedFileInfo.mtime = 0 THEN RETURN[file]; -- dont check IF mTimeAsGMT # fileInfo.uniqueID.egmt.time OR loadedFileInfo.size # CARD[fileInfo.bytes] THEN RETURN[NIL]; RETURN[file]}; checkedFile _ ConditionalCheckFile[]; IF checkedFile # NIL THEN parsed _ ObjF.CreateParsed[checkedFile, NIL, targetData]; }; packagedFile _ NEW[PackagedFileBody_[loadedFileInfo.mtime, loadedFileInfo.size, mTimeAsGMT, checkedFile, parsed]]; IF NOT RefTab.Insert[lsh.objHash.table, key, packagedFile] THEN ERROR; }; RETURN[packagedFile]; }; GetLoadedModuleFromLoadedFile: PROC[loadedFile: LoadedFile, absPC: CARD, possibleNames: LIST OF PATH, moduleRope: Rope.ROPE _ NIL] RETURNS[LoadedModule] = { module: ObjF.Module _ NIL; stabRange: StabRange _ [0,0]; fastway: BOOL _ FALSE; relPC: CARD; format: Rope.ROPE _ ObjectFiles.GetFormatString[loadedFile.packagedFile.parsed]; IF format.Equal["SunADotOut"] THEN fastway _ TRUE; IF fastway THEN { stabRange _ FindStabRange[loadedFile, absPC]; IF stabRange.count # 0 THEN module _ SunADotOut.ModuleFromParsedAndStabRange[loadedFile.packagedFile.parsed, stabRange]; } ELSE { relPC _ RelativePCFromAbsolutePC[loadedFile, absPC]; module _ ObjF.ModuleFromParsedAndPC[loadedFile.packagedFile.parsed, [[0, ""], relPC], moduleRope]; }; IF module = NIL OR (fastway AND stabRange.count = 0) THEN { <> SystemInterface.ShowReport[IO.PutFR["LoadStateAccessImpl reports that the object file containing absPC = %g appears to be optimized", IO.card[absPC]], $urgent]; RETURN[NIL] }; {moduleInfo: REF ObjF.ModuleInfo _ ObjF.GetModuleInfo[module]; info: REF LoadStateAccess.LoadedModuleInfo _ IF moduleInfo = NIL THEN NIL ELSE NEW[LoadStateAccess.LoadedModuleInfo_[ loadedFile.packagedFile.mtime, loadedFile.packagedFile.size, loadedFile.packagedFile.createTime, loadedFile.packagedFile.parsedFile, loadedFile.packagedFile.parsed, loadedFile.lsi, module, possibleNames, 0 --module.startPC moduleInfo.startPC--]]; loadedModule: LoadedModule _ IF moduleInfo = NIL THEN NIL ELSE NEW[LoadedModuleBody_[loadedFile, module, 0 --moduleInfo.startPC--, info]]; IF moduleInfo # NIL AND info # NIL THEN info.possibleModuleFileNames _ AddAName[moduleInfo.fileName, info.possibleModuleFileNames]; RETURN[loadedModule]; }; }; <> <> GMTFromSunTime: PROC[sunTime: CARD] RETURNS[BasicTime.GMT] = { RETURN[BasicTime.Update[unixOrg, sunTime]]; }; unixOrg: BasicTime.GMT _ BasicTime.Pack[[1970, January, 1, 0, 0, 0, 0, no]]; AddAName: PROC[newName: PATH, names: LIST OF PATH] RETURNS[LIST OF PATH] = { FOR nms: LIST OF PATH _ names, nms.rest WHILE nms # NIL DO IF nms.first.Equal[newName] THEN RETURN[names]; ENDLOOP; RETURN[CONS[newName, names]]; }; <> ObjectFileHashTable: TYPE = REF ObjectFileHashTableBody; ObjectFileHashTableBody: TYPE = RECORD[table: RefTab.Ref]; CreateObjectFileHashTable: PROC RETURNS[ObjectFileHashTable] = {RETURN[NEW[ObjectFileHashTableBody _ [RefTab.Create[]]]]}; CreateLoadedFileKey: PROC[longPathName: Rope.ROPE, mtime: CARD, size: CARD] RETURNS[ATOM] = {RETURN[Atom.MakeAtom[Rope.Cat[Convert.RopeFromCard[mtime], Convert.RopeFromCard[size], longPathName]]]}; LoadedObjectFileHashTable: TYPE = REF LoadedObjectFileHashTableBody; LoadedObjectFileHashTableBody: TYPE = RECORD[table: CardTab.Ref]; CreateLoadedFileHashTable: PROC RETURNS[LoadedObjectFileHashTable] = {RETURN[NEW[LoadedObjectFileHashTableBody _ [CardTab.Create[]]]]}; ModuleNameHashTable: TYPE = REF ModuleNameHashTableBody; ModuleNameHashTableBody: TYPE = RECORD[table: SymTab.Ref]; CreateNameHashTable: PROC RETURNS[ModuleNameHashTable] = {RETURN[NEW[ModuleNameHashTableBody _ [SymTab.Create[]]]]}; NameEntry: TYPE = REF NameSeq; NameSeq: TYPE = RECORD [SEQUENCE nEntries: CARDINAL OF NameData]; NameData: TYPE = RECORD [symID: CARD _ noSymId, loadedModule: LoadedModule _ NIL]; noSymId: CARD = CARD.LAST; --no actual symID can have this value <> <<>> RelativePCFromAbsolutePC: PROC[loadedFile: LoadedFile, absPC: CARD] RETURNS [relPC: CARD] ~ { <> <<>> nub: CirioNubAccess.Handle _ loadedFile.lsh.nub; fileInfo: CirioNubAccess.FileEntry _ loadedFile.loadedFileInfo; pcInfo: CirioNubAccess.PCInfo _ CirioNubAccess.PCtoInfo[nub, absPC]; pcSymEntryResult: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByID[nub, pcInfo.procSymID]; procValue: CARD _ IF pcSymEntryResult = NIL THEN ERROR ELSE pcSymEntryResult.value; procedureStartRelativePC: CARD _ procValue - fileInfo.textReloc; relPC _ procedureStartRelativePC; }; StabRange: TYPE = ObjectFilesPrivate.StabRange; <> <> <> <> <> FindStabRange: PROC[loadedFile: LoadedFile, absPC: CARD] RETURNS[StabRange] = BEGIN nub: CirioNubAccess.Handle _ loadedFile.lsh.nub; fileInfo: CirioNubAccess.FileEntry _ loadedFile.loadedFileInfo; pcInfo: CirioNubAccess.PCInfo _ CirioNubAccess.PCtoInfo[nub, absPC]; pcSymEntryResult: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByID[nub, pcInfo.procSymID]; procValue: CARD _ IF pcSymEntryResult = NIL THEN ERROR ELSE pcSymEntryResult.value; procedureStartRelativePC: CARD _ procValue - fileInfo.textReloc; GroupSize: CARD = 16; nGroups: INT _ fileInfo.readerDataSize/GroupSize; x: CARD _ 0; y: CARD _ nGroups; <> IF nGroups = 0 THEN RETURN[[0, 0]]; <> BEGIN xData: StbGpEntry _ ReadOneDbxStabGroupEntry[nub, fileInfo, x]; IF procedureStartRelativePC < xData.firstPC THEN RETURN[[0, 0]]; IF procedureStartRelativePC <= xData.lastPC THEN RETURN[[xData.firstX, xData.count]]; END; <> < group[x].lastPC>> <> <<>> WHILE x+1 < y DO mid: CARD _ (x+y)/2; midData: StbGpEntry _ ReadOneDbxStabGroupEntry[nub, fileInfo, mid]; SELECT TRUE FROM procedureStartRelativePC < midData.firstPC => y _ mid; midData.firstPC <= procedureStartRelativePC AND procedureStartRelativePC <= midData.lastPC => RETURN[[midData.firstX, midData.count]]; midData.lastPC < procedureStartRelativePC => x _ mid; ENDCASE => ERROR; ENDLOOP; <<>> <> RETURN[[0, 0]]; END; StbGpEntry: TYPE = RECORD[firstX: INT, count: INT, firstPC: CARD, lastPC: CARD]; ReadOneDbxStabGroupEntry: PROC[nub: CirioNubAccess.Handle, fileInfo: CirioNubAccess.FileEntry, gpIndex: CARD] RETURNS[StbGpEntry] = BEGIN bytesForOneGroup: CARD = 16; firstAddr: CARD _ fileInfo.readerData+gpIndex*bytesForOneGroup; RETURN[[ ReadIntAtCardAddr[nub, firstAddr], ReadIntAtCardAddr[nub, firstAddr+4], ReadCardAtCardAddr[nub, firstAddr+8], ReadCardAtCardAddr[nub, firstAddr+12]]]; END; ReadCardAtCardAddr: PROC[nub: CirioNubAccess.Handle, addr: CARD32] RETURNS[CARD32] = BEGIN RETURN[CirioNubAccess.Read32BitsAsCard[[nub, addr, 0, FALSE, TRUE]]]; END; ReadIntAtCardAddr: PROC[nub: CirioNubAccess.Handle, addr: CARD32] RETURNS[INT32] = BEGIN RETURN[LOOPHOLE[CirioNubAccess.Read32BitsAsCard[[nub, addr, 0, FALSE, TRUE]]]]; END; <> TestLoadStateByPC: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; remoteName: Rope.ROPE _ args[1]; portNum: CARD _ Convert.CardFromRope[args[2]]; absPC: CARD _ Convert.CardFromRope[args[3]]; nub: CirioNubAccess.Handle _ CirioNubAccess.CreateRemoteNub[debuggee: remoteName, port: portNum, timeoutMsec: 10000]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => {SystemInterface.CloseFileSet[fileSet]; CirioNubAccess.DestroyNub[nub]}; loadState: LoadStateHandle _ CreateLoadStateHandle[remoteName, nub, fileSet]; basicInfo: REF LoadStateAccess.BasicPCInfo _ GetBasicPCInfo[loadState, absPC]; moreInfo: REF LoadStateAccess.LoadedModuleInfo _ GetLoadedModuleInfoFromAbsPC[loadState, absPC]; rope1: Rope.ROPE _ GetRopeForBasicPCInfo[basicInfo, absPC, TRUE, TRUE, TRUE, TRUE]; ropes2: LIST OF Rope.ROPE _ GetRopeListForBasicPCInfo[basicInfo]; ropes3: LIST OF Rope.ROPE _ GetRopeListForLoadedModuleInfo[moreInfo]; IO.PutF[cmd.out, "%g\N", IO.rope[rope1]]; FOR rps: LIST OF Rope.ROPE _ ropes2, rps.rest WHILE rps # NIL DO IO.PutF[cmd.out, "%g\N", IO.rope[rps.first]]; ENDLOOP; FOR rps: LIST OF Rope.ROPE _ ropes3, rps.rest WHILE rps # NIL DO IO.PutF[cmd.out, "%g\N", IO.rope[rps.first]]; ENDLOOP; END; SystemInterface.CloseFileSet[fileSet]; CirioNubAccess.DestroyNub[nub]; END; TestLoadStateByName: Commander.CommandProc = BEGIN args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; remoteName: Rope.ROPE _ args[1]; portNum: CARD _ Convert.CardFromRope[args[2]]; name: Rope.ROPE _ args[3]; nToSkip: CARD _ Convert.CardFromRope[args[4]]; nub: CirioNubAccess.Handle _ CirioNubAccess.CreateRemoteNub[debuggee: remoteName, port: portNum, timeoutMsec: 10000]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; BEGIN ENABLE UNWIND => {SystemInterface.CloseFileSet[fileSet]; CirioNubAccess.DestroyNub[nub]}; loadState: LoadStateHandle _ CreateLoadStateHandle[remoteName, nub, fileSet]; info: REF LoadStateAccess.LoadedModuleInfo _ GetLoadedModuleInfoFromStemName[loadState, name, nToSkip]; ropes: LIST OF Rope.ROPE _ GetRopeListForLoadedModuleInfo[info]; FOR rps: LIST OF Rope.ROPE _ ropes, rps.rest WHILE rps # NIL DO IO.PutF[cmd.out, "%g\N", IO.rope[rps.first]]; ENDLOOP; END; SystemInterface.CloseFileSet[fileSet]; CirioNubAccess.DestroyNub[nub]; END; <
> Commander.Register["TestLoadStateByPC", TestLoadStateByPC]; <<>> <> <<>> Commander.Register["TestLoadStateByName", TestLoadStateByName]; <<>> <> END..