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; 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.. า LoadStateAccessImpl.mesa Copyright ำ 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Sturgis, March 23, 1990 3:33 pm PST Last tweaked by Mike Spreitzer on April 10, 1992 4:33 pm PDT Linda Howe December 28, 1989 8:27:18 am PST Coolidge, July 23, 1990 4:22 pm PDT Laurie Horton, October 23, 1991 2:55 pm PDT Philip James, February 13, 1992 11:03 am PST Katsuyuki Komatsu December 29, 1992 8:31 pm PST Jas, January 8, 1993 2:00 pm PST This module is intended to replace part of the old SymbolFindingImpl. It knows about: the load state (through the nub), parsed object files (through ObjectFiles), and finding loaded object files files. It knows nothing about mobs, CFiles, or Mesa files. This should be cleaned up (better use of PATH) If I understand correctly, this is the containing object file I am a little suspicious about installing the name I was supplied with. Perhaps I should do what I do when given an absPC, get the list from the basic pc info. (Or at least check that the given name is in that list?) If I understand correctly, this is the containing object file I am a little suspicious about installing the name I was supplied with. Perhaps I should do what I do when given an absPC, get the list from the basic pc info. (Or at least check that the given name is in that list?) In the SGI IRIX version, I count on this to return NIL to tell me that the absPC is within the patch space. I think NIL is OK. I added this check to accommodate a SGI IRIX pcr bug, when guessedEmbeddedFileSymID is 0 LookupSymEntryByID causes the pcr to PANIC We need to try harder here instead of giving up when the LoadState doesn't know a guessedEmbedded file name. Not all object file formats support this functionality. looks promising, lets continue lets consider the nominal entry nominal entry does not match conditions, so we have to make our first probe with numToSkip = 0 in order not to miss an entry lets try earlier entries lets try later entries patch: [fileInfo.patchReloc, fileInfo.patchSize], common: [fileInfo.commonReloc, fileInfo.commonSize] It becomes critical that the module information exists with SGI, I've changed $normal to $urgent BasicTime.mesa says that earliestGMT is the beginning of 1968 Sun documentation says that Sun time (Unix standard?) is zero at beginning of 1970 hash mechanism Stab ranges This was taken from FindStabRange We consult a table located in the target world. That table is described in /palain-UX/jaune/xrhome/DEVELOPMENT/loading/INCLUDE/xr/ADotOutExtras.h in vicinity of dbxstabgroup We return [1,0] if there are no dbx symbol table entries for the given pc. Suppose that nGroups = 0. This probably means that the embedded DotO has no dbx symbols. lets check x invariant: procedureStartRelativePC > group[x].lastPC y = nGroups OR procedureStartRelativePC < group[y].firstPC no dbx symbols crude test of LoadStateAccess and Nub (and fileSets) main code TestLoadStateByPC menhir 4816 4567890 TestLoadStateByName menhir 4816 ThreadsSwitch.o 0 สu•NewlineDelimiter – "cedar" style™codešœ™K™HKšœ#™#K™œ˜†Kšœœžœ˜K˜Kšœœœ˜Kšœœ œ˜Kšœ œ˜,Kšœœ&˜>K™Kšœœœ˜0š œœœ œœ˜4Kšœœ˜Kšœ˜Kšœ!˜!Kšœ˜Kšœ$˜$Kšœ˜—K˜š žœœœœ@œ˜’Kš˜Kšœ;˜;KšœB˜BKšœ6˜6KšœœR˜\Kšœ˜K˜—K˜Kšœœœ˜*šœœœ˜ Kšœ˜K˜Kšœœฯc˜˜YKšœœœœ˜UKšœœ˜&Kšœœœ0œ$˜pšœ œœ9˜gKš˜Kšœ œœ˜š œœœœ,œ œ˜Wšœ œ˜Kšœ+˜+—Kšœ$œœœ˜]Kšœœ˜Kšœ˜—Kšœ˜—Kšœœ3˜>Kšœ˜—Kšœ˜—K˜šž.œœœœ#œœœœ˜„Kš˜š œœœœœ ˜/Kš˜Kšœœœ>˜]Kš œ œœœœ$˜xKšœœ˜$Kšœ˜—Kšœ˜—K˜šžœœœœœœœ˜uKš˜Kšœ1˜1Kšœ0˜0KšœC˜CKšœP˜PK˜šœœ˜ Kš˜KšœœTœ˜‹Kšœœ˜ Kš˜—Kšœœœ[˜gKšœ˜—K˜K˜K˜šœ œœ˜Kšœ œ˜+Kšœ˜Kšœ*˜*—K˜šžœœœ2œœœœ˜ŒKš˜Kš œ œœœœ˜!šœœ1˜UKš˜Kšœœ`œ˜—K™Kšœœ˜ Kš˜—šœ˜Kš˜Kšœœ>Ÿ!˜~K˜šœœœŸะci˜KKš˜KšœA˜AKšœ œC˜QKšœ œe˜uKšœœDœœ˜UKšœ˜—K˜Kšœ ˜Kšœ˜—Kšœ˜—K˜K˜šžœœœœœœœ˜oKš œœœœœ'˜E—K˜K˜K˜Kšž œœ˜-Kšžœœ˜)K˜šž œœœœ˜LKš˜KšœH˜Hšœœœ˜Kšœœ{œ˜ณKšœœœœ˜K˜—šœœ˜Kšœœ@œ˜xKšœœœœ˜K˜—Kšœ^˜^Kšœ.˜.Kšœ#˜#K˜Kšœƒ™ƒšœ&˜,Kšœc˜c—KšœI˜IK˜K™งšœ%œœ˜IKš˜KšœœMœ˜„Kšœœ˜ Kšœ˜K˜—K˜šœ™Kš˜šœ œœ˜NKšœ ˜ K˜/Kšœœ"Ÿ ˜EKšœF˜FKšœ˜Kš œ!œ œœœ.˜mKšœœ˜2—K˜K™šœ7œ9˜xKšœ)œH˜t—šœ˜K™|Kš˜Kšœž˜žšœœœ3˜RKš˜Kšœ)œC˜oKšœ&˜&Kšœ˜—Kšœ˜K˜—K™š˜KšœŸ˜ŸKš œœœ3œœ˜WKšœ)œC˜oKšœ&˜&Kšœ˜—K™Kšœ,˜,š˜Kšœ›˜›Kš œœœ0œœ˜QKšœ)œ@˜lKšœ#˜#Kšœ˜—Kšœ ˜&Kšœ˜—Kšœœ˜—K˜K˜K˜šžœœœœ%œœœœ˜„Kšœœœœ˜.Kš œœœœœ˜Kšœ˜K˜Kšœœ^˜hK˜šœœœ'˜QKš˜Kšœ œœ˜š œœœœ(œ œ˜SKšœ œ˜'K˜Kšœ œ˜*Kšœœ˜Kšœ˜—Kšœ˜—KšœœL˜Všœœ˜ Kšœ˜Kšœ œ$˜2KšœœF˜P—Kšœ˜K˜Kšœœ˜—K˜šžœœœœœœœœ˜jKš˜Kš œœœœœ˜3šœ˜Kš˜Kš œœœ&œœ%œ˜ŽKšœœ˜&Kšœœœ0œ$˜nKš œœœ-œœ-˜’K˜šœœœ@˜jKš˜Kšœ œœ˜š œœœœ(œ œ˜SKšœ œ,˜?Kšœ$œœœ˜]Kšœœ˜Kšœ˜—Kšœ˜—K˜Kšœœ0˜;Kšœ˜—Kšœ˜—K˜K˜K˜Kšœœœ˜*šœœœ˜ Kšœœ˜ Kšœœ˜ Kšœœ˜K˜Kšœ˜—K˜K˜K˜šžœœ&œ˜kšœ˜ Kšœ1™1Kšœ.˜.Kšœ.˜.Kšœ*˜*Kšœ3™3K˜——K˜š žœœMœœœœ˜ƒKšœœœS˜vKšœœ+˜NKšœœ(˜AšœœœŸข˜WKšœˆ˜ˆKšœœ˜!Kšœœ˜šœœœ˜KšœL˜Lšžœœœ˜2KšœœœŸ ˜š œœ$œœœœ˜Nšœ#˜&Kšœ˜Kšœ˜Kšœ#˜#Kšœ#˜#Kšœ˜Kšœ˜Kšœ˜Kšœ˜KšœŸ&œ˜+——Kšœœœœœœœ)Ÿœ ˜ŠKš œœœœœ\˜ƒKšœ˜Kšœ˜—Kšœ˜—J˜J˜K™=K™Rš žœœ œœ œ˜Kšœœœ0˜;K˜—K˜šžœœœ œœœœ˜[Kšœœb˜i—K˜K˜Kšœœœ˜DKšœœœ˜AK˜K˜šžœœœ˜DKšœœœ7˜B—K˜K˜Kšœœœ˜8Kšœœœ˜:K˜šžœœœ˜8Kšœœœ0˜;—K˜Kšœ œœ ˜Kš œ œœœ œœ ˜AKš œ œœ œ)œ˜Ršœ œœœŸ%˜@K˜——K˜šœ ™ K™š žœœ œœ œ˜]K™!K™Kšœ0˜0Kšœ?˜?K˜K˜KšœD˜DKšœe˜eKš œ œœœœœœ˜SKšœœ"˜@Kšœ!˜!K˜K˜—Kšœ œ ˜/˜K™/™K™FK™—K™J—šž œœ œœ ˜MKš˜Kšœ0˜0Kšœ?˜?K˜K˜KšœD˜DKšœe˜eKš œ œœœœœœ˜SKšœœ"˜@Kšž œœ˜Kšœ œ%˜1Kšœœ˜ Kšœœ ˜K˜K™YKšœ œœ ˜#K˜™ Kš˜Kšœ?˜?Kšœ*œœ ˜@Kšœ*œœ˜UKšœ˜—K˜šœ ™ Kšœ*™*Kšœ:™:—K™šœ ˜Kšœœ ˜KšœC˜Cšœœ˜Kšœ6˜6šœ,œ.˜]Kšœ"˜(—Kšœ5˜5Kšœœ˜—Kšœ˜—K™K™Kšœ ˜Kšœ˜—K˜Kš œ œœ œ œ œ œ˜PK˜šžœœJœœ˜ƒKš˜Kšœœ˜Kšœ œ0˜?šœ˜Kšœ"˜"Kšœ$˜$K˜%K˜(—Kšœ˜—K˜š žœœ#œœœ˜TKš˜Kšœ0œœ˜EKšœ˜—K˜š žœœ#œœœ˜RKš˜Kšœœ0œœ˜OKšœ˜——K˜™4K˜šžœ˜*Kš˜Kšœ:˜:Kšœœ ˜ Kšœ œ!˜.Kšœœ!˜,Kšœu˜ušœC˜Cšœœœ˜KšœH˜H—KšœM˜MKšœ œ@˜NKšœ œS˜`K˜Kš œ œ+œœœœ˜SKšœœœœ(˜AKšœœœœ,˜EK˜Kšœœ˜)š œœœœœœ˜@Kšœœ˜-Kšœ˜—š œœœœœœ˜@Kšœœ˜-Kšœ˜—Kšœ˜—K˜&Kšœ˜Kšœ˜—K˜šžœ˜,Kš˜Kšœ:˜:Kšœœ ˜ Kšœ œ!˜.Kšœ œ ˜Kšœ œ!˜.Kšœu˜ušœC˜Cšœœœ˜KšœH˜H—KšœM˜MKšœœ^˜gKšœœœœ(˜@š œœœœœœ˜?Kšœœ˜-Kšœ˜—Kšœ˜—K˜&Kšœ˜Kšœ˜—K˜—K˜K™ K˜šœ;˜;K™Kšœ%™%—K™šœ?˜?K™Kšœ1™1K˜—Kšœ˜——…—bœ‰ใ