<<>> <> <> <> 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.PutFR["value (%xH) greater than segment size (%xH) for symbol %g in %g", [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.