<<>> <> <> <> <> DIRECTORY Basics USING [BITAND, BITLSHIFT, BITSHIFT, Card16FromH, Card32FromF, Comparison, FWORD, HWORD, Int32FromF], BasicTime USING [GMT, Now], CCTypes USING[CCError, CCErrorCase], CirioTypes USING [zeroBA], Commander USING [Register, CommandProc], CommanderOps USING [ArgumentVector, Parse], Convert USING [IntFromRope], IO, List USING [Sort], ObjectFiles USING[BracketPairKind, CNameOfStab, CreateParsed, DescribeModule, FileSegmentPC, GlobalVarLoc, MakeUnknownVarLoc, ReadInstruction, RopeForStabType, SimpleSeg, Stab, StabBody, StabType, UnreadableObjectFile, unspecdBitSize, VarLoc, VarLocBody, VersionStampInfo], ObjectFilesPrivate USING[AlterFunStabType, BracketConsumer, BracketPair, BracketPairBody, CheckStaticVar, FnConsumer, FunStabSetBody, GetSPOffsetType, GetTypeRefProcType, HeaderBody, InstallStaticVarsType, LineNumToPCMapBody, MemorySegmentInfo, ModuleBody, ModuleFromParsedAndPCProcType, ObjectFileFlavorBody, Parsed, ParsedBody, PCtoLineNumMapBody, ReadHeaderProcType, ReadInitialDataAsRope, ReadStab, RegisterObjectFileFlavor, SLineData, StabList, StabRange, StabSet, TranslationTable, TranslationTableBody, VarLocFromStabProcType], PFS USING [PathFromRope, RopeFromPath, StreamFromOpenFile, OpenFileFromStream], PFSNames USING [PATH], Random USING[ChooseInt, Create, RandomStream], RMTWBackdoor USING [GetDotO], Rope, SystemInterface USING[CirioFile, CloseFileSet, CreateFileSet, FileSet, GetCirioFile, GetStreamForFile, ReleaseStreamForFile, ShowReport]; SunELFFiles: CEDAR MONITOR IMPORTS Basics, BasicTime, CCTypes, Commander, CommanderOps, Convert, IO, List, ObjectFiles, ObjectFilesPrivate, PFS, Random, RMTWBackdoor, Rope, SystemInterface EXPORTS ObjectFiles = BEGIN CCError: ERROR[case: CCTypes.CCErrorCase, msg: ROPE ¬ NIL] ¬ CCTypes.CCError; <> ROPE: TYPE ~ Rope.ROPE; PATH: TYPE ~ PFSNames.PATH; <> Stab: TYPE = ObjectFiles.Stab; StabList: TYPE = ObjectFilesPrivate.StabList; StabBody: TYPE = ObjectFiles.StabBody; StabType: TYPE = ObjectFiles.StabType; StabRange: TYPE = ObjectFilesPrivate.StabRange; FileSegmentPC: TYPE = ObjectFiles.FileSegmentPC; VersionStampInfo: TYPE = ObjectFiles.VersionStampInfo; <> <<>> LBrac: BYTE = 0c0H; RBrac: BYTE = 0e0H; SLine: BYTE = 044H; Fun: BYTE = 024H; PSym: BYTE = 0a0H; LSym: BYTE = 080H; RSym: BYTE = 040H; STSym: BYTE = 026H; LCSym: BYTE = 028H; GSym: BYTE = 020H; Main: BYTE = 02aH; SO: BYTE = 064H; BIncl: BYTE = 082H; EIncl: BYTE = 0a2H; Excl: BYTE = 0c2H; SOL: BYTE = 084H; <> <<>> Parsed: TYPE = REF ParsedBody; ParsedBody: PUBLIC TYPE = ObjectFilesPrivate.ParsedBody; Module: TYPE = REF ModuleBody; ModuleBody: PUBLIC TYPE = ObjectFilesPrivate.ModuleBody; <<>> Header: TYPE = REF HeaderBody; HeaderBody: TYPE = ObjectFilesPrivate.HeaderBody; MemorySegmentInfo: TYPE ~ ObjectFilesPrivate.MemorySegmentInfo; StabSet: TYPE = ObjectFilesPrivate.StabSet; BracketPair: TYPE ~ ObjectFilesPrivate.BracketPair; BracketPairBody: TYPE ~ ObjectFilesPrivate.BracketPairBody; <> <<>> unspecdBitSize: CARD ~ ObjectFiles.unspecdBitSize; <> 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; SHFWrite: CARD = 1; SHFAlloc: CARD = 2; SHFExecInstr: CARD = 4; STBLocal: CARD = 0; STBGlobal: CARD = 1; STBWeak: CARD = 2; STTNoType: CARD = 0; STTObject: CARD = 1; STTFunc: CARD = 2; STTSection: CARD = 3; STTFile: CARD = 4; <> <<>> RSparcNone: CARD = 0; RSparc8: CARD = 1; RSparc16: CARD = 2; RSparc32: CARD = 3; RSparcDisk8: CARD = 4; RSparcDisk16: CARD = 5; RSparcDisk32: CARD = 6; RSparcWDisp30: CARD = 7; RSparcWDisp22: CARD = 8; RSparcHi22: CARD = 9; RSparc22: CARD = 10; RSparc13: CARD = 11; RSparcLo10: CARD = 12; RSparcGot10: CARD = 13; RSparcGot13: CARD = 14; RSparcGot22: CARD = 15; RSparcPc10: CARD = 16; RSparcPc22: CARD = 17; RSparcWPlt30: CARD = 18; RSparcCopy: CARD = 19; RSparcGlobDat: CARD = 20; RSparcJmpSlot: CARD = 21; RSparcRelative: CARD = 22; RSparcUa32: CARD = 23; <> WireHeader: TYPE = REF WireHeaderBody; WireHeaderBody: 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]; WireSectionHeader: TYPE = REF WireSectionHeaderBody; WireSectionHeaderBody: 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]; WireStabEntry: TYPE = REF WireStabEntryBody; WireStabEntryBody: TYPE = MACHINE DEPENDENT RECORD[ stringX(0: 0..31): Basics.FWORD, type(0: 32..39): BYTE, other(0: 40..47): BYTE, desc(0: 48..63): Basics.HWORD, value(0: 64..95): Basics.FWORD]; WireSymtabEntry: TYPE = REF WireSymtabEntryBody; WireSymtabEntryBody: TYPE = MACHINE DEPENDENT RECORD[ name(0: 0..31): Basics.FWORD, value(0: 32..63): Basics.FWORD, size(0: 64..95): Basics.FWORD, bind(0: 96..99): [0..15], type(0: 100..103): [0..15], other(0: 104..111): BYTE, sectionIndex(0: 112..127): Basics.HWORD]; SymtabRange: TYPE = RECORD[first, count: CARD]; SymtabBind: TYPE ~ { Local, Global, Weak }; SymtabType: TYPE ~ { NoType, Object, Func, Section, File }; WireRelocEntry: TYPE = REF WireRelocEntryBody; WireRelocEntryBody: TYPE = MACHINE DEPENDENT RECORD[ offset(0: 0..31): Basics.FWORD, sym(0: 32..55): [0..16777215], type(0: 56..63): BYTE, addend(0: 64..95): Basics.FWORD]; <
> BitsOn: PROC [flags: CARD, mask: CARD] RETURNS [on: BOOL] ~ INLINE { RETURN [Basics.BITAND[flags, mask] # 0] }; IsDataSection: PROC [section: SectionHeader] RETURNS [BOOL] ~ INLINE { RETURN [(section.type = SHTProgBits OR section.type = SHTNoBits) AND BitsOn[section.flags, SHFAlloc] AND NOT BitsOn[section.flags, SHFExecInstr]] }; ReadHeader: ObjectFilesPrivate.ReadHeaderProcType ~ TRUSTED { <> wHeader: WireHeader ¬ NEW[WireHeaderBody]; nBytes: INT ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wHeader­], 0, BYTES[WireHeaderBody]]]; magic: CARD ¬ Basics.Card32FromF[wHeader.magic]; 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 # EMSparc); nPageSize: CARD ¬ 1000H; textSeg: MemorySegmentInfo ¬ [0, 0]; iDataSeg: MemorySegmentInfo ¬ [0, 0]; bssSeg: MemorySegmentInfo ¬ [0, 0]; symtabSeg: MemorySegmentInfo ¬ [0, 0]; symtabStrSeg: MemorySegmentInfo ¬ [0, 0]; symsSeg: MemorySegmentInfo ¬ [0, 0]; symsStrSeg: MemorySegmentInfo ¬ [0, 0]; textRelocSeg: MemorySegmentInfo ¬ [0, 0]; dataRelocSeg: MemorySegmentInfo ¬ [0, 0]; symsRelocSeg: MemorySegmentInfo ¬ [0, 0]; textLoadOffset: 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]; maxSymsSize: CARD ¬ 0; header: Header; IO.SetIndex[stream, sectHdrOffset]; FOR i: CARD IN [0..sectHdrNum) DO wSectionHeader: WireSectionHeader ¬ NEW[WireSectionHeaderBody]; nBytes: INT ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wSectionHeader­], 0, BYTES[WireSectionHeaderBody]]]; 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; FOR i: CARD IN [0..sectHdrNum) DO IO.SetIndex[stream, sectionList[sectStrTblX].offset+sectionList[i].nameIndex]; sectionList[i].name ¬ ReadRope[stream]; 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; IF objType = ETRelocatable THEN sectionList[i].addr ¬ sectionList[i].offset - textSeg.byteOffset; } ELSE { IF dataIndex = LAST[CARD] THEN { iDataSeg ¬ [sectionList[i].offset, sectionList[i].size]; dataIndex ¬ i; } ELSE iDataSeg.byteLength ¬ iDataSeg.byteLength + sectionList[i].size; IF objType = ETRelocatable THEN sectionList[i].addr ¬ sectionList[i].offset - iDataSeg.byteOffset; }; }; (sectionList[i].type = SHTNoBits) AND BitsOn[sectionList[i].flags, SHFWrite] => { IF bssIndex = LAST[CARD] THEN { bssSeg ¬ [sectionList[i].offset, sectionList[i].size]; bssIndex ¬ i; } ELSE bssSeg.byteLength ¬ bssSeg.byteLength + sectionList[i].size; IF objType = ETRelocatable THEN sectionList[i].addr ¬ sectionList[i].offset - bssSeg.byteOffset; }; (sectionList[i].type = SHTSymTab) => { IF symtabIndex = LAST[CARD] THEN { symtabSeg ¬ [sectionList[i].offset, sectionList[i].size]; symtabIndex ¬ i; IF sectionList[i].entrySize # BYTES[WireSymtabEntryBody] THEN ERROR; symtabStrSeg ¬ [sectionList[sectionList[i].link].offset, sectionList[sectionList[i].link].size]; }; }; (sectionList[i].type = SHTProgBits) AND sectionList[i].flags = 0 => { <> IF sectionList[i].entrySize = BYTES[WireStabEntryBody] THEN { IF maxSymsSize < sectionList[i].size THEN { symsSeg ¬ [sectionList[i].offset, sectionList[i].size]; symsIndex ¬ i; <> maxSymsSize ¬ 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] ELSE IF sectionList[i].info = symsIndex THEN symsRelocSeg ¬ [sectionList[i].offset, sectionList[i].size]; }; ENDCASE; ENDLOOP; IF symsIndex # 0 THEN { symsStrName: ROPE ¬ Rope.Concat[sectionList[symsIndex].name, "str"]; symsRelocName: ROPE ¬ Rope.Concat[".rela", sectionList[symsIndex].name]; FOR i: CARD IN [0..sectHdrNum) DO IF Rope.Equal[symsStrName, sectionList[i].name] THEN symsStrSeg ¬ [sectionList[i].offset, sectionList[i].size]; IF Rope.Equal[symsRelocName, sectionList[i].name] THEN symsRelocSeg ¬ [sectionList[i].offset, sectionList[i].size]; ENDLOOP; }; header ¬ NEW[HeaderBody ¬ [ dynamic: objType = ETDynamicLib, toolversion: BYTE[0] -- wHeader.version --, machtype: machine, magic: 0 -- wHeader.magic --, text: textSeg, iData: iDataSeg, textReloc: textRelocSeg, dataReloc: dataRelocSeg, symsReloc: symsRelocSeg, syms: symsSeg, extSyms: symtabSeg, textLoadOffset: textLoadOffset, bssSize: bssSeg.byteLength, entryPoint: Basics.Card32FromF[wHeader.entry], nPageSize: nPageSize, nEntries: symsSeg.byteLength/BYTES[WireStabEntryBody], nExtEntries: symtabSeg.byteLength/BYTES[WireSymtabEntryBody], stringOffset: symsStrSeg.byteOffset, stringIndexLimit: symsStrSeg.byteLength, extStringOffset: symtabStrSeg.byteOffset, extStringIndexLimit: symtabStrSeg.byteLength, clientData: sectionList ]]; RETURN[header]; }; <<>> <> <<>> <> <> <> <<>> SunELFModuleFromParsedAndPC: ObjectFilesPrivate.ModuleFromParsedAndPCProcType ~ { <> IF whole = NIL THEN RETURN [NIL] ELSE { symtabRange: SymtabRange; minFuncX: CARD; minPC: CARD; dataReloc: CARD; [symtabRange, minFuncX, minPC, dataReloc] ¬ AlternativeFindModuleSymtabRange[whole, spc.relPC]; IF symtabRange = [0, 0] THEN RETURN [NIL]; IF symtabRange = [1, whole.header.nExtEntries-1] THEN { <> RETURN [ModuleFromParsedInner[whole]]; }; { moduleWhole: Parsed ¬ NIL; sourceRope: Rope.ROPE ¬ NIL; funcRope: Rope.ROPE ¬ NIL; dotOPathRope, dotORope: Rope.ROPE ¬ NIL; dotOId: CARD ¬ 0; lag: LIST OF Module ¬ NIL; newModule: Module ¬ NIL; cell: LIST OF Module ¬ NIL; sourceRope ¬ ReadSymtabRope[whole, symtabRange.first]; <> FOR modules: LIST OF Module ¬ whole.modules, modules.rest WHILE modules # NIL DO IF minPC < modules.first.firstPC THEN EXIT; -- we should have found it by now IF Rope.Equal[PFS.RopeFromPath[modules.first.fileName], sourceRope] THEN { -- we already have it RETURN[modules.first] }; lag ¬ modules; ENDLOOP; IF whole.targetData = NIL THEN RETURN [NIL]; funcRope ¬ ReadSymtabRope[whole, minFuncX]; [dotOPathRope, dotORope, dotOId] ¬ GetFileNameAndID[whole, sourceRope]; IF dotOId = 0 THEN RETURN [NIL]; moduleWhole ¬ RMTWBackdoor.GetDotO[whole.targetData, dotOPathRope, dotORope, dotOId, GetDotOId]; newModule ¬ ModuleFromParsedInner[moduleWhole, funcRope, minPC, dataReloc]; IF newModule = NIL THEN RETURN [NIL]; cell ¬ LIST[newModule]; IF lag # NIL THEN lag.rest ¬ cell ELSE whole.modules ¬ cell; newModule.whole ¬ whole; newModule.moduleWhole ¬ moduleWhole; RETURN [newModule]; }; }; }; ModuleFromParsedInner: PROC[whole: Parsed, funcRope: Rope.ROPE ¬ NIL, funcPC, dataReloc: CARD ¬ 0] RETURNS[Module] = { IF whole = NIL THEN RETURN [NIL] ELSE { stream: IO.STREAM ¬ SystemInterface.GetStreamForFile[whole.file]; <> IF whole = NIL THEN RETURN [NIL] ELSE { ENABLE UNWIND => { SystemInterface.ReleaseStreamForFile[whole.file, stream]; }; stabRange: StabRange ¬ [0, whole.header.nEntries]; firstPC: CARD ¬ 0; lag: LIST OF Module ¬ NIL; <> FOR modules: LIST OF Module ¬ whole.modules, modules.rest WHILE modules # NIL DO IF modules.first.firstPC = firstPC THEN { -- we already have it SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[modules.first] }; IF firstPC < modules.first.firstPC THEN { -- we should have found it by now newModule: Module ¬ CreateModule[whole, stream, stabRange]; cell: LIST OF Module ¬ LIST[newModule]; cell.rest ¬ modules; IF lag # NIL THEN lag.rest ¬ cell ELSE whole.modules ¬ cell; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[newModule]; }; lag ¬ modules; ENDLOOP; { newModule: Module ¬ CreateModule[whole, stream, stabRange, funcRope, funcPC, dataReloc]; cell: LIST OF Module ¬ LIST[newModule]; IF lag # NIL THEN lag.rest ¬ cell ELSE whole.modules ¬ cell; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[newModule]; }; }; }; }; GetFileNameAndID: PROC [whole: Parsed, sourceRope: Rope.ROPE] RETURNS [dotOPathRope, dotORope: Rope.ROPE ¬ NIL, dotOId: CARD ¬ 0] = { stream: IO.STREAM ¬ SystemInterface.GetStreamForFile[whole.file]; <<>> <> { ENABLE UNWIND => { SystemInterface.ReleaseStreamForFile[whole.file, stream]; }; nStabs: CARD ¬ whole.header.nEntries; stabX, nextStabX: CARD ¬ 0; strIndex, nextStrIndex: CARD ¬ whole.header.stringOffset; source: Rope.ROPE ¬ NIL; dotOPath, dotO: Rope.ROPE ¬ NIL; ropeStream: IO.STREAM ¬ PFS.StreamFromOpenFile[openFile~PFS.OpenFileFromStream[stream]]; WHILE stabX < nStabs DO IO.SetIndex[stream, whole.header.syms.byteOffset+stabX*BYTES[WireStabEntryBody]]; TRUSTED{[] ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireStabBuffer­], 0, BYTES[WireStabEntryBody]]]}; SELECT wireStabBuffer.type FROM 00H => { stabX ¬ stabX + 1; nextStabX ¬ stabX + Basics.Card16FromH[wireStabBuffer.desc]; strIndex ¬ nextStrIndex; nextStrIndex ¬ nextStrIndex + Basics.Card32FromF[wireStabBuffer.value]; IO.SetIndex[ropeStream, strIndex+Basics.Card32FromF[wireStabBuffer.stringX]]; source ¬ ReadRope[ropeStream]; dotOPath ¬ NIL; }; 38H => { stabX ¬ stabX + 1; IO.SetIndex[ropeStream, strIndex+Basics.Card32FromF[wireStabBuffer.stringX]]; dotO ¬ ReadRope[ropeStream]; dotOPath ¬ Rope.Concat[dotOPath, dotO]; }; 3cH => { stabX ¬ nextStabX; IF Rope.Equal[source, sourceRope] THEN RETURN [dotOPathRope: dotOPath, dotORope: dotO, dotOId: Basics.Card32FromF[wireStabBuffer.value]]; }; ENDCASE => stabX ¬ stabX + 1; ENDLOOP; }; }; GetDotOId: PROC [whole: Parsed] RETURNS [dotOId: CARD ¬ 0] = { stream: IO.STREAM ¬ SystemInterface.GetStreamForFile[whole.file]; <<>> <> { ENABLE UNWIND => { SystemInterface.ReleaseStreamForFile[whole.file, stream]; }; nStabs: CARD ¬ whole.header.nEntries; stabX, nextStabX: CARD ¬ 0; WHILE stabX < nStabs DO IO.SetIndex[stream, whole.header.syms.byteOffset+stabX*BYTES[WireStabEntryBody]]; TRUSTED{[] ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireStabBuffer­], 0, BYTES[WireStabEntryBody]]]}; SELECT wireStabBuffer.type FROM 00H => { stabX ¬ stabX + 1; nextStabX ¬ stabX + Basics.Card16FromH[wireStabBuffer.desc]; }; 3cH => { stabX ¬ nextStabX; RETURN [Basics.Card32FromF[wireStabBuffer.value]]; }; ENDCASE => stabX ¬ stabX + 1; ENDLOOP; }; }; LineNumList: TYPE = REF LineNumListBody; LineNumListBody: TYPE = RECORD [nLines: CARD, lines: LIST OF REF ANY ¬ NIL]; CreateModule: PROC[whole: Parsed, stream: IO.STREAM, stabRange: StabRange ¬ [0, 0], funcRope: Rope.ROPE ¬ NIL, funcPC, dataReloc: CARD ¬ 0] RETURNS[Module] = BEGIN module: Module ¬ NEW[ModuleBody]; lineNums: LineNumList ¬ NEW [LineNumListBody ¬ [0, NIL]]; lineNums2: LineNumList ¬ NEW [LineNumListBody ¬ [0, NIL]]; nStabs: CARD ¬ stabRange.count; <> module.whole ¬ whole; module.firstStabX ¬ stabRange.first; module.limitStabX ¬ stabRange.first+stabRange.count; module.firstPC ¬ 0; module.limitPC ¬ whole.header.text.byteLength; module.dataReloc ¬ dataReloc; <> <<>> module.stabs ¬ NEW[StabSet[nStabs]]; {I: CARD ¬ 0; WHILE I> <<>> RelocateStabAndLineNum[whole, stream, module, nStabs, funcRope, funcPC, dataReloc, lineNums, lineNums2]; InstallPCLineNumMaps[module, lineNums, lineNums2]; module.fileName ¬ PFS.PathFromRope[module.stabs[0].rope]; module.staticVarsInstalled ¬ FALSE; module.versionStampInfo ¬ NIL; module.outerBracket ¬ NEW[ObjectFilesPrivate.BracketPairBody¬[ module: module, kind: syntheticOuter, firstX: 0, limitX: module.whole.header.nEntries, firstPC: module.firstPC, pcLimit: module.limitPC, funStab: NIL, funIndex: 0, symbols: NIL, innerBrackets: NIL]]; RETURN[module]; END; <<>> <> RandomTestFindSymtabRange: Commander.CommandProc = { args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; path: PATH ¬ PFS.PathFromRope[args[1]]; fileSet: SystemInterface.FileSet ¬ SystemInterface.CreateFileSet[]; { 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, "SunELF"]; IO.PutF[cmd.out, "beginning seed = %g at %g\N", IO.card[nextSeed], IO.time[start]]; FOR I: INT IN [0..100) DO pc: CARD ¬ Random.ChooseInt[rs, 0, whole.header.text.byteLength]; range: SymtabRange ¬ AlternativeFindModuleSymtabRange[whole, pc].symtabRange; 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]; }; <> <<>> SymtabBody: TYPE ~ RECORD[symtabX: CARD, value: CARD, size: CARD, symtabBind: SymtabBind, symtabType: SymtabType, symtabSection: CARD]; nullSymtabBody: SymtabBody ~ [0, 0, 0, Local, NoType, 0]; AlternativeFindModuleSymtabRange: PROC[whole: Parsed, relativePC: CARD] RETURNS[symtabRange: SymtabRange ¬ [0, 0], minFuncX, minPC: CARD ¬ 0, dataReloc: CARD ¬ 0] = { baseFile: SymtabBody ¬ nullSymtabBody; maxPC: CARD ¬ 0; highSymtabX: CARD ¬ 0; foundDataReloc: BOOLEAN ¬ FALSE; FindModuleSymtabRange: PROC [nominalX: CARD] RETURNS [failed: BOOL] = { IF nominalX >= whole.header.nExtEntries THEN RETURN[failed: TRUE]; baseFile ¬ nullSymtabBody; maxPC ¬ 0; highSymtabX ¬ 0; foundDataReloc ¬ FALSE; minPC ¬ LAST[CARD]; FOR x: CARD DECREASING IN [0..nominalX] DO info: SymtabBody ¬ ReadSymtabBody[whole, x]; SELECT info.symtabType FROM Func => IF info.symtabSection # 0 THEN { maxPC ¬ MAX[maxPC, info.value + info.size]; IF info.symtabBind = Local AND info.value < minPC THEN { minFuncX ¬ x; minPC ¬ info.value}}; File => {baseFile ¬ info; EXIT}; NoType => {dataReloc ¬ info.value; foundDataReloc ¬ TRUE}; ENDCASE; highSymtabX ¬ MAX[highSymtabX, info.symtabX]; ENDLOOP; IF baseFile.symtabType # File THEN { RETURN[failed: TRUE]}; FOR x: CARD IN (nominalX..whole.header.nExtEntries) DO info: SymtabBody ¬ ReadSymtabBody[whole, x]; SELECT info.symtabType FROM Func => IF info.symtabSection # 0 THEN { maxPC ¬ MAX[maxPC, info.value + info.size]; IF info.symtabBind = Local AND info.value < minPC THEN { minFuncX ¬ x; minPC ¬ info.value}}; File => EXIT; NoType => IF NOT foundDataReloc THEN { dataReloc ¬ info.value; foundDataReloc ¬ TRUE}; ENDCASE; highSymtabX ¬ MAX[highSymtabX, info.symtabX]; ENDLOOP; RETURN[failed: FALSE]; }; IF whole = NIL THEN RETURN[[0, 0], 0, 0, 0] ELSE { nominalX: CARD ¬ SearchForPCSymtab[whole, relativePC]; DO IF FindModuleSymtabRange[nominalX].failed THEN RETURN[[0, 0], 0, 0, 0]; IF minPC <= relativePC AND relativePC < maxPC THEN { RETURN[[baseFile.symtabX, highSymtabX-baseFile.symtabX+1], minFuncX, minPC, dataReloc]}; IF minPC > relativePC THEN EXIT; <> nominalX ¬ highSymtabX + 1; ENDLOOP; RETURN[[0, 0], 0, 0, 0]; }; }; SearchForPCSymtab: PROC[whole: Parsed, pc: CARD] RETURNS[CARD] = BEGIN x: CARD ¬ 0; y: CARD ¬ whole.header.nExtEntries; WHILE x+1 < y DO mid: CARD ¬ (x+y)/2; midSymtab: SymtabBody ¬ SearchFwdForPCSymtab[whole, mid, y]; SELECT TRUE FROM midSymtab.symtabX = y => y ¬ mid; pc < midSymtab.value => y ¬ mid; midSymtab.value = pc => RETURN[midSymtab.symtabX]; midSymtab.value < pc => x ¬ mid; ENDCASE => ERROR; ENDLOOP; RETURN[x]; END; SearchFwdForPCSymtab: PROC[whole: Parsed, start: CARD, limit: CARD] RETURNS[SymtabBody] = BEGIN FOR x: CARD ¬ start, x+1 WHILE x < limit DO info: SymtabBody ¬ ReadSymtabBody[whole, x]; IF info.symtabType = Func AND info.symtabBind = Local THEN RETURN[info]; IF info.symtabBind = Global THEN EXIT; ENDLOOP; RETURN[[limit, 0, 0, Local, NoType, 0]]; END; SymtabBindFromData: PROC [data: [0..15]] RETURNS [symtabType: SymtabBind] ~ { val: CARD ¬ data; symtabType ¬ SELECT val FROM STBLocal => Local, STBGlobal => Global, STBWeak => Weak, ENDCASE => ERROR; }; SymtabTypeFromData: PROC [data: [0..15]] RETURNS [symtabType: SymtabType] ~ { val: CARD ¬ data; symtabType ¬ SELECT val FROM STTNoType => NoType, STTObject => Object, STTFunc => Func, STTSection => Section, STTFile => File, ENDCASE => ERROR; }; ReadSymtabBody: ENTRY PROC[whole: Parsed, symtabX: CARD] RETURNS[SymtabBody] = BEGIN ENABLE UNWIND => NULL; stream: IO.STREAM ¬ SystemInterface.GetStreamForFile[whole.file]; IO.SetIndex[stream, whole.header.extSyms.byteOffset+symtabX*BYTES[WireSymtabEntryBody]]; TRUSTED{[] ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireSymtabBuffer­], 0, BYTES[WireSymtabEntryBody]]]}; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[[symtabX, Basics.Card32FromF[wireSymtabBuffer.value], Basics.Card32FromF[wireSymtabBuffer.size], SymtabBindFromData[wireSymtabBuffer.bind], SymtabTypeFromData[wireSymtabBuffer.type], Basics.Card16FromH[wireSymtabBuffer.sectionIndex]]]; END; ReadSymtabRope: ENTRY PROC[whole: Parsed, symtabX: CARD] RETURNS[rope: Rope.ROPE ¬ NIL] = BEGIN ENABLE UNWIND => NULL; stream: IO.STREAM ¬ SystemInterface.GetStreamForFile[whole.file]; IO.SetIndex[stream, whole.header.extSyms.byteOffset+symtabX*BYTES[WireSymtabEntryBody]]; TRUSTED{[] ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireSymtabBuffer­], 0, BYTES[WireSymtabEntryBody]]]}; IO.SetIndex[stream, whole.header.extStringOffset+Basics.Card32FromF[wireSymtabBuffer.name]]; rope ¬ ReadRope[stream]; SystemInterface.ReleaseStreamForFile[whole.file, stream]; END; <> SunELFVarLocFromStab: ObjectFilesPrivate.VarLocFromStabProcType ~ { <> header: Header ~ stab.module.whole.header; MkSegment: PROC [kind: ObjectFiles.SimpleSeg] RETURNS [ObjectFiles.VarLoc] ~ { segRope: ROPE; segBase: CARD ~ SELECT kind FROM text => 0, data => header.text.byteLength, bss => header.text.byteLength + header.iData.byteLength, ENDCASE => ERROR; segSize: CARD ~ SELECT kind FROM text => header.text.byteLength, data => header.iData.byteLength, bss => header.bssSize, ENDCASE => ERROR; IF stab.value >= segSize THEN ObjectFiles.UnreadableObjectFile[IO.PutFLR["value (%xH) greater than segment size (%xH) for symbol %g in %g", LIST[[cardinal[stab.value]], [cardinal[segSize]], [rope[ObjectFiles.CNameOfStab[stab]]], [rope[ObjectFiles.DescribeModule[stab.module]]]] ]]; SELECT kind FROM text => segRope ¬ "text"; data => segRope ¬ "data"; bss => segRope ¬ "bss"; ENDCASE => ERROR; RETURN [NEW [ObjectFiles.VarLocBody ¬ [ bitSize: IF stab.size#0 THEN stab.size*8 ELSE unspecdBitSize, where: fSegment[ [0, segRope], stab.value*8, stab.value + segBase + header.text.byteOffset - header.textLoadOffset] ]]]}; 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[Rope.Concat["_", 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]]] ]]; }; SunELFInstallStaticVars: ObjectFilesPrivate.InstallStaticVarsType ~ <> <> { 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 ¬ 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; }; <> PCtoLineNumMap: TYPE = REF PCtoLineNumMapBody; PCtoLineNumMapBody: TYPE = ObjectFilesPrivate.PCtoLineNumMapBody; <> LineNumToPCMap: TYPE = REF LineNumToPCMapBody; LineNumToPCMapBody: TYPE = ObjectFilesPrivate.LineNumToPCMapBody; <> SLineData: TYPE = ObjectFilesPrivate.SLineData; InstallPCLineNumMaps: PROC[module: Module, lineNums, lineNums2: LineNumList] = { CompareByCLineNum: PROC[ref1: REF ANY, ref2: REF ANY] RETURNS [Basics.Comparison] = { 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] = { 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]; }; sortedList: LIST OF REF ANY ¬ NIL; IF module.pcToLineNum # NIL OR module.lineNumToPC # NIL THEN { IF module.pcToLineNum = NIL OR module.lineNumToPC = NIL THEN ERROR; RETURN; }; sortedList ¬ List.Sort[lineNums.lines, CompareByCLineNum]; module.lineNumToPC ¬ NEW[LineNumToPCMapBody[lineNums.nLines]]; FOR I: INTEGER IN [0..lineNums.nLines) DO info: REF SLineData ¬ NARROW[sortedList.first]; module.lineNumToPC[I] ¬ info­; sortedList ¬ sortedList.rest; ENDLOOP; sortedList ¬ List.Sort[lineNums2.lines, CompareByPC]; module.pcToLineNum ¬ NEW[PCtoLineNumMapBody[lineNums2.nLines]]; FOR I: INTEGER IN [0..lineNums2.nLines) DO info: REF SLineData ¬ NARROW[sortedList.first]; module.pcToLineNum[I] ¬ info­; sortedList ¬ sortedList.rest; ENDLOOP; }; <<>> <> <<>> TypeFromData: PROC [data: BYTE] RETURNS [stabType: ObjectFiles.StabType] ~ { val: CARD ¬ data; stabType ¬ SELECT val FROM LBrac => LBrac, RBrac => RBrac, SLine => SLine, Fun => Fun, PSym => PSym, LSym => LSym, RSym => RSym, STSym => STSym, LCSym => LCSym, GSym => GSym, Main => Main, SO => SO, BIncl => BIncl, EIncl => EIncl, Excl => Excl, SOL => SOL, ENDCASE => Unspecified }; BasicReadStab: ENTRY PROC[whole: Parsed, stream: IO.STREAM, stabX: CARD] RETURNS[stab: Stab, numStabsRead: CARD] ~ { <> <> <<>> ENABLE UNWIND => NULL; stab ¬ NEW [StabBody]; [stab­, numStabsRead] ¬ ReadStabBody[whole, stream, stabX]; RETURN }; <> previousStream: IO.STREAM ¬ NIL; cloneStream: IO.STREAM ¬ NIL; ReadStabBody: PROC [whole: Parsed, stream: IO.STREAM, stabX: CARD] RETURNS [stab: StabBody, numStabsRead: CARD] ~ { rope: ROPE ¬ "\\"; size, rLen, offset: CARD16 ¬ 0; value: CARD32; stabType: ObjectFiles.StabType; IO.SetIndex[stream, whole.header.syms.byteOffset+stabX*BYTES[WireStabEntryBody]]; TRUSTED{[] ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireStabBuffer­], 0, BYTES[WireStabEntryBody]]]}; stabType ¬ TypeFromData[wireStabBuffer.type]; size ¬ Basics.Card16FromH[wireStabBuffer.desc]; value ¬ Basics.Card32FromF[wireStabBuffer.value]; IF stream#previousStream THEN { cloneStream ¬ PFS.StreamFromOpenFile[openFile~PFS.OpenFileFromStream[stream]]; previousStream ¬ stream; }; rope ¬ ReadStringX[cloneStream, whole, Basics.Card32FromF[wireStabBuffer.stringX]]; rLen ¬ rope.Length[]; numStabsRead ¬ 1; IF ~rope.IsEmpty[] THEN WHILE rope.Fetch[rLen-1] = '\\ DO offset ¬ offset + 1; IO.SetIndex[stream, whole.header.syms.byteOffset+(stabX + offset)*BYTES[WireStabEntryBody]]; TRUSTED{[] ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireStabBuffer­], 0, BYTES[WireStabEntryBody]]]}; rope ¬ rope.Substr[len:rLen-1].Concat[ReadStringX[cloneStream, whole, Basics.Card32FromF[wireStabBuffer.stringX]]]; rLen ¬ rope.Length[]; numStabsRead ¬ numStabsRead + 1; ENDLOOP; stab ¬ [ module: NIL, stabX: stabX, stabType: stabType, size: size, value: value, rope: rope ]; RETURN}; RelocateStabAndLineNum: PROC [whole: Parsed, stream: IO.STREAM, module: Module, nStabs: CARD, funcRope: Rope.ROPE ¬ NIL, funcPC, dataReloc: CARD ¬ 0, lineNum, lineNum2: LineNumList] ~ { sectionList: SectionList ¬ NARROW[whole.header.clientData]; nRelocEntries: INT ¬ whole.header.symsReloc.byteLength / BYTES[WireRelocEntryBody]; symtabStream: IO.STREAM ¬ PFS.StreamFromOpenFile[openFile~PFS.OpenFileFromStream[stream]]; previousSymtabX: CARD ¬ LAST[CARD]; symtabX: CARD; sectionIndex: CARD; baseValue: CARD; value: CARD; stabX: CARD; stabRope: Rope.ROPE ¬ Rope.Concat[funcRope, ":f("]; -- local function FOR I: CARD IN [0..nRelocEntries) DO IO.SetIndex[stream, whole.header.symsReloc.byteOffset+I*BYTES[WireRelocEntryBody]]; TRUSTED{[] ¬ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireRelocBuffer­], 0, BYTES[WireRelocEntryBody]]]}; symtabX ¬ wireRelocBuffer.sym; IF symtabX # previousSymtabX THEN { IO.SetIndex[symtabStream, whole.header.extSyms.byteOffset+symtabX*BYTES[WireSymtabEntryBody]]; TRUSTED{[] ¬ IO.UnsafeGetBlock[symtabStream, [LOOPHOLE[@wireSymtabBuffer­], 0, BYTES[WireSymtabEntryBody]]]}; sectionIndex ¬ Basics.Card16FromH[wireSymtabBuffer.sectionIndex]; baseValue ¬ Basics.Card32FromF[wireSymtabBuffer.value] + sectionList[sectionIndex].addr; IF IsDataSection[sectionList[sectionIndex]] THEN baseValue ¬ baseValue + dataReloc; previousSymtabX ¬ symtabX; }; value ¬ baseValue + Basics.Int32FromF[wireRelocBuffer.addend]; stabX ¬ Basics.Card32FromF[wireRelocBuffer.offset] / BYTES[WireStabEntryBody]; SELECT wireRelocBuffer.type FROM RSparc32 => module.stabs[stabX].value ¬ value; ENDCASE => ERROR; IF module.stabs[stabX].stabType = Fun AND Rope.IsPrefix[stabRope, module.stabs[stabX].rope] THEN { module.firstPC ¬ module.firstPC + (funcPC - module.stabs[stabX].value); module.limitPC ¬ module.limitPC + (funcPC - module.stabs[stabX].value); }; ENDLOOP; FOR I: CARD IN [0..nStabs) DO SELECT module.stabs[I].stabType FROM Fun => IF Rope.Find[module.stabs[I].rope, ":P("] = -1 THEN value ¬ module.stabs[I].value ¬ module.stabs[I].value + module.firstPC; SLine => { info: REF SLineData ¬ NEW[SLineData¬[cLineNum: module.stabs[I].size, parsedRelPC: [[1, ".text"], module.stabs[I].value + value]]]; lineNum.lines ¬ CONS[info, lineNum.lines]; lineNum.nLines ¬ lineNum.nLines + 1; lineNum2.lines ¬ CONS[info, lineNum2.lines]; lineNum2.nLines ¬ lineNum2.nLines + 1; module.stabs[I].value ¬ module.stabs[I].value + value; }; LBrac, RBrac => module.stabs[I].value ¬ module.stabs[I].value + value; ENDCASE; ENDLOOP; RETURN}; wireStabBuffer: WireStabEntry ¬ NEW[WireStabEntryBody]; <> wireSymtabBuffer: WireSymtabEntry ¬ NEW[WireSymtabEntryBody]; <> wireRelocBuffer: WireRelocEntry ¬ NEW[WireRelocEntryBody]; <> <<>> ReadStringX: PROC[stream: IO.STREAM, whole: Parsed, stringX: CARD] RETURNS[rope: ROPE] ~ { IO.SetIndex[stream, whole.header.stringOffset+stringX]; rope ¬ ReadRope[stream]}; <> <> <<>> RopeBufferSize: CARD = 100; ropeBuffer: REF PACKED ARRAY [0..RopeBufferSize) OF CHAR ¬ NEW[PACKED ARRAY [0..RopeBufferSize) OF CHAR]; <> ReadRope: PROC[s: IO.STREAM] RETURNS[rope: ROPE] = BEGIN ENABLE UNWIND => NULL; rope: ROPE ¬ NIL; WHILE TRUE DO nChars: CARD ¬ RopeBufferSize; -- tentative rt: Rope.Text; TRUSTED{[] ¬ IO.UnsafeGetBlock[s, [LOOPHOLE[@ropeBuffer­], 0, RopeBufferSize]]}; FOR I: CARD IN [0..RopeBufferSize) DO IF ropeBuffer[I] = '\000 THEN {nChars ¬ I; EXIT}; ENDLOOP; rt ¬ Rope.NewText[nChars]; FOR I: CARD IN [0..nChars) DO rt[I] ¬ ropeBuffer[I] ENDLOOP; rope ¬ IF rope = NIL THEN (IF nChars = 0 THEN "" ELSE rt) ELSE (IF nChars = 0 THEN rope ELSE Rope.Concat[rope, rt]); IF nChars < RopeBufferSize THEN EXIT; ENDLOOP; RETURN[rope]; END; <<>> <> IsExternalFun: PROC [stab: Stab] RETURNS [BOOL] ~ { RETURN[Rope.Find[stab.rope, ":P", 0, TRUE] # -1]}; SunELFScanModuleStructure: 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 => IF IsExternalFun[stab] THEN I ¬ I + 1 ELSE { 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, RSym => NULL; LBrac => { SELECT module.stabs[I+1].stabType FROM STSym, LSym, RSym => firstLocal ¬ module.stabs[I+1]; ENDCASE; EXIT}; Invalid, Unspecified, Main, SO, BIncl, EIncl, Excl, SOL => 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]; REPEAT FINISHED => SystemInterface.ShowReport[IO.PutFR["Missed an LBRAC in function %g in %g", [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; ENDLOOP; I ¬ perFn[funStab, firstLocal, I+module.firstStabX] - module.firstStabX}; SLine, Invalid, Unspecified, Main, SO, BIncl, EIncl, Excl, SOL => 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}; SunELFScanFnStructure: 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 PassLocals[module, funStab, funStab.stabX+1, nextX, perParm]; limitX ¬ DoBrack[module, funStab, module.stabs[nextX-module.firstStabX], 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 => IF stab.value > funStab.value THEN 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 ¬ SunELFScanBktStructure[module, funStab, first, NIL, NIL].limitX; RETURN}; SunELFScanBktStructure: 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 + 1; stab: Stab; IF first.stabType # LBrac THEN ERROR; firstPc ¬ first.value; 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 RBrac => RETURN [I+1+module.firstStabX, firstPc, stab.value]; STSym, LSym, RSym => IF perLocal#NIL THEN perLocal[stab]; LBrac => I ¬ DoBrack[module, funStab, stab, perSubBracket] - 1 - module.firstStabX; Fun => IF NOT IsExternalFun[stab] THEN {--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]; RETURN [I+module.firstStabX, stab.value, stab.value]}; SLine, Invalid, Unspecified, Main, SO, BIncl, EIncl, Excl, SOL => NULL; ENDCASE => SystemInterface.ShowReport[IO.PutFR["Found %g stab before an RBRAC 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[I+module.firstStabX, module.limitPC, module.limitPC]}; PassLocals: 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]; SLine, Invalid, Unspecified, Main, SO, BIncl, EIncl, Excl, SOL => NULL; ENDCASE => SystemInterface.ShowReport[IO.PutFR["Found %g stab in parms/locals of %g in %g", [rope[ObjectFiles.RopeForStabType[stab.stabType]]], [rope[ObjectFiles.CNameOfStab[funStab]]], [rope[ObjectFiles.DescribeModule[module]]] ], $normal]; ENDLOOP; RETURN}; SunELFGetTypeRef: ObjectFilesPrivate.GetTypeRefProcType ~ { <> typeRef: Rope.ROPE; lastChar: CHAR ¬ IO.PeekChar[sourceStream]; IF IsDigit[lastChar] THEN { typeRef ¬ IO.GetTokenRope[sourceStream, NumTok].token; RETURN[typeRef]} ELSE IF lastChar='( THEN DO lastChar ¬ IO.GetChar[sourceStream]; typeRef ¬ Rope.Concat[typeRef, Rope.FromChar[lastChar]]; IF lastChar = ') THEN RETURN[typeRef] ENDLOOP ELSE CCError[cirioError, IO.PutFR1["malformed type rep (starts with %q)", [character[lastChar]] ]]; }; IsDigit: PROC [c:CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['0 .. '9]] }; NumTok: PROC [char: CHAR] RETURNS [IO.CharClass] ~ { SELECT char FROM IN ['0..'9] => RETURN [other]; ENDCASE => RETURN [break]}; SunELFAlterFunStab: ObjectFilesPrivate.AlterFunStabType ~ {RETURN [module.funStabs[funStabX].stab]; }; <> SunELFGetSPOffset: ObjectFilesPrivate.GetSPOffsetType ~ { entryRelativePC: CARD ¬ spc.relPC; inst0: CARD ¬ ObjectFiles.ReadInstruction[module, [spc.fSeg, spc.relPC]]; inst1: CARD ¬ ObjectFiles.ReadInstruction[module, [spc.fSeg, spc.relPC+4]]; inst2: CARD ¬ ObjectFiles.ReadInstruction[module, [spc.fSeg, spc.relPC+8]]; spOffset: INT ¬ SaveProtocol1[inst0, inst1, inst2]; IF spOffset = 0 THEN spOffset ¬ SaveProtocol2[inst0]; RETURN[spOffset]; }; <> <> <<>> <> <> <> <> SaveProtocol1: PROC[inst0, inst1, inst2: CARD] RETURNS[spOffset: INT] ~ { decoded0: DecodedSparcInstruction ¬ DecodeSparcInstruction[inst0]; decoded1: DecodedSparcInstruction ¬ DecodeSparcInstruction[inst1]; decoded2: DecodedSparcInstruction ¬ DecodeSparcInstruction[inst2]; <> IF decoded0.op # 0 THEN RETURN[0]; IF decoded0.op2 # 4 THEN RETURN[0]; IF decoded0.rd # 1 THEN RETURN[0]; -- this is %g1 <> IF decoded1.op # 2 THEN RETURN[0]; IF decoded1.op3 # 0 THEN RETURN[0]; IF decoded1.i # 1 THEN RETURN[0]; IF decoded1.rs1 # 1 THEN RETURN[0]; -- this is %g1 IF decoded1.rd # 1 THEN RETURN[0]; -- this is %g1 <> IF decoded2.op # 2 THEN RETURN[0]; IF decoded2.op3 # 74B THEN RETURN[0]; IF decoded2.i # 0 THEN RETURN[0]; IF decoded2.rs1 # 16B THEN RETURN[0]; -- this is %sp IF decoded2.rs2 # 1 THEN RETURN[0]; -- this is %g1 IF decoded2.rd # 16B THEN RETURN[0]; -- this is %sp spOffset ¬ LOOPHOLE[Basics.BITSHIFT[decoded0.imm22, 10] + decoded1.simm13]; }; <> <> SaveProtocol2: PROC[inst0: CARD] RETURNS[spOffset: INT] ~ { decoded0: DecodedSparcInstruction ¬ DecodeSparcInstruction[inst0]; <> IF decoded0.op # 2 THEN RETURN[0]; IF decoded0.op3 # 74B THEN RETURN[0]; IF decoded0.i # 0 THEN RETURN[0]; IF decoded0.rs1 # 16B THEN RETURN[0]; -- this is %sp IF decoded0.rd # 16B THEN RETURN[0]; -- this is %sp spOffset ¬ decoded0.simm13; }; DecodedSparcInstruction: TYPE = RECORD[ op, disp30, rd, a, cond, op2, imm22, disp22, op3, rs1, i, asi, rs2, simm13, opf: CARD]; DecodeSparcInstruction: PROC[inst: CARD] RETURNS[DecodedSparcInstruction] ~ { RETURN[[ op: Basics.BITAND[3, Basics.BITSHIFT[inst, -30]], disp30: Basics.BITAND[7777777777B, inst], rd: Basics.BITAND[37B, Basics.BITSHIFT[inst, -25]], a: Basics.BITAND[1, Basics.BITSHIFT[inst, -29]], cond: Basics.BITAND[17B, Basics.BITSHIFT[inst, -25]], op2: Basics.BITAND[7, Basics.BITSHIFT[inst, -22]], imm22: Basics.BITAND[17777777B, inst], disp22: Basics.BITAND[17777777B, inst], op3: Basics.BITAND[77B, Basics.BITSHIFT[inst, -19]], rs1: Basics.BITAND[37B, Basics.BITSHIFT[inst, -14]], i: Basics.BITAND[1, Basics.BITSHIFT[inst, -13]], asi: Basics.BITAND[377B, Basics.BITSHIFT[inst, -5]], rs2: Basics.BITAND[37B, inst], simm13: Basics.BITAND[17777B, inst], opf: Basics.BITAND[777B, Basics.BITSHIFT[inst, -5]]]]; }; <
> <<>> transTable: ObjectFilesPrivate.TranslationTable ¬ NEW[ObjectFilesPrivate.TranslationTableBody[2]]; Commander.Register["SunELFRandomTestFindSymtabRange", RandomTestFindSymtabRange]; transTable[0] ¬ [0, 4, ElfMagic, "SunELF", first]; transTable[1] ¬ [18, 2, EMSparc, "SunELF", last]; ObjectFilesPrivate.RegisterObjectFileFlavor[NEW[ObjectFilesPrivate.ObjectFileFlavorBody ¬ [ "SunELF", SunADotOut, ReadHeader, SunELFModuleFromParsedAndPC, SunELFVarLocFromStab, SunELFGetTypeRef, NIL, SunELFScanModuleStructure, SunELFScanFnStructure, SunELFScanBktStructure, TRUE, SunELFInstallStaticVars, SunELFAlterFunStab, SunELFGetSPOffset ]], transTable]; <<>> END.