<<>> <> <> <> <> <> <> <> DIRECTORY Basics USING [Card16FromH, Card32FromF, Comparison, BITLSHIFT, BITRSHIFT, BITAND, BITOR, FWORD, HWORD], BasicTime USING [GMT, Now], CCTypes USING [CCError, CCErrorCase], CirioTypes USING [zeroBA], Commander USING [Register, Handle], CommanderOps USING [ArgumentVector, Parse], Convert USING [IntFromRope, RopeFromChar], IO, List USING [CompareProc, Sort], ObjectFiles USING [BracketNest, BracketPairKind, BracketProc, CNameOfStab, CreateParsed, DescribeModule, FileSegmentPC, FunInfo, GlobalVarLoc, MakeUnknownVarLoc, ModuleInfo, Parsed, RopeForStabType, SimpleSeg, Stab, StabBody, StorageClass, StabType, SymbolProc, UnreadableObjectFile, unspecdBitSize, VarLoc, VarLocBody, VersionStampInfo], ObjectFilesPrivate USING [AlterFunStabType, BracketConsumer, BracketPair, BracketPairBody, CheckStaticVar, FnConsumer, FunStabSet, FunStabInfo, FunHandleBody, FunStabSetBody, GetSPOffsetType, GetTypeRefProcType, HeaderBody, InstallStaticVarsType, LineNumToPCMapBody, MemorySegmentInfo, Module, ModuleBody, ModuleFromParsedAndPCProcType, ObjectFileFlavorBody, Parsed, ParsedBody, PCtoLineNumMapBody, ReadHeaderProcType, ReadInitialDataAsRope, ReadStab, RegisterObjectFileFlavor, RaiseUnreadableObjectFileForFun, SLineData, ScanSymbolStabs, StabList, StabRange, StabSet, TranslationTable, TranslationTableBody, VarLocFromStabProcType], PFS USING [PathFromRope, RopeFromPath], PFSNames USING [PATH], Random USING [ChooseInt, Create, RandomStream], Rope USING [Concat, Equal, FromChar, ROPE], SGI, SystemInterface USING [CirioFile, CloseFileSet, CreateFileSet, FileSet, GetCirioFile, GetStreamForFile, GetNameOfFile, ReleaseStreamForFile, ShowReport], UXStrings USING [CString, Create]; SGIFiles: CEDAR MONITOR IMPORTS Basics, BasicTime, CCTypes, Commander, CommanderOps, Convert, IO, List, ObjectFiles, ObjectFilesPrivate, PFS, Random, Rope, SystemInterface, UXStrings EXPORTS ObjectFiles, SGI = BEGIN CCError: ERROR[case: CCTypes.CCErrorCase, msg: ROPE ¬ NIL] ¬ CCTypes.CCError; <> ROPE: TYPE = Rope.ROPE; PATH: TYPE = PFSNames.PATH; Comparison: TYPE = Basics.Comparison; FWORD: TYPE = Basics.FWORD; HWORD: TYPE = Basics.HWORD; <> Stab: TYPE = ObjectFiles.Stab; StabBody: TYPE = ObjectFiles.StabBody; StabType: TYPE = ObjectFiles.StabType; StorageClass: TYPE = ObjectFiles.StorageClass; FunInfo: TYPE = ObjectFiles.FunInfo; SymbolProc: TYPE = ObjectFiles.SymbolProc; BracketProc: TYPE = ObjectFiles.BracketProc; BracketNest: TYPE = ObjectFiles.BracketNest; BracketPairKind: TYPE = ObjectFiles.BracketPairKind; VersionStampInfo: TYPE = ObjectFiles.VersionStampInfo; <> Parsed: TYPE = REF ParsedBody; ParsedBody: PUBLIC TYPE = ObjectFilesPrivate.ParsedBody; Module: TYPE = REF ModuleBody; ModuleBody: PUBLIC TYPE = ObjectFilesPrivate.ModuleBody; ModuleInfo: TYPE = ObjectFiles.ModuleInfo; StabSet: TYPE = ObjectFilesPrivate.StabSet; StabRange: TYPE = ObjectFilesPrivate.StabRange; MemorySegmentInfo: TYPE = ObjectFilesPrivate.MemorySegmentInfo; FileSegmentPC: TYPE = ObjectFiles.FileSegmentPC; BracketPair: TYPE = REF BracketPairBody; BracketPairBody: TYPE = ObjectFilesPrivate.BracketPairBody; FunStabSet: TYPE = ObjectFilesPrivate.FunStabSet; FunStabSetBody: TYPE = ObjectFilesPrivate.FunStabSetBody; FunStabInfo: TYPE = ObjectFilesPrivate.FunStabInfo; <> PCtoLineNumMap: TYPE = REF PCtoLineNumMapBody; PCtoLineNumMapBody: TYPE = ObjectFilesPrivate.PCtoLineNumMapBody; <> LineNumToPCMap: TYPE = REF LineNumToPCMapBody; LineNumToPCMapBody: TYPE = ObjectFilesPrivate.LineNumToPCMapBody; Header: TYPE = REF HeaderBody; HeaderBody: PUBLIC TYPE = ObjectFilesPrivate.HeaderBody; FunHandle: TYPE = REF FunHandleBody; FunHandleBody: TYPE = ObjectFilesPrivate.FunHandleBody; <> WireHeader: TYPE = REF SGI.WireHeaderBody; WireAuxHeader: TYPE = REF SGI.WireAuxHeaderBody; WireSectionHeader: TYPE = REF SGI.WireSectionHeaderBody; WireSymHeader: TYPE = REF SGI.WireSymHeaderBody; WirePackedLineNum: TYPE = REF SGI.WirePackedLineNumBody; WireProcDescriptor: TYPE = REF SGI.WireProcDescriptorBody; WireRelFileTable: TYPE = REF SGI.WireRelFileTableBody; WireFileDescriptor: TYPE = REF SGI.WireFileDescriptorBody; WireSTEntry: TYPE = REF SGI.WireSTEntryBody; WireExtSTEntry: TYPE = REF SGI.WireExtSTEntryBody; WireTypeInfo: TYPE = REF SGI.WireTypeInfoBody; WireRelIndex: TYPE = REF SGI.WireRelIndexBody; WireAuxSTEntry: TYPE = REF SGI.WireAuxSTEntryBody; SectionTable: TYPE = REF SGI.SectionTableBody; FileDescrTable: TYPE = REF SGI.FileDescrTableBody; RelFileTable: TYPE = REF SGI.RelFileTableBody; ProcDescrTable: TYPE = REF SGI.ProcDescrTableBody; LocalSymTable: TYPE = REF SGI.LocalSymTableBody; IndexedLocalSymTable: TYPE = REF SGI.IndexedLocalSymTableBody; ExtSymTable: TYPE = REF SGI.ExtSymTableBody; AuxSymTable: TYPE = REF SGI.AuxSymTableBody; IndexedAuxSymTable: TYPE = REF SGI.IndexedAuxSymTableBody; StringTable: TYPE = REF SGI.StringTableBody; WireTables: TYPE = REF SGI.WireTablesBody; <<>> StabIndexTypeAndValue: TYPE = RECORD [ stabX: CARD, type: StabType, value: CARD ]; StabList: TYPE = ObjectFilesPrivate.StabList; ScannedBracketPair: TYPE = RECORD[bpi: BracketPair, nextX: CARD]; FMap: TYPE = LIST OF FMapData; FMapBody: TYPE = RECORD [SEQUENCE maxIndex: CARD OF FMapData]; FMapData: TYPE = REF FMapDataBody; FMapDataBody: TYPE = RECORD [ fName: Rope.ROPE, stabOffset: CARD ]; DotOType: TYPE = Rope.ROPE; PDTType: TYPE = RECORD [SEQUENCE maxIndex: CARD OF Rope.ROPE]; ByteSequence: TYPE = REF ByteSequenceBody; ByteSequenceBody: TYPE = RECORD [SEQUENCE maxIndex: CARD OF BYTE]; <<========================================================================>> <<========================================================================>> <> <<========================================================================>> <<========================================================================>> IndexNil: CARD = 0FFFFFH; -- max valid index for aux entries <> ECOFFMagic: CARD16 = 352; <> <<>> nPageSize: CARD = 01000H; -- this is according to getpagesize() SymbolSize: CARD = 12; -- this is the size of a local sym ExtSymbolSize: CARD = 16; -- this is ext sym size AuxSymbolSize: CARD = 4; -- this is aux sym size RelocEntrySize: CARD = 8; LnnoEntrySize: CARD = 4; FileDescrSize: CARD = 72; -- Need to check this...may be some <> ProcDescrSize: CARD = 56; BasicSizes: ARRAY [0..64) OF BYTE = [0,32,8,8,16,16,32,32,32,32,32,64,0,0,32,0,32,32,64,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; WordByteSize: CARD = 4; WordBitSize: CARD = 32; <<>> <> ElfMagic: CARD = (Basics.BITLSHIFT[177B, 24] + Basics.BITLSHIFT['E.ORD, 16] + Basics.BITLSHIFT['L.ORD, 8] + 'F.ORD); <<>> ElfClassNone: CARD = 0; ElfClass32: CARD = 1; ElfClass64: CARD = 2; ElfDataNone: CARD = 0; ElfData2LSB: CARD = 1; ElfData2MSB: CARD = 2; ETNone: CARD = 0; ETRelocatable: CARD = 1; ETExecutable: CARD = 2; ETDynamicLib: CARD = 3; ETCore: CARD = 4; EMNone: CARD = 0; EMM32: CARD = 1; EMSparc: CARD = 2; EM386: CARD = 3; EM68K: CARD = 4; EM88K: CARD = 5; EM486: CARD = 6; EM860: CARD = 7; EMMips: CARD = 8; EMS370: CARD = 9; SHTNull: CARD = 0; SHTProgBits: CARD = 1; SHTSymTab: CARD = 2; SHTStrTab: CARD = 3; SHTRela: CARD = 4; SHTHash: CARD = 5; SHTDynamic: CARD = 6; SHTNote: CARD = 7; SHTNoBits: CARD = 8; SHTRel: CARD = 9; SHTShLib: CARD = 10; SHTDynSym: CARD = 11; SHTLoProc: CARD = 70000000H; SHTMipsDebug: CARD = SHTLoProc+5; SHFWrite: CARD = 1; SHFAlloc: CARD = 2; SHFExecInStr: CARD = 4; ElfWireHeader: TYPE = REF ElfWireHeaderBody; ElfWireHeaderBody: TYPE = MACHINE DEPENDENT RECORD[ magic: Basics.FWORD, elfClass: BYTE, elfData: BYTE, elfVersion: BYTE, elfPad1: BYTE, elfPad2: PACKED ARRAY [8..15] OF BYTE, type: Basics.HWORD, machine: Basics.HWORD, version: Basics.FWORD, entry: Basics.FWORD, progHdrOffset: Basics.FWORD, sectHdrOffset: Basics.FWORD, flags: Basics.FWORD, elfHdrSize: Basics.HWORD, progHdrSize: Basics.HWORD, progHdrNum: Basics.HWORD, sectHdrSize: Basics.HWORD, sectHdrNum: Basics.HWORD, sectStrTblX: Basics.HWORD]; SectionList: TYPE = REF SectionListBody; SectionListBody: TYPE = RECORD[ list: SEQUENCE length: CARD OF SectionHeader]; SectionHeader: TYPE = REF SectionHeaderBody; SectionHeaderBody: TYPE = RECORD[ name: ROPE ¬ NIL, nameIndex: CARD32, type: CARD32, flags: CARD32, addr: CARD32, offset: CARD32, size: CARD32, link: CARD32, info: CARD32, alignment: CARD32, entrySize: CARD32]; ElfWireSectionHeader: TYPE = REF ElfWireSectionHeaderBody; ElfWireSectionHeaderBody: TYPE = MACHINE DEPENDENT RECORD[ nameIndex: Basics.FWORD, type: Basics.FWORD, flags: Basics.FWORD, addr: Basics.FWORD, offset: Basics.FWORD, size: Basics.FWORD, link: Basics.FWORD, info: Basics.FWORD, alignment: Basics.FWORD, entrySize: Basics.FWORD]; <<========================================================================>> <<========================================================================>> <> <<========================================================================>> <<========================================================================>> unspecdBitSize: CARD ~ ObjectFiles.unspecdBitSize; NullStabIndexTypeAndValue: StabIndexTypeAndValue = [0, Invalid, 0]; <<========================================================================>> <<========================================================================>> <> <<========================================================================>> <<========================================================================>> RawBytes: TYPE = RECORD [PACKED SEQUENCE COMPUTED CARD OF BYTE]; Printf: PROC [fmt: POINTER TO RawBytes, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10: UNSPECIFIED ¬ 0] RETURNS [INTEGER] = TRUSTED MACHINE CODE { "xr_printf" }; Print: PROC [s: STRING, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10: UNSPECIFIED ¬ 0] = TRUSTED { [] ¬ Printf[LOOPHOLE[@s.text], arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10]; }; DebugProc: PROC = TRUSTED MACHINE CODE { "XR_CallDebugger"; }; <<========================================================================>> <<========================================================================>> <> <<========================================================================>> <<========================================================================>> FindMatchingProcDescr: PUBLIC PROC [relPC: CARD, parsed: ObjectFiles.Parsed] RETURNS [SGI.WireProcDescriptorBody, BOOLEAN] = TRUSTED { privateParsed: ObjectFilesPrivate.Parsed ¬ LOOPHOLE[parsed, ObjectFilesPrivate.Parsed]; wireTables: WireTables ¬ NARROW[privateParsed.privateInfo, WireTables]; found: BOOLEAN ¬ FALSE; high, low, mid: INT32; procDescrStartingAddr: CARD32 ¬ wireTables.procDescr[0].startAddress; numOfProcs: INT32 ¬ wireTables.wSymHeader.procDescrIndexLimit; dummy: SGI.WireProcDescriptorBody ¬ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; IF relPC = 0 THEN RETURN [dummy, found]; <<>> <> low ¬ 0; high ¬ numOfProcs; WHILE low < high DO mid ¬ (low+high+1)/2; IF mid = numOfProcs THEN RETURN [dummy, found]; IF relPC < wireTables.procDescr[mid].startAddress THEN high ¬ mid - 1 ELSE low ¬ mid; ENDLOOP; RETURN [wireTables.procDescr[high], TRUE]; }; FixUpProcedureDescrAddrs: PROC [header: Header, numFileDescr: CARD32, fileDescr: FileDescrTable, procDescr: ProcDescrTable] = { numProcDescr: INT32; j, jStart, jStop: CARD32; i: CARD32; FOR i IN [0..numFileDescr) DO numProcDescr ¬ fileDescr[i].cpd; jStart ¬ fileDescr[i].ipdFirst; jStop ¬ jStart + numProcDescr; FOR j IN [jStart..jStop) DO procDescr[j].startAddress ¬ fileDescr[i].startAddress + procDescr[j].startAddress - header.textLoadOffset; ENDLOOP; ENDLOOP; }; IsSameEndianSGI: PUBLIC PROC [stream: IO.STREAM] RETURNS [BOOLEAN] = TRUSTED { magicNum: Basics.HWORD; nBytes, oldFileIndex: INT; fileHeader: WireHeader ¬ NEW[SGI.WireHeaderBody]; oldFileIndex ¬ IO.GetIndex[stream]; IO.SetIndex[stream, 0]; -- SGI magic number is 2 bytes at start of file nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@fileHeader­], 0, BYTES[SGI.WireHeaderBody]]]; IO.SetIndex[stream, oldFileIndex]; magicNum ¬ LOOPHOLE[fileHeader.magic]; IF (nBytes = 0) THEN ERROR; -- something is very wrong <> IF (magicNum.hi = 01H) AND (magicNum.lo = 062H OR magicNum.lo = 060H) THEN RETURN [TRUE] ELSE IF (magicNum.hi = 062H OR magicNum.hi = 060H) AND (magicNum.lo = 01H) THEN RETURN [FALSE] ELSE ERROR; -- this is not a MIPS SGI file }; ProcessQualifierSizes: PROC [typeInfo: SGI.WireTypeInfoBody, qualifiedSize: CARD, auxIndex: INT32, wireTables: WireTables] RETURNS [continued: BOOLEAN, size: CARD, nextAuxIndex: INT32] ~ TRUSTED { qualifier: ARRAY [0..5) OF BYTE; numQualifiers: CARD ¬ 0; continued ¬ LOOPHOLE[typeInfo.continued, INT] = 1; size ¬ qualifiedSize; nextAuxIndex ¬ auxIndex; <> DO IF (typeInfo.typeQual0 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] ¬ typeInfo.typeQual0; numQualifiers ¬ numQualifiers + 1; IF (typeInfo.typeQual1 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] ¬ typeInfo.typeQual1; numQualifiers ¬ numQualifiers + 1; IF (typeInfo.typeQual2 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] ¬ typeInfo.typeQual2; numQualifiers ¬ numQualifiers + 1; IF (typeInfo.typeQual3 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] ¬ typeInfo.typeQual3; numQualifiers ¬ numQualifiers + 1; IF (typeInfo.typeQual4 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] ¬ typeInfo.typeQual4; numQualifiers ¬ numQualifiers + 1; IF (typeInfo.typeQual5 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] ¬ typeInfo.typeQual5; numQualifiers ¬ numQualifiers + 1; IF numQualifiers > 5 THEN EXIT; ENDLOOP; <> FOR i: INT IN (numQualifiers..0] DO { low, high, bitWidth: INT32; SELECT qualifier[i] FROM SGI.TQNil => NULL; SGI.TQPtr => { size ¬ WordBitSize; RETURN; }; SGI.TQProc => NULL; -- size info is redundant with pointer SGI.TQVol => NULL; -- volatile doesnt have any size info SGI.TQArray => { low ¬ LOOPHOLE[wireTables.auxSyms[nextAuxIndex].lowIndex]; nextAuxIndex ¬ nextAuxIndex + 1; high ¬ LOOPHOLE[wireTables.auxSyms[nextAuxIndex].highIndex]; nextAuxIndex ¬ nextAuxIndex + 1; bitWidth ¬ LOOPHOLE[wireTables.auxSyms[nextAuxIndex].bitWidth]; nextAuxIndex ¬ nextAuxIndex + 1; size ¬ (high+1)*bitWidth; RETURN; } ENDCASE => NULL; }; ENDLOOP; RETURN; }; <> SLineData: TYPE = ObjectFilesPrivate.SLineData; LineNum: TYPE = REF LineNumSeqBody; LineNumSeqBody: TYPE = RECORD [SEQUENCE maxIndex: CARD OF LineNumRecBody]; LineNumRecBody: TYPE = RECORD [ lineNumber: INT32, relativePC: CARD ]; UnPackLineNumbers: PUBLIC PROC [stream: IO.STREAM, module: Module, wireTables: WireTables] = TRUSTED { CompareByCLineNum: PROC [ref1: REF ANY, ref2: REF ANY] RETURNS [Basics.Comparison] = TRUSTED { info1: REF SLineData ¬ NARROW[ref1]; info2: REF SLineData ¬ NARROW[ref2]; <<>> IF info1.cLineNum < info2.cLineNum THEN RETURN[less]; IF info1.cLineNum > info2.cLineNum THEN RETURN[greater]; IF info1.parsedRelPC.relPC < info2.parsedRelPC.relPC THEN RETURN[less]; IF info1.parsedRelPC.relPC > info2.parsedRelPC.relPC THEN RETURN[greater]; RETURN[equal]; }; CompareByPC: PROC [ref1: REF ANY, ref2: REF ANY] RETURNS [Basics.Comparison] = TRUSTED { info1: REF SLineData ¬ NARROW[ref1]; info2: REF SLineData ¬ NARROW[ref2]; <<>> IF info1.parsedRelPC.relPC < info2.parsedRelPC.relPC THEN RETURN[less]; IF info1.parsedRelPC.relPC > info2.parsedRelPC.relPC THEN RETURN[greater]; IF info1.cLineNum < info2.cLineNum THEN RETURN[less]; IF info1.cLineNum > info2.cLineNum THEN RETURN[greater]; RETURN[equal]; }; header: Header ¬ module.whole.header; fileDescr: FileDescrTable ¬ wireTables.fileDescr; procDescr: ProcDescrTable ¬ wireTables.procDescr; numBytes: CARD ¬ wireTables.wSymHeader.numBytesPackedLineNums; packedLineNum: WirePackedLineNum ¬ NEW[SGI.WirePackedLineNumBody[numBytes]]; l, count: BYTE; signedShort, absOfSignedShort: INT16; delta, lowByte: INT32; packedIndex, stopIndex, lineTableIndex: INT32 ¬ 0; k, numProcDescr: INT32; j, jStart, jStop: CARD32; numBytesRead: INT32; currentSrcLine: CARD; info: REF SLineData; startAddress: CARD32; list1: LIST OF REF ANY ¬ NIL; -- LIST OF REF SLineData list2: LIST OF REF ANY ¬ NIL; -- LIST OF REF SLineData sortedList: LIST OF REF ANY ¬ NIL; unpackedNums: LineNum ¬ NEW[LineNumSeqBody[wireTables.wSymHeader.lineNumIndexLimit]]; instrCount: CARD32; fdIndex: INT32; <> IO.SetIndex[stream, wireTables.wSymHeader.packedLineNumPtr]; numBytesRead ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[LOOPHOLE[packedLineNum, CARD]+BYTES[CARD]], 0, numBytes]]; <<>> <> fdIndex ¬ module.fdIndex; numProcDescr ¬ fileDescr[fdIndex].cpd; jStart ¬ fileDescr[fdIndex].ipdFirst; jStop ¬ jStart + numProcDescr; <> FOR j IN [jStart..jStop) DO IF (procDescr[j].iline # -1) AND (procDescr[j].lnLow # -1) AND (procDescr[j].lnHigh # -1) THEN { stopIndex ¬ fileDescr[fdIndex].ilineBase + fileDescr[fdIndex].cline; <> <> FOR k IN [j+1..numProcDescr) DO IF procDescr[k].iline # -1 THEN { stopIndex ¬ fileDescr[fdIndex].ilineBase + procDescr[k].iline; EXIT; }; ENDLOOP; IF (stopIndex - procDescr[j].iline) > 0 THEN { startAddress ¬ procDescr[j].startAddress; instrCount ¬ 0; lineTableIndex ¬ fileDescr[fdIndex].ilineBase + procDescr[j].iline; currentSrcLine ¬ procDescr[j].lnLow; packedIndex ¬ fileDescr[fdIndex].cbLineOffset + procDescr[j].cbLineOffset; <> WHILE lineTableIndex < stopIndex DO <> delta ¬ packedLineNum[packedIndex]; IF delta > 127 THEN delta ¬ LOOPHOLE[Basics.BITOR[delta, 0FFFF00H]]; delta ¬ LOOPHOLE[Basics.BITRSHIFT[delta, 4]]; count ¬ Basics.BITAND[packedLineNum[packedIndex], 0FH] + 1; packedIndex ¬ packedIndex + 1; signedShort ¬ LOOPHOLE[delta, INT16]; absOfSignedShort ¬ ABS[signedShort]; IF absOfSignedShort > 7 THEN { delta ¬ Basics.BITLSHIFT[packedLineNum[packedIndex], 8]; packedIndex ¬ packedIndex + 1; lowByte ¬ Basics.BITAND[packedLineNum[packedIndex], 0FFH]; delta ¬ Basics.BITOR[delta, lowByte]; packedIndex ¬ packedIndex + 1; signedShort ¬ LOOPHOLE[delta, INT16]; }; currentSrcLine ¬ currentSrcLine + signedShort; FOR l IN [0..count) DO unpackedNums[lineTableIndex].lineNumber ¬ currentSrcLine; unpackedNums[ lineTableIndex].relativePC ¬ instrCount*4+startAddress; instrCount ¬ instrCount + 1; lineTableIndex ¬ lineTableIndex + 1; ENDLOOP; ENDLOOP; }; }; ENDLOOP; FOR I: CARD IN [0..wireTables.wSymHeader.lineNumIndexLimit) DO info ¬ NEW[SLineData ¬ [ cLineNum: unpackedNums[I].lineNumber, parsedRelPC: [ [0 --??--, PFS.RopeFromPath[module.fileName]], unpackedNums[I].relativePC ] ]]; list1 ¬ CONS[info, list1]; list2 ¬ CONS[info, list2]; ENDLOOP; sortedList ¬ List.Sort[list1, CompareByCLineNum]; module.lineNumToPC ¬ NEW[LineNumToPCMapBody[wireTables.wSymHeader.lineNumIndexLimit]]; FOR I: INTEGER IN [0..wireTables.wSymHeader.lineNumIndexLimit) DO info: REF SLineData ¬ NARROW[sortedList.first]; module.lineNumToPC[I] ¬ info­; sortedList ¬ sortedList.rest; ENDLOOP; sortedList ¬ List.Sort[list2, CompareByPC]; module.pcToLineNum ¬ NEW[PCtoLineNumMapBody[wireTables.wSymHeader.lineNumIndexLimit]]; FOR I: INTEGER IN [0..wireTables.wSymHeader.lineNumIndexLimit) DO info: REF SLineData ¬ NARROW[sortedList.first]; module.pcToLineNum[I] ¬ info­; sortedList ¬ sortedList.rest; ENDLOOP; wireTables.pcToLineNum ¬ module.pcToLineNum; wireTables.lineNumToPC ¬ module.lineNumToPC; FREE[@packedLineNum]; FREE[@unpackedNums]; RETURN; }; CalcSymbolSize: PUBLIC PROC [symTabIndex: CARD, fdIndex: INT32, wireTables: WireTables, isExternal: BOOLEAN] RETURNS [size : CARD ¬ 0] = TRUSTED { <> <<>> thisSym: WireSTEntry; auxIndex: CARD; symIndex, basicType, qualifiedSize: CARD ¬ 0; typeInfo: SGI.WireTypeInfoBody; nonStandardWidth: BOOLEAN; continued: BOOLEAN ¬ TRUE; symBaseIndex: CARD; symType: CARD; IF isExternal THEN { thisSym ¬ LOOPHOLE[@wireTables.extSyms[symTabIndex].sym]; fdIndex ¬ wireTables.extSyms[symTabIndex].fileDescrIndex; } ELSE { thisSym ¬ LOOPHOLE[@wireTables.localSyms[symTabIndex]]; }; symType ¬ thisSym.symbolType; SELECT symType FROM SGI.STStruct, SGI.STUnion => { size ¬ thisSym.value*8; RETURN; }; SGI.STFile, SGI.STProc, SGI.STStaticProc, SGI.STBlock, SGI.STEnd => RETURN; SGI.STConstant, SGI.STLabel, SGI.STRegReloc, SGI.STForward, SGI.STStaParam => { size ¬ WordBitSize; RETURN; }; ENDCASE => NULL; <> auxIndex ¬ wireTables.fileDescr[fdIndex].iauxBase + thisSym.index; IF auxIndex >= IndexNil THEN { size ¬ WordBitSize; RETURN; }; typeInfo ¬ wireTables.auxSyms[auxIndex].typeInfo; nonStandardWidth ¬ LOOPHOLE[typeInfo.fBitField]; basicType ¬ typeInfo.basicType; IF (basicType = SGI.BTNil) THEN RETURN; <> IF ((basicType = SGI.BTStruct) OR (basicType = SGI.BTUnion)) THEN { currentIndex: CARD; relFileIndex: INT32; relFileOffset: INT32; relIndex: SGI.WireRelIndexBody ¬ wireTables.auxSyms[auxIndex+1].relIndex; IF relIndex.relFileDescrIndex = 0FFFH THEN { relFileIndex ¬ wireTables.auxSyms[auxIndex+2].relFileIndex; } ELSE { relFileIndex ¬ relIndex.relFileDescrIndex; }; relFileOffset ¬ wireTables.fileDescr[fdIndex].rfdBase + relFileIndex; IF relFileOffset # 0 THEN fdIndex ¬ wireTables.relFiles[relFileOffset]; symIndex ¬ relIndex.index; symBaseIndex ¬ wireTables.fileDescr[fdIndex].isymBase; currentIndex ¬ symIndex + symBaseIndex; size ¬ wireTables.localSyms[currentIndex].value*8; auxIndex ¬ auxIndex + 2; } ELSE IF ((basicType = SGI.BTTypedef) OR (basicType = SGI.BTIndirect)) THEN { <> size ¬ WordBitSize; } ELSE IF (nonStandardWidth = FALSE) THEN size ¬ BasicSizes[basicType] ELSE IF wireTables.auxSyms[auxIndex+1].bitWidth # 0 THEN size ¬ wireTables.auxSyms[auxIndex+1].bitWidth ELSE size ¬ 0; <> WHILE continued DO { [continued, qualifiedSize, auxIndex] ¬ ProcessQualifierSizes[typeInfo, qualifiedSize, auxIndex, wireTables]; IF continued THEN typeInfo ¬ wireTables.auxSyms[auxIndex].typeInfo; }; ENDLOOP; IF (qualifiedSize # 0) THEN { size ¬ qualifiedSize; }; }; ReadElfWireSymHeader: PROC [stream: IO.STREAM] RETURNS [WireSymHeader] = TRUSTED { wHeader: ElfWireHeader ¬ NEW[ElfWireHeaderBody]; nBytes: INT ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wHeader­], 0, BYTES[ElfWireHeaderBody]]]; wSymHeader: WireSymHeader ¬ NIL; sectHdrOffset: CARD ¬ Basics.Card32FromF[wHeader.sectHdrOffset]; sectHdrNum: CARD ¬ Basics.Card16FromH[wHeader.sectHdrNum]; type: CARD; IO.SetIndex[stream, sectHdrOffset]; FOR i: CARD IN [0..sectHdrNum) DO wSectionHeader: ElfWireSectionHeader ¬ NEW[ElfWireSectionHeaderBody]; nBytes: INT ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wSectionHeader­], 0, BYTES[ElfWireSectionHeaderBody]]]; type ¬ Basics.Card32FromF[wSectionHeader.type]; IF type = SHTMipsDebug THEN { offset: CARD ¬ Basics.Card32FromF[wSectionHeader.offset]; wSymHeader ¬ NEW[SGI.WireSymHeaderBody]; [] ¬ ReadWireSymHeader[stream, offset, wSymHeader]; RETURN[wSymHeader]; }; ENDLOOP; RETURN[wSymHeader]; }; InitParsedWireTables: PROC [stream: IO.STREAM, parsed: Parsed] = TRUSTED { filename: UXStrings.CString; wireTables: WireTables ¬ NEW[SGI.WireTablesBody]; nBytes: CARD; magic: CARD; header: Header ¬ parsed.header; symHeader: WireSymHeader; symLimit, extSymLimit, auxSymLimit: CARD; procDescLimit, fileDescLimit, relFileLimit: CARD; filename ¬ UXStrings.Create[PFS.RopeFromPath[SystemInterface.GetNameOfFile[parsed.file]]]; <> IO.SetIndex[stream, 0]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@magic], 0, 4]]; IF magic = ElfMagic THEN { Print["Found an ELF object\n"]; IO.SetIndex[stream, 0]; wireTables.wSymHeader ¬ ReadElfWireSymHeader[stream]; } ELSE { magic ¬ Basics.BITRSHIFT[LOOPHOLE[magic, WORD], 16]; IF magic = ECOFFMagic THEN { <> wireTables.wHeader ¬ ReadWireHeader[stream, 0, NIL]; wireTables.wAuxHeader ¬ ReadWireAuxHeader[stream, NIL]; wireTables.wSymHeader ¬ ReadWireSymHeader[stream, wireTables.wHeader.symPtr, NIL]; } ELSE { Print["Found unknown magic number %d\n", magic]; ERROR; }; }; <<>> symHeader ¬ wireTables.wSymHeader; <> IO.SetIndex[stream, symHeader.fileDescrPtr]; fileDescLimit ¬ symHeader.fileDescrIndexLimit; wireTables.fileDescr ¬ NEW[SGI.FileDescrTableBody[fileDescLimit]]; FOR i: CARD IN [0..fileDescLimit) DO [] ¬ ReadWireFileDescriptor[stream, LOOPHOLE[@wireTables.fileDescr[i]]]; ENDLOOP; <> IO.SetIndex[stream, symHeader.relFileDescrPtr]; relFileLimit ¬ symHeader.numRelFileDescr; wireTables.relFiles ¬ NEW[SGI.RelFileTableBody[relFileLimit]]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[LOOPHOLE[wireTables.relFiles, CARD]+BYTES[CARD]], 0, relFileLimit*BYTES[SGI.RelFileTableBody]]]; <> IO.SetIndex[stream, wireTables.wSymHeader.procDescrPtr]; procDescLimit ¬ symHeader.procDescrIndexLimit; wireTables.procDescr ¬ NEW[SGI.ProcDescrTableBody[procDescLimit]]; FOR i: CARD IN [0..procDescLimit) DO [] ¬ ReadWireProcDescriptor[stream, LOOPHOLE[@wireTables.procDescr[i]]]; ENDLOOP; <> FixUpProcedureDescrAddrs[header, fileDescLimit, wireTables.fileDescr, wireTables.procDescr]; <> IO.SetIndex[stream, symHeader.symPtr]; symLimit ¬ symHeader.symIndexLimit; wireTables.localSyms ¬ NEW[SGI.LocalSymTableBody[symLimit]]; FOR i: CARD IN [0..symLimit) DO [] ¬ ReadWireSTEntry[stream, LOOPHOLE[@wireTables.localSyms[i]]]; ENDLOOP; <> IO.SetIndex[stream, symHeader.extSymPtr]; extSymLimit ¬ symHeader.extSymIndexLimit; wireTables.extSyms ¬ NEW[SGI.ExtSymTableBody[extSymLimit]]; FOR i: CARD IN [0..extSymLimit) DO [] ¬ ReadWireExtSTEntry[stream, LOOPHOLE[@wireTables.extSyms[i]]]; ENDLOOP; <> <> <> IO.SetIndex[stream, symHeader.auxSymPtr]; auxSymLimit ¬ symHeader.auxSymIndexLimit; wireTables.auxSyms ¬ NEW[SGI.AuxSymTableBody[auxSymLimit]]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[LOOPHOLE[wireTables.auxSyms, CARD]+BYTES[CARD]], 0, auxSymLimit*AuxSymbolSize]]; <> IO.SetIndex[stream, symHeader.symStringPtr]; wireTables.localStrings ¬ NEW[SGI.StringTableBody[symHeader.symStringIndexLimit]]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[LOOPHOLE[wireTables.localStrings, CARD]+BYTES[CARD]], 0, symHeader.symStringIndexLimit]]; <> IO.SetIndex[stream, symHeader.extSymStringPtr]; wireTables.extStrings ¬ NEW[SGI.StringTableBody[symHeader.extSymStringIndexLimit]]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[LOOPHOLE[wireTables.extStrings, CARD]+BYTES[CARD]], 0, symHeader.extSymStringIndexLimit]]; parsed.privateInfo ¬ wireTables; }; RopeFromStream: PROC [stream: IO.STREAM, offset: CARD] RETURNS [name: Rope.ROPE ¬ NIL] = TRUSTED { c: CHAR; IO.SetIndex[stream, offset]; IF IO.EndOf[stream] THEN RETURN[""]; DO c ¬ ' ; c ¬ IO.GetChar[stream]; IF (c = VAL[0]) THEN EXIT; name ¬ name.Concat[Convert.RopeFromChar[from: c, quote: FALSE]]; ENDLOOP; <> <> name ¬ name.Concat[Convert.RopeFromChar[from: ':, quote: FALSE]]; RETURN }; TypeAndClassFromData: PROC [sc: BYTE, st: BYTE ¬ 0] RETURNS [type: StabType, class: StorageClass] = { classVal: CARD ¬ sc; typeVal: CARD ¬ st; <<>> SELECT typeVal FROM SGI.STNil => type ¬ Unspecified; SGI.STGlobal => type ¬ GSym; SGI.STStatic => { IF classVal = SGI.SCBSS OR classVal = SGI.SCSBSS THEN type ¬ LCSym ELSE type ¬ STSym; }; SGI.STParam => type ¬ PSym; SGI.STLocal => type ¬ LSym; SGI.STLabel => type ¬ Unspecified; SGI.STStaticProc, SGI.STProc => type ¬ Fun; SGI.STBlock => type ¬ LBrac; SGI.STEnd => type ¬ RBrac; SGI.STMember => type ¬ LSym; SGI.STTypeDef => type ¬ LSym; SGI.STFile => type ¬ SO; SGI.STConstant => type ¬ Unspecified; ENDCASE => type ¬ Unspecified; SELECT classVal FROM SGI.SCNIL => class ¬ SCNil; SGI.SCTEXT => class ¬ SCText; SGI.SCDATA => class ¬ SCData; SGI.SCBSS => class ¬ SCBss; SGI.SCREGISTER => class ¬ SCRegister; SGI.SCABS => class ¬ SCAbs; SGI.SCUNDEFINED => class ¬ SCUnspecified; SGI.SCBITS => class ¬ SCBits; SGI.SCDBX => class ¬ SCInvalid; SGI.SCREGIMAGE => class ¬ SCRegImage; SGI.SCINFO => class ¬ SCUserStruct; SGI.SCUSERSTRUCT => class ¬ SCUserStruct; SGI.SCSDATA => class ¬ SCSData; SGI.SCSBSS => class ¬ SCSBss; SGI.SCRDATA => class ¬ SCRData; SGI.SCVAR => class ¬ SCCommon; SGI.SCCOMMON => class ¬ SCCommon; SGI.SCSCOMMON => class ¬ SCSCommon; SGI.SCVARREGISTER => class ¬ SCVerRegister; SGI.SCVARIANT => class ¬ SCVariant; SGI.SCUNDEFINE => class ¬ SCSUndefined; ENDCASE => class ¬ SCInvalid }; ReadStabBody: PROC [symTabIndex: CARD, fdIndex: INT32, isExternal: BOOLEAN, wireTables: WireTables, header: Header, stream: IO.STREAM] RETURNS [stab: StabBody] = TRUSTED { size: CARD; rope: Rope.ROPE ¬ NIL; wireSymTabEntry: WireSTEntry; stringBase: INT32 ¬ wireTables.fileDescr[fdIndex].issBase; type: StabType; class: StorageClass; IF (isExternal) THEN { wireSymTabEntry ¬ LOOPHOLE[@wireTables.extSyms[symTabIndex].sym]; rope ¬ RopeFromStream[stream, header.extStringOffset+wireSymTabEntry.symStringIndex]; } ELSE { wireSymTabEntry ¬ LOOPHOLE[@wireTables.localSyms[symTabIndex]]; rope ¬ RopeFromStream[stream, header.stringOffset+stringBase+wireSymTabEntry.symStringIndex]; }; <> size ¬ CalcSymbolSize[symTabIndex, fdIndex, wireTables, isExternal]/8; [type, class] ¬ TypeAndClassFromData[LOOPHOLE[wireSymTabEntry.storageClass], LOOPHOLE[wireSymTabEntry.symbolType]]; stab ¬ [ module: NIL, stabX: symTabIndex, stabType: type, stabStorClass: class, size: size, value: wireSymTabEntry.value, rope: rope, index: wireSymTabEntry.index, extRef: isExternal, fdIndex: fdIndex ]; RETURN }; BasicReadStab: ENTRY PROC [stabX: CARD, fdIndex: INT32, isExternal: BOOLEAN, wireTables: WireTables, header: Header, stream: IO.STREAM] RETURNS[stab: Stab] = { ENABLE UNWIND => NULL; stab ¬ NEW[StabBody]; stab­ ¬ ReadStabBody[stabX, fdIndex, isExternal, wireTables, header, stream]; RETURN }; ReadWireHeader: PROC [stream: IO.STREAM, pos: CARD ¬ 0, wHeader: WireHeader ¬ NIL] RETURNS [WireHeader] = TRUSTED { nBytes: INT; IF (wHeader = NIL) THEN wHeader ¬ NEW[SGI.WireHeaderBody]; IO.SetIndex[stream, pos]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wHeader­], 0, BYTES[SGI.WireHeaderBody]]]; RETURN [wHeader]; }; ReadWireAuxHeader: PROC [stream: IO.STREAM, wAuxHeader: WireAuxHeader ¬ NIL] RETURNS [WireAuxHeader] = TRUSTED { nBytes: INT; IF (wAuxHeader = NIL) THEN wAuxHeader ¬ NEW[SGI.WireAuxHeaderBody]; <> nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wAuxHeader­], 0, BYTES[SGI.WireAuxHeaderBody]]]; RETURN [wAuxHeader]; }; ReadWireSectionHeader: PROC [stream: IO.STREAM, wSectHeader: WireSectionHeader ¬ NIL] RETURNS [WireSectionHeader] = TRUSTED { nBytes: INT; IF (wSectHeader = NIL) THEN wSectHeader ¬ NEW[SGI.WireSectionHeaderBody]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wSectHeader­], 0, BYTES[SGI.WireSectionHeaderBody]]]; RETURN [wSectHeader]; }; ReadWireSymHeader: PROC [stream: IO.STREAM, pos: CARD, wSymHeader: WireSymHeader ¬ NIL] RETURNS [WireSymHeader] = TRUSTED { nBytes: INT; IF (wSymHeader = NIL) THEN wSymHeader ¬ NEW[SGI.WireSymHeaderBody]; IO.SetIndex[stream, pos]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wSymHeader­], 0, BYTES[SGI.WireSymHeaderBody]]]; RETURN [wSymHeader]; }; ReadWireProcDescriptor: PROC [stream: IO.STREAM, wProcDescriptor: WireProcDescriptor ¬ NIL] RETURNS [WireProcDescriptor] = TRUSTED { nBytes: INT; IF (wProcDescriptor = NIL) THEN wProcDescriptor ¬ NEW[SGI.WireProcDescriptorBody]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wProcDescriptor­], 0, BYTES[SGI.WireProcDescriptorBody]]]; RETURN [wProcDescriptor]; }; ReadWireFileDescriptor: PROC [stream: IO.STREAM, wFileDescriptor: WireFileDescriptor ¬ NIL] RETURNS [WireFileDescriptor] = TRUSTED { nBytes: INT; IF (wFileDescriptor = NIL) THEN wFileDescriptor ¬ NEW[SGI.WireFileDescriptorBody]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wFileDescriptor­], 0, BYTES[SGI.WireFileDescriptorBody]]]; RETURN [wFileDescriptor]; }; ReadWireSTEntry: PROC [stream: IO.STREAM, wSTEntry: WireSTEntry ¬ NIL] RETURNS [WireSTEntry] = TRUSTED { nBytes: INT; IF (wSTEntry = NIL) THEN wSTEntry ¬ NEW[SGI.WireSTEntryBody]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wSTEntry­], 0, BYTES[SGI.WireSTEntryBody]]]; RETURN [wSTEntry]; }; ReadWireExtSTEntry: PROC [stream: IO.STREAM, wExtSTEntry: WireExtSTEntry ¬ NIL] RETURNS [WireExtSTEntry] = TRUSTED { nBytes: INT; IF (wExtSTEntry = NIL) THEN wExtSTEntry ¬ NEW[SGI.WireExtSTEntryBody]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wExtSTEntry­], 0, BYTES[SGI.WireExtSTEntryBody]]]; RETURN [wExtSTEntry]; }; <<>> BitsOn: PROC [flags: CARD, mask: CARD] RETURNS [on: BOOL] ~ INLINE { RETURN [Basics.BITAND[flags, mask] # 0] }; ReadELFHeader: ObjectFilesPrivate.ReadHeaderProcType ~ TRUSTED { <> wHeader: ElfWireHeader ¬ NEW[ElfWireHeaderBody]; nBytes: INT ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wHeader­], 0, BYTES[ElfWireHeaderBody]]]; magic: CARD ¬ Basics.Card32FromF[wHeader.magic]; shortMagic: CARD ¬ Basics.BITRSHIFT[LOOPHOLE[magic, WORD], 16]; objType: CARD ¬ Basics.Card16FromH[wHeader.type]; machine: CARD ¬ Basics.Card16FromH[wHeader.machine]; nBadMagic: BOOLEAN ¬ (magic # ElfMagic) OR (wHeader.elfClass # ElfClass32) OR (wHeader.elfData # ElfData2MSB) OR ((objType # ETRelocatable) AND (objType # ETExecutable)) OR (machine # EMMips); nPageSize: CARD ¬ 1000H; textSeg: MemorySegmentInfo ¬ [0, 0]; iDataSeg: MemorySegmentInfo ¬ [0, 0]; symHdrSeg: MemorySegmentInfo ¬ [0, 0]; textRelocSeg: MemorySegmentInfo ¬ [0, 0]; dataRelocSeg: MemorySegmentInfo ¬ [0, 0]; bssSeg: MemorySegmentInfo ¬ [0, 0]; bssSize: CARD32 ¬ 0; sectHdrOffset: CARD ¬ Basics.Card32FromF[wHeader.sectHdrOffset]; sectHdrNum: CARD ¬ Basics.Card16FromH[wHeader.sectHdrNum]; sectionList: SectionList ¬ NEW[SectionListBody[sectHdrNum]]; sectStrTblX: CARD ¬ Basics.Card16FromH[wHeader.sectStrTblX]; textIndex, dataIndex, bssIndex, symtabIndex, symsIndex: CARD ¬ LAST[CARD]; header: Header; wSymHeader: WireSymHeader ¬ NEW[SGI.WireSymHeaderBody]; textLoadOffset: CARD32 ¬ Basics.Card32FromF[wHeader.entry]; IF nBadMagic THEN ERROR; IO.SetIndex[stream, sectHdrOffset]; FOR i: CARD IN [0..sectHdrNum) DO wSectionHeader: ElfWireSectionHeader ¬ NEW[ElfWireSectionHeaderBody]; nBytes: INT ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wSectionHeader­], 0, BYTES[ElfWireSectionHeaderBody]]]; sectionList[i] ¬ NEW[SectionHeaderBody]; sectionList[i].nameIndex ¬ Basics.Card32FromF[wSectionHeader.nameIndex]; sectionList[i].type ¬ Basics.Card32FromF[wSectionHeader.type]; sectionList[i].flags ¬ Basics.Card32FromF[wSectionHeader.flags]; sectionList[i].addr ¬ Basics.Card32FromF[wSectionHeader.addr]; sectionList[i].offset ¬ Basics.Card32FromF[wSectionHeader.offset]; sectionList[i].size ¬ Basics.Card32FromF[wSectionHeader.size]; sectionList[i].link ¬ Basics.Card32FromF[wSectionHeader.link]; sectionList[i].info ¬ Basics.Card32FromF[wSectionHeader.info]; sectionList[i].alignment ¬ Basics.Card32FromF[wSectionHeader.alignment]; sectionList[i].entrySize ¬ Basics.Card32FromF[wSectionHeader.entrySize]; ENDLOOP; IO.SetIndex[stream, sectionList[sectStrTblX].offset]; FOR i: CARD IN [0..sectHdrNum) DO SELECT TRUE FROM (sectionList[i].type = SHTProgBits) AND BitsOn[sectionList[i].flags, SHFAlloc] => { IF NOT BitsOn[sectionList[i].flags, SHFWrite] THEN { IF textIndex = LAST[CARD] THEN { textSeg ¬ [sectionList[i].offset, sectionList[i].size]; textIndex ¬ i; } ELSE textSeg.byteLength ¬ textSeg.byteLength + sectionList[i].size; } ELSE { IF dataIndex = LAST[CARD] THEN { iDataSeg ¬ [sectionList[i].offset, sectionList[i].size]; dataIndex ¬ i; } ELSE iDataSeg.byteLength ¬ iDataSeg.byteLength + sectionList[i].size; }; }; (sectionList[i].type = SHTNoBits) AND BitsOn[sectionList[i].flags, SHFWrite] => { IF bssIndex = LAST[CARD] THEN { bssSize ¬ bssSize + sectionList[i].size; bssIndex ¬ i; bssSeg ¬ [sectionList[i].offset, sectionList[i].size]; }; }; (sectionList[i].type = SHTRela) OR (sectionList[i].type = SHTRel) => { IF sectionList[i].info = textIndex THEN textRelocSeg ¬ [sectionList[i].offset, sectionList[i].size] ELSE IF sectionList[i].info = dataIndex THEN dataRelocSeg ¬ [sectionList[i].offset, sectionList[i].size]; }; (sectionList[i].type = SHTMipsDebug) => { <> [] ¬ ReadWireSymHeader[stream, sectionList[i].offset, wSymHeader]; symHdrSeg ¬ [sectionList[i].offset, sectionList[i].size]; }; ENDCASE; ENDLOOP; header ¬ NEW[HeaderBody ¬ [ dynamic: objType = ETDynamicLib, toolversion: BYTE[0] -- wHeader.version --, machtype: machine, magic: shortMagic, text: textSeg, iData: iDataSeg, textReloc: textRelocSeg, dataReloc: dataRelocSeg, syms: symHdrSeg, debug: [0, 0], linno: [0, 0], textLoadOffset: textLoadOffset, bssSize: bssSize, entryPoint: Basics.Card32FromF[wHeader.entry], nPageSize: nPageSize, nEntries: wSymHeader.symIndexLimit, stringOffset: wSymHeader.symStringPtr, extStringOffset: wSymHeader.extSymStringPtr ]]; RETURN[header]; }; ReadHeader: PROC [stream: IO.STREAM] RETURNS [Header] = TRUSTED { wHeader: WireHeader; wAuxHeader: WireAuxHeader; wSymHeader: WireSymHeader; magic: CARD; nBytes: CARD; dataRelocSeg: MemorySegmentInfo ¬ [0, 0]; bssRelocSeg: MemorySegmentInfo ¬ [0, 0]; textRawData, dataRawData, bssRawData, textRelocSeg: MemorySegmentInfo ¬ [0, 0]; header: Header; numSects: CARD; sectionTable: SectionTable; sectionName: ROPE ¬ NIL; ch: CHAR; <<>> <> IO.SetIndex[stream, 0]; nBytes ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@magic], 0, 4]]; IF magic = ElfMagic THEN { IO.SetIndex[stream, 0]; RETURN[ReadELFHeader[stream]]}; magic ¬ Basics.BITRSHIFT[LOOPHOLE[magic, WORD], 16]; IF magic # ECOFFMagic THEN ERROR; wHeader ¬ ReadWireHeader[stream, 0, NIL]; wAuxHeader ¬ ReadWireAuxHeader[stream, NIL]; wSymHeader ¬ NEW[SGI.WireSymHeaderBody]; magic ¬ wHeader.magic; numSects ¬ wHeader.numSections; sectionTable ¬ NEW[SGI.SectionTableBody[numSects]]; <> FOR i: CARD IN [0..numSects) DO <> [] ¬ ReadWireSectionHeader[stream, LOOPHOLE[@sectionTable[i]]]; ENDLOOP; <> FOR i: CARD IN [0..numSects) DO FOR j: CARD IN [0..8) DO IF (sectionTable[i].name[j] = 0) THEN EXIT; ch ¬ VAL[sectionTable[i].name[j]]; sectionName ¬ sectionName.Concat[Rope.FromChar[ch]]; ENDLOOP; IF Rope.Equal[sectionName, ".text", TRUE] THEN { textRawData ¬ [sectionTable[i].dataPtr, sectionTable[i].size]; textRelocSeg ¬ [sectionTable[i].relocPtr, sectionTable[i].numRelocEntries * RelocEntrySize] } ELSE IF Rope.Equal[sectionName, ".data", TRUE] THEN { dataRawData ¬ [sectionTable[i].dataPtr, sectionTable[i].size]; dataRelocSeg ¬ [sectionTable[i].vAddr, sectionTable[i].numRelocEntries * RelocEntrySize]; } ELSE IF Rope.Equal[sectionName, ".bss", TRUE] THEN { bssRawData ¬ [sectionTable[i].dataPtr, sectionTable[i].size]; }; FREE[@sectionName]; sectionName ¬ NIL; ENDLOOP; [] ¬ ReadWireSymHeader[stream, wHeader.symPtr, wSymHeader]; <<>> <> header ¬ NEW[HeaderBody ¬ [ dynamic: FALSE, toolversion: BYTE[0], machtype: BYTE[0], magic: magic, text: textRawData, iData: dataRawData, textReloc: textRelocSeg, dataReloc: dataRelocSeg, syms: [0, 0], debug: [0, 0], linno: [0, 0], textLoadOffset: wAuxHeader.textBase, bssSize: wAuxHeader.bssSize, entryPoint: wAuxHeader.entryPtr, nPageSize: nPageSize, nEntries: wSymHeader.symIndexLimit, stringOffset: wSymHeader.symStringPtr, extStringOffset: wSymHeader.extSymStringPtr ]]; RETURN[header]; }; <<========================================================================>> <> <<>> <> <> <> <> <<========================================================================>> AlternativeFindModuleStabRange: PROC [header: Header, fileDescr: FileDescrTable, procDescr: ProcDescrTable, symHeader: WireSymHeader, relativePC: CARD] RETURNS [sr: StabRange, pcRange: StabRange ¬ [0, 0], fdIndex: INT32 ¬ 0] = { IF header = NIL THEN RETURN[[0, 0], [0, 0], 0] ELSE { pcCount: CARD ¬ 0; minPC: CARD ¬ LAST[CARD]; indexFirstSym, numSyms, numInstructions: INT32; i, indexFirstProc: INT16; startAddress, textOffset: CARD32; absolutePC: CARD ¬ 0; numFileDescr: INT32 ¬ symHeader.fileDescrIndexLimit; <<>> textOffset ¬ header.textLoadOffset; absolutePC ¬ textOffset + relativePC; FOR i IN [0..numFileDescr) DO startAddress ¬ fileDescr[i].startAddress; IF absolutePC < startAddress THEN { IF i = 0 THEN RETURN[[0, 0], [0, 0], 0]; fdIndex ¬ i - 1; startAddress ¬ fileDescr[fdIndex].startAddress; WHILE fdIndex > 1 AND startAddress = fileDescr[fdIndex-1].startAddress AND fileDescr[fdIndex].fMerge # 0 DO fdIndex ¬ fdIndex - 1; ENDLOOP; EXIT; } ENDLOOP; IF (fdIndex > numFileDescr) THEN RETURN[[0, 0], [0, 0], 0]; startAddress ¬ fileDescr[fdIndex].startAddress; indexFirstProc ¬ fileDescr[fdIndex].ipdFirst; minPC ¬ procDescr[indexFirstProc].startAddress + textOffset; numInstructions ¬ fileDescr[fdIndex].cline; pcCount ¬ 4 * numInstructions; indexFirstSym ¬ fileDescr[fdIndex].isymBase; numSyms ¬ fileDescr[fdIndex].csym; IF (absolutePC < (minPC + pcCount)) THEN RETURN[[ indexFirstSym, numSyms], [minPC-textOffset, pcCount], fdIndex]; RETURN[[0, 0], [0, 0], 0]; }; }; <<========================================================================>> <> <<>> <> <> <<========================================================================>> GetExtStabList: PROC [fdIndex: INT32, wireTables: WireTables, header: Header, stream: IO.STREAM] RETURNS [extStabList: LIST OF Stab, numExtSyms: CARD] = TRUSTED { i: CARD; totNumExtSyms: CARD ¬ wireTables.wSymHeader.extSymIndexLimit; lastElem: LIST OF Stab ¬ NIL; newStab: Stab; numExtSyms ¬ 0; extStabList ¬ NIL; FOR i IN [0..totNumExtSyms) DO <> <> IF (wireTables.extSyms[i].fileDescrIndex = CARD16[fdIndex]) THEN { newStab ¬ BasicReadStab[i, fdIndex, TRUE, wireTables, header, stream]; IF (extStabList = NIL) THEN { extStabList ¬ LIST[newStab]; -- make one element list holding new Stab lastElem ¬ extStabList; } ELSE { lastElem.rest ¬ LIST[newStab]; lastElem ¬ lastElem.rest; }; lastElem.rest ¬ NIL; numExtSyms ¬ numExtSyms + 1; }; ENDLOOP; }; <<========================================================================>> <> <<========================================================================>> CreateModule: PROC [parsed: Parsed, fdIndex: INT32, wireTables: WireTables, stream: IO.STREAM, stabRange, pcRange: StabRange ¬ [0, 0]] RETURNS [Module] = TRUSTED { module: Module ¬ NEW[ModuleBody]; nStabs: CARD ¬ stabRange.count; currentIndex: CARD; I: CARD ¬ 0; nExtStabs: CARD; extStabList, thisExtStab: LIST OF Stab ¬ NIL; stab: Stab; lineNumbers: LineNum ¬ NIL; stringBase: INT32 ¬ wireTables.fileDescr[fdIndex].issBase; fileNameOffset: INT32 ¬ wireTables.fileDescr[fdIndex].rss; filename: UXStrings.CString; [extStabList, nExtStabs] ¬ GetExtStabList[fdIndex, wireTables, parsed.header, stream]; <> module.whole ¬ parsed; <> <> <> <> module.firstStabX ¬ stabRange.first; module.limitStabX ¬ stabRange.first + nStabs + nExtStabs; module.firstPC ¬ pcRange.first; module.limitPC ¬ pcRange.first + pcRange.count; module.stabs ¬ NEW[StabSet[nStabs + nExtStabs]]; module.fdIndex ¬ fdIndex; <> <<(we also relocate the pc value of bracket stabs.)>> currentIndex ¬ 0; I ¬ 0; WHILE (I < nStabs) DO <> module.stabs[currentIndex] ¬ BasicReadStab[stabRange.first+I, fdIndex, FALSE, wireTables, parsed.header, stream]; stab ¬ module.stabs[currentIndex]; stab.module ¬ module; IF (stab.stabType = LBrac) OR (stab.stabType = RBrac) THEN -- relocate bracket pcs stab.value ¬ stab.value + module.firstPC; IF (stab.stabType = Fun) THEN stab.value ¬ stab.value - parsed.header.textLoadOffset; currentIndex ¬ currentIndex + 1; I ¬ I + 1; ENDLOOP; <> <> <> FOR thisExtStab ¬ extStabList, thisExtStab.rest WHILE (thisExtStab # NIL) DO module.stabs[currentIndex] ¬ thisExtStab.first; currentIndex ¬ currentIndex + 1 ENDLOOP; module.fileName ¬ PFS.PathFromRope[RopeFromStream[stream, parsed.header.stringOffset+stringBase+fileNameOffset]]; filename ¬ UXStrings.Create[PFS.RopeFromPath[module.fileName]]; <> module.staticVarsInstalled ¬ FALSE; module.versionStampInfo ¬ NIL; module.outerBracket ¬ NEW[BracketPairBody ¬ [ module: module, kind: syntheticOuter, firstX: 0, limitX: module.whole.header.nEntries, firstPC: module.firstPC, pcLimit: module.limitPC, funIndex: 0, symbols: NIL, innerBrackets: NIL ]]; <<>> <> <<>> <> <> <> RETURN[module]; }; <<========================================================================>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<========================================================================>> SGIModuleFromParsedAndPC: PROC [whole: Parsed, spc: FileSegmentPC, moduleRope: Rope.ROPE ¬ NIL] RETURNS [newModule: Module ¬ NIL] = TRUSTED { stabRange, pcRange: StabRange; stream: IO.STREAM; nBytes, fdIndex: INT32 ¬ 0; firstPC: CARD32; newElem, prevElem, modules: LIST OF Module; wireTables: WireTables ¬ NIL; <<>> IF whole = NIL THEN RETURN ELSE { stream ¬ SystemInterface.GetStreamForFile [whole.file]; IF (whole.privateInfo = NIL) THEN InitParsedWireTables [stream, whole]; wireTables ¬ NARROW [whole.privateInfo, WireTables]; [stabRange, pcRange, fdIndex] ¬ AlternativeFindModuleStabRange [whole.header, wireTables.fileDescr, wireTables.procDescr, wireTables.wSymHeader, spc.relPC]; <> <> stream ¬ SystemInterface.GetStreamForFile[whole.file]; <> { <> ENABLE UNWIND => SystemInterface.ReleaseStreamForFile[whole.file, stream]; firstPC ¬ pcRange.first; prevElem ¬ NIL; IF whole.modules = NIL THEN { newModule ¬ CreateModule[whole, fdIndex, wireTables, stream, stabRange, pcRange]; newElem ¬ LIST[newModule]; -- make one element list holding new module newElem.rest ¬ modules; <> IF (prevElem = NIL) THEN whole.modules ¬ newElem ELSE prevElem.rest ¬ newElem; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN; }; FOR modules ¬ whole.modules, modules.rest WHILE (modules # NIL) DO <> IF (modules.first.firstPC = firstPC) THEN -- we already have it { SystemInterface.ReleaseStreamForFile[whole.file, stream]; newModule ¬ modules.first; RETURN }; IF (firstPC < modules.first.firstPC) THEN { -- we should have found it by now newModule ¬ CreateModule[whole, fdIndex, wireTables, stream, stabRange, pcRange]; newElem ¬ LIST[newModule]; -- make one element list holding new module newElem.rest ¬ modules; <> IF (prevElem = NIL) THEN whole.modules ¬ newElem ELSE prevElem.rest ¬ newElem; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN; }; prevElem ¬ modules; ENDLOOP; }; { newModule: Module ¬ CreateModule[whole, fdIndex, wireTables, stream, stabRange, pcRange]; cell: LIST OF Module ¬ LIST[newModule]; IF prevElem # NIL THEN prevElem.rest ¬ cell ELSE whole.modules ¬ cell; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[newModule]; }; }; }; <<========================================================================>> <> <> <> <<========================================================================>> SGIVarLocFromStab: PROC [stab: Stab] RETURNS [ObjectFiles.VarLoc] = { header: Header ~ stab.module.whole.header; wireTables: WireTables ¬ NARROW[stab.module.whole.privateInfo, WireTables]; MkSegment: PROC [kind: ObjectFiles.SimpleSeg] RETURNS [ObjectFiles.VarLoc] ~ { segRope: Rope.ROPE; fileByteOffset: CARD; bitOffset: CARD; segBase: CARD ~ SELECT kind FROM text => 0, <> data => header.dataReloc.byteOffset, bss => wireTables.wAuxHeader.bssBase, ENDCASE => ERROR; IF stab.value < segBase THEN ObjectFiles.UnreadableObjectFile[IO.PutFLR["value (%xH) less than segment base (%xH) for symbol %g in %g", LIST[[cardinal[stab.value]], [cardinal[segBase]], [rope[ObjectFiles.CNameOfStab[stab]]], [rope[ObjectFiles.DescribeModule[stab.module]]]] ]]; SELECT kind FROM text => { segRope ¬ "text"; bitOffset ¬ (stab.value-segBase)*8; fileByteOffset ¬ stab.value-segBase+header.text.byteOffset; }; data => { segRope ¬ "data"; bitOffset ¬ (stab.value-segBase)*8; fileByteOffset ¬ stab.value-segBase+header.iData.byteOffset; }; bss => { segRope ¬ "bss"; bitOffset ¬ (stab.value-segBase)*8; fileByteOffset ¬ stab.value-segBase+header.iData.byteOffset; }; ENDCASE => ERROR; RETURN [NEW [ObjectFiles.VarLocBody ¬ [ bitSize: IF stab.size#0 THEN stab.size*8 ELSE unspecdBitSize, where: fSegment[ [0, segRope], bitOffset, fileByteOffset] ]]]}; SELECT stab.stabType FROM Fun => RETURN MkSegment[text]; STSym => RETURN MkSegment[data]; LCSym => RETURN MkSegment[bss]; LSym, PSym => { byteOffset: INT ~ LOOPHOLE[stab.value]; vLB: ObjectFiles.VarLoc; IF stab.stabType=PSym AND stab.size>4 AND stab.size # LAST[CARD] THEN vLB ¬ NEW[ObjectFiles.VarLocBody ¬ [ bitSize: stab.size*8, where: indirect[ base: NEW[ObjectFiles.VarLocBody ¬ [ bitSize: 32, where: frame[bitOffset: 8*byteOffset]]], offset: CirioTypes.zeroBA]]] ELSE vLB ¬ NEW[ObjectFiles.VarLocBody ¬ [ bitSize: IF stab.size#0 THEN stab.size*8 ELSE unspecdBitSize, where: frame[bitOffset: 8*byteOffset]]]; RETURN[vLB]}; RSym => { sz: CARD ~ IF stab.size#LAST[CARD] AND stab.size#0 THEN stab.size*8 ELSE unspecdBitSize; vLB: ObjectFiles.VarLoc; IF stab.size>4 AND stab.size # LAST[CARD] THEN vLB ¬ NEW[ObjectFiles.VarLocBody ¬ [ bitSize: sz, where: indirect[ base: NEW[ObjectFiles.VarLocBody ¬ [ bitSize: 32, where: register[regNum: stab.value]]], offset: CirioTypes.zeroBA]]] ELSE vLB ¬ NEW[ObjectFiles.VarLocBody ¬ [ bitSize: sz, where: register[regNum: stab.value]]]; RETURN[vLB] }; GSym => RETURN [NEW [ObjectFiles.VarLocBody ¬ [ bitSize: IF stab.size#0 THEN stab.size*8 ELSE unspecdBitSize, where: namedCommon[ObjectFiles.CNameOfStab[stab], 0, 0, FALSE, FALSE] ]]]; ENDCASE => RETURN ObjectFiles.MakeUnknownVarLoc[IO.PutFR["unrecognized stabType (%02xH) for %g", [cardinal[ORD[stab.stabType]]], [rope[ObjectFiles.CNameOfStab[stab]]] ]]; }; <<========================================================================>> <> <<>> <> <> <> <> <<========================================================================>> ScanOneBracketPairSequence: PROC [module: Module, fun: Stab, funIndex: CARD, firstX: CARD, unclaimedHead, unclaimedTail: StabList] RETURNS [--finalRBracX-- CARD, --innerBrackets-- LIST OF BracketPair, --head of unclaimed symbols-- StabList] = { innerBrackets: LIST OF BracketPair ¬ NIL; lastInnerBracket: LIST OF BracketPair ¬ NIL; x: CARD ¬ firstX; symHead, symTail: StabList ¬ NIL; DO xAfterSymbs: CARD; stabAfterSymbs: Stab; [xAfterSymbs, symHead, symTail] ¬ ObjectFilesPrivate.ScanSymbolStabs[module, x, symHead, symTail]; IF xAfterSymbs >= module.limitStabX THEN { IF unclaimedTail#NIL THEN unclaimedTail.rest ¬ symHead ELSE unclaimedHead ¬ symHead; RETURN[xAfterSymbs, innerBrackets, unclaimedHead]}; stabAfterSymbs ¬ ObjectFilesPrivate.ReadStab[module, xAfterSymbs]; SELECT stabAfterSymbs.stabType FROM LBrac => { finalRBracX: CARD; nestedInnerBrackets: LIST OF BracketPair; bracket: BracketPair; bracketCell: LIST OF BracketPair; [finalRBracX, nestedInnerBrackets, symHead] ¬ ScanOneBracketPairSequence[module, fun, funIndex, xAfterSymbs+1, symHead, symTail]; bracket ¬ NEW[BracketPairBody¬[ module: module, kind: actual, firstX: stabAfterSymbs.stabX, limitX: finalRBracX+1, firstPC: stabAfterSymbs.value, pcLimit: IF finalRBracX { IF unclaimedTail#NIL THEN unclaimedTail.rest ¬ symHead ELSE unclaimedHead ¬ symHead; RETURN[xAfterSymbs, innerBrackets, unclaimedHead]}; ENDCASE => ERROR; -- can't happen ENDLOOP }; SGIInstallBracketPairsForOneFunStab: PROC [module: Module, funStabIndex: CARD] = { wasScanned: BOOLEAN ¬ module.funStabs[funStabIndex].bracketsScanned; module.funStabs[funStabIndex].bracketsScanned ¬ TRUE; -- if error occurs, then we won't do this again. IF NOT wasScanned THEN { funStab: Stab ¬ module.funStabs[funStabIndex].stab; paramNames, lastParamName: LIST OF Rope.ROPE ¬ NIL; paramStabs, lastParamStab: LIST OF Stab ¬ NIL; -- includes param mod stabs x: CARD ¬ funStab.stabX+1; good: BOOL ¬ TRUE; <<>> module.funStabs[funStabIndex].brackets ¬ NEW[BracketPairBody¬[ module: module, kind: syntheticFun, firstX: funStab.stabX, limitX: 0, firstPC: funStab.value, pcLimit: 0, funStab: funStab, funIndex: funStabIndex, symbols: NIL, innerBrackets: NIL]]; <> <<>> <> <> <> <> <<>> <> WHILE x < module.limitStabX DO stab: Stab ¬ ObjectFilesPrivate.ReadStab[module, x]; TakeBP: PROC ~ { finalRBracX: CARD; [finalRBracX, module.funStabs[funStabIndex].brackets.innerBrackets, paramStabs] ¬ ScanOneBracketPairSequence[module, funStab, funStabIndex, x, paramStabs, lastParamStab]; IF good THEN module.funStabs[funStabIndex].brackets.limitX ¬ finalRBracX+1; module.funStabs[funStabIndex].brackets.pcLimit ¬ IF finalRBracX { stabCell: LIST OF Stab ¬ LIST[stab]; name: Rope.ROPE ¬ ObjectFiles.CNameOfStab[stab]; nameCell: LIST OF Rope.ROPE ¬ LIST[name]; IF paramStabs#NIL AND stab=paramStabs.first THEN ERROR; IF paramNames = NIL THEN paramNames ¬ nameCell ELSE lastParamName.rest ¬ nameCell; lastParamName ¬ nameCell; IF paramStabs = NIL THEN paramStabs ¬ stabCell ELSE lastParamStab.rest ¬ stabCell; lastParamStab ¬ stabCell}; RSym, LSym => { stabCell: LIST OF Stab ¬ LIST[stab]; name: Rope.ROPE ¬ ObjectFiles.CNameOfStab[stab]; isAParam: BOOLEAN ¬ FALSE; -- initial value FOR pNames: LIST OF Rope.ROPE ¬ paramNames, pNames.rest WHILE pNames # NIL DO IF Rope.Equal[name, pNames.first] THEN {isAParam ¬ TRUE; EXIT}; ENDLOOP; IF isAParam THEN { IF paramStabs = NIL THEN paramStabs ¬ stabCell ELSE lastParamStab.rest ¬ stabCell; lastParamStab ¬ stabCell} ELSE -- we are facing the first symbol of a nested block {TakeBP[]; EXIT}; }; GSym, LCSym, STSym => IF good THEN { module.funStabs[funStabIndex].brackets.limitX ¬ stab.stabX; good ¬ FALSE}; SLine, Unspecified => NULL; LBrac => {TakeBP[]; EXIT}; Fun => { IF good THEN module.funStabs[funStabIndex].brackets.limitX ¬ stab.stabX; module.funStabs[funStabIndex].brackets.pcLimit ¬ stab.value; EXIT}; ENDCASE => ObjectFilesPrivate.RaiseUnreadableObjectFileForFun[ IO.PutFR["Unexpected stab (of stabType %02xH) in intro to %g", [rope[ObjectFiles.RopeForStabType[stab.stabType]]], [rope[ObjectFiles.CNameOfStab[funStab]]] ], module, funStab]; x ¬ x + 1; REPEAT FINISHED => { IF good THEN module.funStabs[funStabIndex].brackets.limitX ¬ module.limitStabX; module.funStabs[funStabIndex].brackets.pcLimit ¬ module.limitPC; }; ENDLOOP; module.funStabs[funStabIndex].brackets.symbols ¬ paramStabs; }; RETURN; }; SGIScanModuleStructure: PROC [module: Module, perFn: ObjectFilesPrivate.FnConsumer] ~ { I: CARD ¬ 0; WHILE I < module.stabs.nStabs DO stab: Stab ¬ module.stabs[I]; IF stab.module = NIL THEN I ¬ I+1 ELSE SELECT stab.stabType FROM GSym, LCSym, STSym, LSym => I ¬ I + 1; Fun => {funStab: Stab ~ stab; firstLocal: Stab ¬ NIL; WHILE I+1 < module.stabs.nStabs DO I ¬ I + 1; stab ¬ module.stabs[I]; IF stab.module = NIL THEN LOOP; SELECT stab.stabType FROM PSym => NULL; LBrac => {firstLocal ¬ module.stabs[I]; EXIT}; Invalid, Unspecified , SO => NULL; ENDCASE => SystemInterface.ShowReport[IO.PutFR["Found %g stab while scanning the arguments for function %g in %g", [rope[ObjectFiles.RopeForStabType[stab.stabType]]], [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; ENDLOOP; I ¬ perFn[funStab, firstLocal, I+module.firstStabX] - module.firstStabX}; Invalid, Unspecified, SO => I ¬ I + 1; RBrac, LBrac => {I ¬ I + 1;}; ENDCASE => { SystemInterface.ShowReport[IO.PutFR["Found %g stab while scanning in the global space of %g", [rope[ObjectFiles.RopeForStabType[stab.stabType]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; I ¬ I + 1}; ENDLOOP; RETURN}; SGIScanFnStructure: PROC [module: Module, funStab: Stab, firstLocal: Stab ¬ NIL, nextX: CARD, perParm: PROC [Stab] ¬ NIL, perBracket: ObjectFilesPrivate.BracketConsumer ¬ NIL] RETURNS [limitX, limitPc: CARD] ~ { IF perParm#NIL THEN PassParams[module, funStab, funStab.stabX+1, nextX, perParm]; IF firstLocal=NIL THEN limitX ¬ nextX ELSE limitX ¬ DoBrack[module, funStab, firstLocal, perBracket]; FOR K: CARD ¬ limitX-module.firstStabX, K+1 WHILE K < module.stabs.nStabs DO stab: Stab ¬ module.stabs[K]; IF stab.module = NIL THEN LOOP; SELECT stab.stabType FROM Fun => RETURN [limitX, stab.value]; ENDCASE => NULL; ENDLOOP; RETURN [limitX, module.limitPC]}; DoBrack: PROC [module: Module, funStab, first: Stab, perSubBracket: ObjectFilesPrivate.BracketConsumer] RETURNS [limitX: CARD] ~ { IF perSubBracket#NIL THEN limitX ¬ perSubBracket[first] ELSE limitX ¬ SGIScanBktStructure[module, funStab, first, NIL, NIL].limitX; RETURN}; SGIScanBktStructure: PROC [module: Module, funStab, first: Stab, perLocal: PROC [Stab] ¬ NIL, perSubBracket: ObjectFilesPrivate.BracketConsumer ¬ NIL] RETURNS [limitX, firstPc, limitPc: CARD] ~ { I: CARD ¬ first.stabX - module.firstStabX; stab: Stab; FOR I ¬ I, I+1 WHILE I < module.stabs.nStabs DO stab ¬ module.stabs[I]; IF stab.module = NIL THEN LOOP; SELECT stab.stabType FROM STSym, LSym => IF perLocal#NIL THEN perLocal[stab]; LBrac => { J: CARD ¬ I+1; firstPc ¬ stab.value+funStab.value; WHILE J < module.stabs.nStabs DO stab ¬ module.stabs[J]; IF stab.module = NIL THEN J ¬ J+1 ELSE SELECT stab.stabType FROM RBrac => RETURN [J+1+module.firstStabX, firstPc, stab.value+funStab.value]; STSym, LSym, LBrac => J ¬ DoBrack[module, funStab, stab, perSubBracket] - module.firstStabX; Invalid, Unspecified, SO => J ¬ J +1; Fun => {--Since we're debugging C, which has no nested functions, this shouldn't happen; if it does, we assume the bracket parsing has failed and re-synch with top level enumeration of functions SystemInterface.ShowReport[IO.PutFR["Found FUN stab after an LBRAC in function %g in %g", [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; RETURN [J+module.firstStabX, firstPc, stab.value]}; ENDCASE => SystemInterface.ShowReport[IO.PutFR["Found %g stab after an LBRAC in function %g in %g", [rope[ObjectFiles.RopeForStabType[stab.stabType]]], [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; ENDLOOP; SystemInterface.ShowReport[IO.PutFR["Missed an RBRAC in function %g in %g", [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; RETURN[J+module.firstStabX, firstPc, module.limitPC]}; Fun => {--shouldn't happen, but ... SystemInterface.ShowReport[IO.PutFR["Found FUN stab before an LBRAC in function %g in %g", [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; }; Invalid, Unspecified, SO => NULL; RBrac => { firstPc ¬ first.value+funStab.value; RETURN[I+module.firstStabX, firstPc, stab.value+funStab.value]; }; ENDCASE => SystemInterface.ShowReport[IO.PutFR["Found %g stab before an LBRAC in function %g in %g", [rope[ObjectFiles.RopeForStabType[stab.stabType]]], [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; ENDLOOP; SystemInterface.ShowReport[IO.PutFR["Missed an LBRAC in function %g in %g", [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; RETURN[I+module.firstStabX, module.limitPC, module.limitPC]}; PassParams: PROC [module: Module, funStab: Stab, firstX, limitX: CARD, to: PROC [Stab]] ~ { FOR I: CARD IN [firstX - module.firstStabX .. limitX-module.firstStabX) DO stab: Stab ¬ module.stabs[I]; IF stab.module#NIL THEN SELECT stab.stabType FROM PSym, RSym, LSym, STSym => to[stab]; Invalid, Unspecified, SO => NULL; RBrac => RETURN; ENDCASE => SystemInterface.ShowReport[IO.PutFR["Found %g stab in parms of %g in %g", [rope[ObjectFiles.RopeForStabType[stab.stabType]]], [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; ENDLOOP; RETURN}; <<========================================================================>> <> <> <<>> <> <> <<========================================================================>> SGIInstallStaticVars: PROC [module: Module] = { IF NOT module.staticVarsInstalled THEN FOR x: CARD IN [module.firstStabX..module.limitStabX) DO stab: Stab ¬ ObjectFilesPrivate.ReadStab[module, x]; IF stab = NIL THEN LOOP; IF stab.stabType = Fun THEN EXIT; IF stab.stabType = STSym OR stab.stabType = LCSym THEN { IF module.versionStampStab = NIL THEN { gvi: ObjectFiles.GlobalVarLoc ¬ NIL; gvi ¬ NARROW[ObjectFilesPrivate.CheckStaticVar[stab, "versionStamp", TRUE]]; IF gvi # NIL THEN { dataRope: Rope.ROPE ¬ ObjectFilesPrivate.ReadInitialDataAsRope[module, gvi.fileByteOffset]; module.versionStampStab ¬ stab; module.versionStampInfo ¬ NEW[ObjectFiles.VersionStampInfo¬[gvi, dataRope]]; LOOP; }; }; IF module.globalFrameStab = NIL THEN { gvi: ObjectFiles.GlobalVarLoc ¬ NIL; gvi ¬ NARROW[ObjectFilesPrivate.CheckStaticVar[stab, "globalframe", TRUE]]; IF gvi # NIL THEN { module.globalFrameStab ¬ stab; module.globalFrameGvl ¬ gvi; LOOP; }; }; }; ENDLOOP; module.staticVarsInstalled ¬ TRUE; }; <<========================================================================>> <> <<========================================================================>> SGIAlterFunStab: PROC [module: Module, funStabX: CARD] RETURNS [Stab] = { RETURN [module.funStabs[funStabX].stab]; }; SGIGetSPOffset: ObjectFilesPrivate.GetSPOffsetType ~ TRUSTED { privateModule: ObjectFilesPrivate.Module ¬ LOOPHOLE[module]; parsed: ObjectFiles.Parsed ¬ LOOPHOLE[privateModule.whole, ObjectFiles.Parsed]; absPC: CARD ¬ spc.relPC + parsed.header.textLoadOffset; currentPDR: SGI.WireProcDescriptorBody; found: BOOLEAN; spOffset: INT; [currentPDR, found] ¬ FindMatchingProcDescr [absPC, parsed]; IF found = FALSE THEN spOffset ¬ 0 ELSE spOffset ¬ LOOPHOLE[currentPDR.frameoffset]; RETURN[spOffset]; }; <<>> <> <<>> <<========================================================================>> <> <<========================================================================>> RandomTestFindStabRange: PROC [cmd: Commander.Handle] RETURNS [result: REF ¬ NIL, msg: ROPE ¬ NIL] = { args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; path: PATH ¬ PFS.PathFromRope[args[1]]; range: StabRange; pc: CARD; fileSet: SystemInterface.FileSet ¬ SystemInterface.CreateFileSet[]; wireTables: WireTables ¬ NIL; { ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; file: SystemInterface.CirioFile ¬ SystemInterface.GetCirioFile[fileSet, path]; nextSeed: INT ¬ IF args.argc < 3 THEN 4466 ELSE Convert.IntFromRope[args[2]]; start: BasicTime.GMT ¬ BasicTime.Now[]; WHILE TRUE DO rs: Random.RandomStream ¬ Random.Create[seed: nextSeed]; whole: Parsed ¬ ObjectFiles.CreateParsed[file, "SGI"]; wireTables ¬ NARROW[whole.privateInfo, WireTables]; IO.PutF[cmd.out, "beginning seed = %g at %g\N", IO.card[nextSeed], IO.time[start]]; FOR I: INT IN [0..100) DO pc ¬ Random.ChooseInt[rs, 0, whole.header.text.byteLength]; [range, [, ], ] ¬ AlternativeFindModuleStabRange[whole.header, wireTables.fileDescr, wireTables.procDescr, wireTables.wSymHeader, pc]; IO.PutF[cmd.out, "\Tpc = %g gives firstX: %g count: %g\N", IO.card[pc], IO.card[range.first], IO.card[range.count]]; ENDLOOP; ENDLOOP; }; SystemInterface.CloseFileSet[fileSet]; }; <
> <<>> transTable: ObjectFilesPrivate.TranslationTable ¬ NEW[ ObjectFilesPrivate.TranslationTableBody[3]]; <<>> <> <> <<>> <> transTable[0] ¬ [0, 2, ECOFFMagic, "SGI"]; -- byteOffset,length,compareValue,format transTable[1] ¬ [0, 4, ElfMagic, "SGI", first]; -- the SGI elf magic sequence transTable[2] ¬ [18, 2, EMMips, "SGI", last]; Commander.Register["sgiRandomTestFindStabRange", RandomTestFindStabRange]; ObjectFilesPrivate.RegisterObjectFileFlavor[ NEW [ ObjectFilesPrivate.ObjectFileFlavorBody ¬ [ "SGI", SGIOBJ, ReadHeader, SGIModuleFromParsedAndPC, SGIVarLocFromStab, NIL, NIL, SGIScanModuleStructure, SGIScanFnStructure, SGIScanBktStructure, TRUE, SGIInstallStaticVars, SGIAlterFunStab, SGIGetSPOffset ]], transTable]; END..