<<>> <> <> <> <> <> <> <> DIRECTORY CirioMemory, CirioNubAccess, CirioTargets, CirioTypes, IO, Rope, LoadStateAccess USING[LoadedModuleInfo], ObjectFiles USING [Parsed], ObjectFilesPrivate USING [Module], SGI USING [FindMatchingProcDescr, WireProcDescriptorBody], PBasics USING [BITLSHIFT, BITAND]; CirioTargetsImpl: CEDAR PROGRAM IMPORTS CirioMemory, CirioNubAccess, IO, Rope, PBasics, SGI EXPORTS CirioTargets = BEGIN OPEN CirioMemory, CirioTargets; BitAddr: TYPE ~ CirioTypes.BitAddr; Mem: TYPE ~ CirioTargets.Mem; Target: TYPE ~ CirioTargets.Target; LoadedModuleInfo: TYPE ~ LoadStateAccess.LoadedModuleInfo; Error: PUBLIC ERROR [msg: ROPE] ~ CODE; CreateTarget: PUBLIC PROC [h: CirioNubAccess.Handle] RETURNS [Target] ~ { SPARCTarget: PROC [h: CirioNubAccess.Handle, instrSet, opSys: Rope.ROPE] RETURNS[Target] ~ { target: Target; SELECT TRUE FROM Rope.Equal[opSys, SunOS4] => target _ NEW[CirioTargets.TargetRep _ [ nub: h, bitsPerAu: 8, bitsPerPtr: 32, ausPerPtr: 4, ptrSize: [4, 0], instrSet: instrSet, opSys: opSys, FpFromSp: SPARCSunOS4FpFromSp, NextSp: SPARCSunOS4NextSp, ReadPc: SPARCSunOS4ReadPc, ReadReg: SPARCSunOS4ReadReg, WriteReg: SPARCSunOS4WriteReg, RegAddr: SPARCSunOS4RegAddr, DescriptorFromPC: SPARCSunOS4DescriptorFromPC, CNameToLoaderName: SPARCSunOS4CNameToLoaderName ]]; Rope.Equal[opSys, SunOS5] => target _ NEW[CirioTargets.TargetRep _ [ nub: h, bitsPerAu: 8, bitsPerPtr: 32, ausPerPtr: 4, ptrSize: [4, 0], instrSet: instrSet, opSys: opSys, FpFromSp: SPARCSunOS4FpFromSp, NextSp: SPARCSunOS4NextSp, ReadPc: SPARCSunOS4ReadPc, ReadReg: SPARCSunOS4ReadReg, WriteReg: SPARCSunOS4WriteReg, RegAddr: SPARCSunOS4RegAddr, DescriptorFromPC: SPARCSunOS4DescriptorFromPC, CNameToLoaderName: SPARCSunOS5CNameToLoaderName ]]; ENDCASE => Error[Rope.Cat["Unsupported opSys: ", opSys, "\N"]]; RETURN[target]; }; RS6000Target: PROC [h: CirioNubAccess.Handle, instrSet, opSys: Rope.ROPE] RETURNS[Target] ~ { target: Target; IF NOT Rope.Equal[opSys, AIX] THEN Error[Rope.Cat["Unsupported opSys: ", opSys, "\N"]]; target _ NEW[CirioTargets.TargetRep _ [ nub: h, bitsPerAu: 8, bitsPerPtr: 32, ausPerPtr: 4, ptrSize: [4, 0], instrSet: instrSet, opSys: opSys, FpFromSp: RS6000AIXFpFromSp, NextSp: RS6000AIXNextSp, ReadPc: RS6000AIXReadPc, ReadReg: RS6000AIXReadReg, WriteReg: RS6000AIXWriteReg, RegAddr: RS6000AIXRegAddr, DescriptorFromPC: RS6000AIXDescriptorFromPC, CNameToLoaderName: RS6000AIXCNameToLoaderName ]]; RETURN[target]; }; MIPSTarget: PROC [h: CirioNubAccess.Handle, instrSet, opSys: Rope.ROPE] RETURNS[Target] ~ { target: Target; IF NOT (Rope.Equal[opSys, IRIX]) THEN Error[Rope.Cat["Unsupported opSys: ", opSys, "\N"]]; target _ NEW[CirioTargets.TargetRep _ [ nub: h, bitsPerAu: 8, bitsPerPtr: 32, ausPerPtr: 4, ptrSize: [4, 0], instrSet: instrSet, opSys: opSys, FpFromSp: MIPSFpFromSp, NextSp: MIPSNextSp, ReadPc: MIPSReadPc, ReadReg: MIPSReadReg, WriteReg: MIPSWriteReg, RegAddr: MIPSRegAddr, DescriptorFromPC: MIPSDescriptorFromPC, CNameToLoaderName: MIPSCNameToLoaderName ]]; RETURN[target]; }; <> SPARC: Rope.ROPE _ "SPARC"; RS6000: Rope.ROPE _ "RS6000"; MIPSEL: Rope.ROPE _ "MIPSEL"; -- MIPS little endian MIPSEB: Rope.ROPE _ "MIPSEB"; -- MIPS big endian <> SunOS4: Rope.ROPE _ "SunOS4"; SunOS5: Rope.ROPE _ "SunOS5"; AIX: Rope.ROPE _ "AIX"; <> IRIX: Rope.ROPE _ "IRIX"; <<>> instrSet, opSys: Rope.ROPE; [instrSet, opSys] _ CirioNubAccess.GetInstructionSetAndOperatingSystem[h]; SELECT TRUE FROM Rope.Equal[instrSet, SPARC] => RETURN[SPARCTarget[h, instrSet, opSys]]; Rope.Equal[instrSet, RS6000] => RETURN[RS6000Target[h, instrSet, opSys]]; Rope.Equal[instrSet, MIPSEL] => RETURN[MIPSTarget[h, instrSet, opSys]]; Rope.Equal[instrSet, MIPSEB] => RETURN[MIPSTarget[h, instrSet, opSys]]; ENDCASE => Error[Rope.Cat["Unsupported instrSet: ", instrSet, "\N"]]; }; <> <<>> <> SPARCSunOS4FpFromSp: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ { stackOffset: INT _ 14*4; RETURN[ReadValue[t, sp, stackOffset]]; }; SPARCSunOS4NextSp: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp, fp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ { RETURN[fp]; }; SPARCSunOS4ReadPc: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp, fp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ { stackOffset: INT _ 15*4; RETURN[ReadValue[t, sp, stackOffset]]; }; SPARCSunOS4ReadReg: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, absPC: CARD] RETURNS [CARD] ~ { regMem: Mem; IF reg < 16 OR reg > 31 THEN Error[IO.PutFR["Can't read register: %g\N", IO.int[reg]]]; regMem _ frame.MemPtrRegIndirect[sp, AusToBa[32], BaCons[(reg-16)*4, 0], FALSE]; RETURN[regMem.MemRead[32, zeroBA]]; }; SPARCSunOS4WriteReg: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, val: CARD, absPC: CARD] ~ { regMem: Mem; IF reg < 16 OR reg > 31 THEN Error[IO.PutFR["Can't write register: %g\N", IO.int[reg]]]; regMem _ frame.MemPtrRegIndirect[sp, AusToBa[32], BaCons[(reg-16)*4, 0], FALSE]; regMem.MemWrite[val, 32, zeroBA]; RETURN; }; SPARCSunOS4RegAddr: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, absPC: CARD] RETURNS [BitAddr] ~ { <> <> <> <> <> <> << (caller's sp) r30 @ sp+(reg-16)*4>> <> <<>> addr: BitAddr; addrBS: BitStretch; IF reg < 16 OR reg > 31 THEN Error[IO.PutFR["Can't find address for register: %g\N", IO.int[reg]]]; addrBS _ frame.MemReadPtrReg[sp]; addr _ BaAdd[addrBS.start, AusToBa[(reg-16)*4]]; RETURN[addr]; }; SPARCSunOS4DescriptorFromPC: PROC [t: Target, pc: BitAddr] RETURNS [BitAddr] ~ { RETURN[pc]; }; SPARCSunOS4CNameToLoaderName: PROC [t: Target, cName: Rope.ROPE] RETURNS [Rope.ROPE] ~ { IF cName = NIL THEN RETURN [cName]; IF cName.IsEmpty THEN RETURN [cName]; RETURN[Rope.Cat["_", cName]]; }; SPARCSunOS5CNameToLoaderName: PROC [t: Target, cName: Rope.ROPE] RETURNS [Rope.ROPE] ~ { RETURN [cName]; }; <> <<>> <> RS6000AIXFpFromSp: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ { RETURN[sp]; }; RS6000AIXNextSp: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp, fp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ { stackOffset: INT _ 0*4; RETURN[ReadValue[t, sp, stackOffset]]; }; RS6000AIXReadPc: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp, fp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ { stackOffset: INT _ 2*4; newfp: BitAddr _ ReadValue[t, fp, 0*4]; IF newfp = CirioMemory.zeroBA THEN RETURN[CirioMemory.unspecdBA]; RETURN[ReadValue[t, newfp, stackOffset]]; }; RS6000AIXReadReg: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, absPC: CARD] RETURNS [CARD] ~ { offset: INT; regMem: Mem; IF reg = 0 OR reg > 10 THEN Error[IO.PutFR["Can't read register: %g\N", IO.int[reg]]]; offset _ IF reg = 1 THEN 0*4 ELSE (reg+3)*4; regMem _ frame.MemPtrRegIndirect[sp, AusToBa[32], BaCons[offset, 0], FALSE]; RETURN[regMem.MemRead[32, zeroBA]]; }; RS6000AIXWriteReg: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, val: CARD, absPC: CARD] ~ { offset: INT; regMem: Mem; IF reg = 0 OR reg > 10 THEN Error[IO.PutFR["Can't read register: %g\N", IO.int[reg]]]; offset _ IF reg = 1 THEN 0*4 ELSE (reg+3)*4; regMem _ frame.MemPtrRegIndirect[sp, AusToBa[32], BaCons[offset, 0], FALSE]; regMem.MemWrite[val, 32, zeroBA]; RETURN; }; RS6000AIXRegAddr: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, absPC: CARD] RETURNS [BitAddr] ~ { <> <> <> <> <> <> <<>> addr: BitAddr; offset: INT; addrBS: BitStretch; IF reg = 0 OR reg > 10 THEN Error[IO.PutFR["Can't find address for register: %g\N", IO.int[reg]]]; offset _ IF reg = 1 THEN 0*4 ELSE (reg+3)*4; addrBS _ frame.MemReadPtrReg[sp]; addr _ BaAdd[addrBS.start, AusToBa[offset]]; RETURN[addr]; }; RS6000AIXDescriptorFromPC: PROC [t: Target, pc: BitAddr] RETURNS [BitAddr] ~ { symEntry, tocEntry: CirioNubAccess.SymEntry; tocName: Rope.ROPE; symEntry _ CirioNubAccess.LookupSymEntryByValue[t.nub, BaToAus[pc], 0]; IF symEntry = NIL THEN RETURN[CirioMemory.unspecdBA]; tocName _ Rope.Substr[symEntry.name, 1, Rope.Length[symEntry.name] - 1]; tocEntry _ CirioNubAccess.LookupSymEntryByName[t.nub, tocName, FALSE, FALSE, 0]; IF tocEntry = NIL THEN RETURN[CirioMemory.unspecdBA]; RETURN[AusToBa[tocEntry.value]]; }; RS6000AIXCNameToLoaderName: PROC [t: Target, cName: Rope.ROPE] RETURNS [Rope.ROPE] ~ { IF cName = NIL THEN RETURN [cName]; IF cName.IsEmpty THEN RETURN [cName]; RETURN[Rope.Cat[".", cName]]; }; <> MIPSFpFromSp: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ TRUSTED { module: ObjectFilesPrivate.Module _ LOOPHOLE[loadedModule.module, ObjectFilesPrivate.Module]; parsed: ObjectFiles.Parsed _ LOOPHOLE[module.whole, ObjectFiles.Parsed]; currentPDR: SGI.WireProcDescriptorBody; found: BOOLEAN; frameReg: INT32; frameSize: INT32; fpAddr : BitAddr; dotORel: CARD; dotORel _ absPC - loadedModule.lsi[text].base; [currentPDR, found] _ SGI.FindMatchingProcDescr [dotORel, parsed]; IF found = FALSE THEN RETURN [zeroBA]; frameReg _ currentPDR.framereg; frameSize _ currentPDR.frameoffset; fpAddr _ BaAdd [sp, BaCons [frameSize, 0]]; RETURN[fpAddr]; }; MIPSNextSp: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp, fp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ TRUSTED { module: ObjectFilesPrivate.Module _ LOOPHOLE[loadedModule.module, ObjectFilesPrivate.Module]; parsed: ObjectFiles.Parsed _ LOOPHOLE[module.whole, ObjectFiles.Parsed]; currentPDR: SGI.WireProcDescriptorBody; found: BOOLEAN; fpReg : INT32; dotORel: CARD; dotORel _ absPC - loadedModule.lsi[text].base; [currentPDR, found] _ SGI.FindMatchingProcDescr [dotORel, parsed]; IF found = FALSE THEN RETURN [zeroBA]; fpReg _ currentPDR.framereg; IF fpReg = 8 THEN { <> RETURN[ReadValue[t, BaAdd [sp, BaCons [32, 0]], 0]]; }; <> RETURN[fp]; }; MIPSReadPc: PROC [loadedModule: REF LoadedModuleInfo, t: Target, sp, fp: BitAddr, absPC: CARD] RETURNS [BitAddr] ~ TRUSTED { module: ObjectFilesPrivate.Module _ LOOPHOLE[loadedModule.module, ObjectFilesPrivate.Module]; parsed: ObjectFiles.Parsed _ LOOPHOLE[module.whole, ObjectFiles.Parsed]; currentPDR: SGI.WireProcDescriptorBody; found: BOOLEAN; fpReg : INT32; pcReg : INT32; fpAddr : BitAddr; dotORel: CARD; dotORel _ absPC - loadedModule.lsi[text].base; [currentPDR, found] _ SGI.FindMatchingProcDescr [dotORel, parsed]; IF found = FALSE THEN RETURN [zeroBA]; fpReg _ currentPDR.framereg; pcReg _ currentPDR.pcreg; fpAddr _ MIPSFpFromSp [loadedModule, t, sp, absPC]; IF fpReg = 8 THEN { <> RETURN[ReadValue[t, BaAdd [sp, BaCons [28, 0]], 0]]; }; <<-- the normal case, pc stored as $31>> IF pcReg = 31 THEN { frameOffset : INT32 _ currentPDR.regoffset; frameSize : INT32 _ currentPDR.frameoffset; offset : BitAddr _ BaCons [(frameSize + frameOffset), 0]; IF frameOffset # 0 THEN RETURN[ReadValue[t, BaAdd [sp, offset], 0]] ELSE { <> RETURN[ReadValue[t, BaSub [sp, BaCons [4, 0]], 0]]; }; } ELSE Error[IO.PutFR["Can't find correct PC reg\N"]]; }; FindPosOfRegOnMipsStack: PROC [reg: INT, procDescrRegmask: INT32] RETURNS [INT] = { RegArray: TYPE = ARRAY [1..10] OF INT; n: INT; regMask, bitMask: INT32; savedReg: RegArray _ RegArray[31, 30, 23, 22, 21, 20, 19, 18, 17, 16]; pos: INT _ 1; <> regMask _ PBasics.BITLSHIFT[1, reg]; <> IF PBasics.BITAND[regMask, procDescrRegmask] = 1 THEN { <> <> FOR n IN [1..10] DO <> bitMask _ PBasics.BITLSHIFT[1, savedReg[n]]; <> IF PBasics.BITAND[bitMask, procDescrRegmask] = 1 THEN { pos _ pos+1; <> IF bitMask = regMask THEN GO TO stopedAtRegister; }; ENDLOOP; EXITS stopedAtRegister => RETURN [pos]; }; RETURN [-1]; }; MIPSReadReg: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, absPC: CARD] RETURNS [CARD] ~ TRUSTED { module: ObjectFilesPrivate.Module _ LOOPHOLE[loadedModule.module, ObjectFilesPrivate.Module]; parsed: ObjectFiles.Parsed _ LOOPHOLE[module.whole, ObjectFiles.Parsed]; currentPDR: SGI.WireProcDescriptorBody; found: BOOLEAN; frameOffset : INT32; frameSize : INT32; posInStack : INT; offset : BitAddr; regMem: Mem; dotORel: CARD; dotORel _ absPC - loadedModule.lsi[text].base; [currentPDR, found] _ SGI.FindMatchingProcDescr [dotORel, parsed]; IF found = FALSE THEN RETURN [0]; frameOffset _ currentPDR.regoffset; frameSize _ currentPDR.frameoffset; posInStack _ FindPosOfRegOnMipsStack [reg, currentPDR.regmask]; IF reg < 16 OR (reg > 23 AND reg # 30) THEN Error[IO.PutFR["Can't read register: %g\N", IO.int[reg]]]; offset _ BaCons [(frameSize + frameOffset - (posInStack * 4)), 0]; regMem _ frame.MemPtrRegIndirect[sp, AusToBa[32], offset, FALSE]; RETURN[regMem.MemRead[32, zeroBA]]; }; MIPSWriteReg: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, val: CARD, absPC: CARD] ~ TRUSTED { module: ObjectFilesPrivate.Module _ LOOPHOLE[loadedModule.module, ObjectFilesPrivate.Module]; parsed: ObjectFiles.Parsed _ LOOPHOLE[module.whole, ObjectFiles.Parsed]; currentPDR: SGI.WireProcDescriptorBody; found: BOOLEAN; frameOffset : INT32; frameSize : INT32; posInStack : INT; offset : BitAddr; regMem: Mem; dotORel: CARD; dotORel _ absPC - loadedModule.lsi[text].base; [currentPDR, found] _ SGI.FindMatchingProcDescr [dotORel, parsed]; IF found = FALSE THEN RETURN; frameOffset _ currentPDR.regoffset; frameSize _ currentPDR.frameoffset; posInStack _ FindPosOfRegOnMipsStack [reg, currentPDR.regmask]; IF reg < 16 OR (reg > 23 AND reg # 30) THEN Error[IO.PutFR["Can't write register: %g\N", IO.int[reg]]]; offset _ BaCons [(frameSize + frameOffset - (posInStack * 4)), 0]; regMem _ frame.MemPtrRegIndirect[sp, AusToBa[32], offset, FALSE]; regMem.MemWrite[val, 32, zeroBA]; RETURN; }; MIPSRegAddr: PROC [loadedModule: REF LoadedModuleInfo, t: Target, frame: Mem, reg: INT, absPC: CARD] RETURNS [BitAddr] ~ TRUSTED { <> <> <> <> << on the stack ($31), N = 1 for the next highest>> << register saved, etc.>> << @sp+(framesize+frameoffset-(N*4))>> module: ObjectFilesPrivate.Module _ LOOPHOLE[loadedModule.module, ObjectFilesPrivate.Module]; parsed: ObjectFiles.Parsed _ LOOPHOLE[module.whole, ObjectFiles.Parsed]; currentPDR: SGI.WireProcDescriptorBody; found: BOOLEAN; frameOffset : INT32; frameSize : INT32; posInStack : INT; offset : BitAddr; addr: BitAddr; addrBS: BitStretch; dotORel: CARD; dotORel _ absPC - loadedModule.lsi[text].base; [currentPDR, found] _ SGI.FindMatchingProcDescr [dotORel, parsed]; IF found = FALSE THEN RETURN [zeroBA]; frameOffset _ currentPDR.regoffset; frameSize _ currentPDR.frameoffset; posInStack _ FindPosOfRegOnMipsStack [reg, currentPDR.regmask]; IF reg < 16 OR (reg > 23 AND reg # 30) THEN Error[IO.PutFR["Can't find address for register: %g\N", IO.int[reg]]]; addrBS _ frame.MemReadPtrReg[sp]; offset _ BaCons [(frameSize + frameOffset - (posInStack * 4)), 0]; addr _ BaAdd[addrBS.start, offset]; RETURN[addr]; }; MIPSDescriptorFromPC: PROC [t: Target, pc: BitAddr] RETURNS [BitAddr] ~ { RETURN[pc]; }; MIPSCNameToLoaderName: PROC [t: Target, cName: Rope.ROPE] RETURNS [Rope.ROPE] ~ { IF cName = NIL THEN RETURN [cName]; IF cName.IsEmpty THEN RETURN [cName]; RETURN[cName]; }; <> <<>> ReadValue: PROC[t: Target, base: BitAddr, offset: INT] RETURNS[BitAddr] ~ { addr: BitAddr _ BaAdd[base, AusToBa[offset]]; value: BitAddr _ PtrToBa[CirioNubAccess.RaFromCi[t.nub, LOOPHOLE[BaToAus[addr]], 0].Read32BitsAsCard]; RETURN[value]; }; WriteValue: PROC[t: Target, base: BitAddr, offset: INT, val: CARD] ~ { addr: BitAddr _ BaAdd[base, AusToBa[offset]]; CirioNubAccess.RaFromCi[t.nub, LOOPHOLE[BaToAus[addr]], 0].WriteCardAs32Bits[val]; RETURN; }; END.