DIRECTORY TargetArchitecture, SPARCArchitecture, BreakWorldArchitecture, SPARCBreakWorldUtilities, SPARCManger; SPARCMangerImpl: CEDAR PROGRAM IMPORTS TargetArchitecture, SPARCArchitecture, BreakWorldArchitecture, SPARCBreakWorldUtilities, SPARCManger EXPORTS SPARCManger ~ { Install: PUBLIC PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { IF address.IsNullAddress[] THEN { ERROR SPARCManger.CantInstall[ code: $NullAddress, message: "Install[null address]"]; }; IF manger.IsNullAddress[] THEN { ERROR SPARCManger.CantInstall[ code: $NullAddress, message: "Install[null manger]"]; }; IF patchCode.IsNullAddress[] THEN { ERROR SPARCManger.CantInstall[ code: $NullAddress, message: "Install[null patchCode]"]; }; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; SELECT TRUE FROM SPARCArchitecture.IsCallInstruction[instruction: instruction] => { InstallCallManger[address: address, manger: manger, patchCode: patchCode]; }; SPARCArchitecture.IsDelayedBranchInstruction[instruction: instruction] => { InstallBranchManger[address: address, manger: manger, patchCode: patchCode]; }; SPARCArchitecture.IsJmplO7Instruction[instruction: instruction] => { InstallJmplO7Manger[address: address, manger: manger, patchCode: patchCode]; }; SPARCArchitecture.IsJmplG0Instruction[instruction: instruction] => { InstallJmplG0Manger[address: address, manger: manger, patchCode: patchCode]; }; SPARCArchitecture.IsDelayedControlTransfer[instruction: instruction] => { ERROR CantInstall[ code: $NotWithDelaySlot, message: "Cannot install manger for instruction with that kind of delay slot"]; }; ENDCASE => { InstallNormalManger[address: address, manger: manger, patchCode: patchCode]; }; }; }; InstallNormalManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: SPARCManger.ErrorCode _ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage _ SPARCManger.nullErrorMessage; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; normalManger: SPARCManger.NormalManger; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; sheepAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: SheepOffset[]]; relocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: instruction, from: instructionAddress, to: sheepAddress ! SPARCArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; normalManger.sheep _ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: SheepOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: normalManger.sheep]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { nextInstructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[ address: BreakWorldArchitecture.NextInstruction[pc: address]]; normalContinueAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: NormalContinueOffset[]]; normalManger.normalContinue _ SPARCArchitecture.BAa[ pc: normalContinueAddress, to: nextInstructionAddress]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: NormalContinueOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: normalManger.normalContinue]]; }; { normalManger.normalNoop _ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: NormalNoopOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: normalManger.normalNoop]]; }; { normalManger.tag _ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.normal], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: normalManger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; InstallBranchManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: SPARCManger.ErrorCode _ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage _ SPARCManger.nullErrorMessage; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; branchManger: SPARCManger.BranchManger; branchDelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[ pc: address]; branchContinueBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[pc: branchDelayBreakWorldAddress]; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; dctiAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: DctiOffset[]]; relocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: instruction, from: instructionAddress, to: dctiAddress ! SPARCArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction at breakpoint address"; GO TO Cannot; }]; branchManger.dcti _ relocated; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: DctiOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: branchManger.dcti]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { branchDelayInstructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[ address: branchDelayBreakWorldAddress]; branchDelayAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: BranchDelayOffset[]]; branchDelayInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: branchDelayBreakWorldAddress]; relocatedBranchDelayInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: branchDelayInstruction, from: branchDelayInstructionAddress, to: branchDelayAddress ! SPARCArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction in delay slot of breakpoint address"; GO TO Cannot; }]; branchManger.branchDelay _ relocatedBranchDelayInstruction; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: BranchDelayOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: branchManger.branchDelay]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { branchContinueInstructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[ address: branchContinueBreakWorldAddress]; branchContinueAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: BranchContinueOffset[]]; branchManger.branchContinue _ SPARCArchitecture.BAa[ pc: branchContinueAddress, to: branchContinueInstructionAddress]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: BranchContinueOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: branchManger.branchContinue]]; }; { branchManger.tag _ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.branch], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: branchManger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; InstallCallManger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { callManger: SPARCManger.CallManger; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; instructionTargetAddress: TargetArchitecture.Address ~ BreakWorldArchitecture.TargetAddressFromBreakWorldAddress[address: address]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromTargetAddress[address: instructionTargetAddress]; instructionDisp30: SPARCArchitecture.Disp30 ~ instruction.GetDisp30[]; byteDisplacement: TargetArchitecture.Displacement ~ instructionDisp30 * BYTES[SPARCArchitecture.SPARCInstruction]; destination: TargetArchitecture.Address ~ TargetArchitecture.AddressFromDisplacement[ address: instructionTargetAddress, displacement: byteDisplacement]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; { callManger.callAddrHi _ SPARCArchitecture.Sethi[ hi: SPARCArchitecture.Hi[value: LOOPHOLE[destination]], dest: SPARCArchitecture.Register.global1]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallAddrHiOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callManger.callAddrHi]]; }; { callManger.callJmp _ SPARCArchitecture.JmplConst[ source: SPARCArchitecture.Register.global1, constant: SPARCArchitecture.Lo[value: LOOPHOLE[destination]], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallJmpOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callManger.callJmp]]; }; { callManger.callNoop _ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: CallNoopOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callManger.callNoop]]; }; { callManger.tag _ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.call], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callManger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; InstallJmplO7Manger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { jmplO7Manger: SPARCManger.JmplO7Manger; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; jmplO7Manger.jmplO7Jmp _ SPARCArchitecture.SetRd[ instruction: instruction, rd: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7JmpOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Manger.jmplO7Jmp]]; }; { jmplO7Manger.jmplO7Noop _ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7NoopOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Manger.jmplO7Noop]]; }; { jmplO7Manger.jmplO7Pad _ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplO7PadOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Manger.jmplO7Pad]]; }; { jmplO7Manger.tag _ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.jmplO7], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Manger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; InstallJmplG0Manger: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS [] ~ { errorCode: SPARCManger.ErrorCode _ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage _ SPARCManger.nullErrorMessage; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; jmplG0Manger: SPARCManger.JmplG0Manger; jmplG0DelayBreakWorldAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.NextInstruction[ pc: address]; { instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[address: address]; jmplG0Manger.jmplG0Jmp _ instruction; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplG0JmpOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0Manger.jmplG0Jmp]]; }; { jmplG0DelayInstructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[ address: jmplG0DelayBreakWorldAddress]; jmplG0DelayAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: JmplG0DelayOffset[]]; jmplG0DelayInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: jmplG0DelayBreakWorldAddress]; relocatedJmplG0DelayInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: jmplG0DelayInstruction, from: jmplG0DelayInstructionAddress, to: jmplG0DelayAddress ! SPARCArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot relocate instruction in delay slot of breakpoint address"; GO TO Cannot; }]; jmplG0Manger.jmplG0Delay _ relocatedJmplG0DelayInstruction; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplG0DelayOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0Manger.jmplG0Delay]]; EXITS Cannot => { ERROR CantInstall[code: errorCode, message: errorMessage]; }; }; { jmplG0Manger.jmplG0Pad _ SPARCArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: JmplG0PadOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0Manger.jmplG0Pad]]; }; { jmplG0Manger.tag _ SPARCArchitecture.Sethi[ hi: ORD[SPARCManger.MangerVariant.jmplG0], dest: SPARCArchitecture.Register.global0]; BreakWorldArchitecture.PokeInstruction[ pc: manger, displacement: TagOffset[], instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0Manger.tag]]; }; { patchSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: patchCode]; instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.BAa[ pc: instructionAddress, to: patchSPARCAddress]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: instruction]]; }; }; Uninstall: PUBLIC PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] ~ { tagInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: TagOffset[]]; SELECT tagInstruction.GetImm22[] FROM ORD[SPARCManger.MangerVariant.normal] => { UninstallNormal[address: address, manger: manger]; }; ORD[SPARCManger.MangerVariant.branch] => { UninstallBranch[address: address, manger: manger]; }; ORD[SPARCManger.MangerVariant.call] => { UninstallCall[address: address, manger: manger]; }; ORD[SPARCManger.MangerVariant.jmplO7] => { UninstallJmplO7[address: address, manger: manger]; }; ORD[SPARCManger.MangerVariant.jmplG0] => { UninstallJmplG0[address: address, manger: manger]; }; ENDCASE => { ERROR CantUninstall[ code: $UnknownTag, message: "Can't decode manger"]; }; }; UninstallNormal: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode _ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage _ SPARCManger.nullErrorMessage; { -- extra scope to contain EXITS. instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: SheepOffset[]]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; sheepAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: SheepOffset[]]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; unrelocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: instruction, from: sheepAddress, to: instructionAddress ! SPARCArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: unrelocated]]; EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; UninstallBranch: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode _ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage _ SPARCManger.nullErrorMessage; { -- extra scope to contain EXITS. instruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: DctiOffset[]]; mangerSPARCAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: manger]; dctiAddress: SPARCArchitecture.SPARCAddress ~ SPARCArchitecture.SPARCAddressFromDisplacement[ address: mangerSPARCAddress, displacement: DctiOffset[]]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; unrelocated: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Relocate[ instruction: instruction, from: dctiAddress, to: instructionAddress ! SPARCArchitecture.CantRelocate => { errorCode _ $CantRelocate; errorMessage _ "Cannot unrelocate instruction to breakpoint address"; GO TO Cannot; }]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: unrelocated]]; EXITS Cannot => { ERROR CantUninstall[code: errorCode, message: errorMessage]; }; }; RETURN; }; UninstallCall: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode _ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage _ SPARCManger.nullErrorMessage; callAddrHiInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: CallAddrHiOffset[]]; callAddrHi: SPARCArchitecture.Imm22 ~ callAddrHiInstruction.GetImm22[]; callAddrLoInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: CallJmpOffset[]]; callAddrLo: SPARCArchitecture.Simm13 ~ callAddrLoInstruction.GetSimm13[]; callAddr: SPARCArchitecture.SPARCAddress ~ LOOPHOLE[SPARCArchitecture.HiLo[hi: callAddrHi, lo: callAddrLo]]; instructionAddress: SPARCArchitecture.SPARCAddress ~ SPARCBreakWorldUtilities.SPARCAddressFromBreakWorldAddress[address: address]; callInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.Call[ pc: instructionAddress, to: callAddr]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: callInstruction]]; RETURN; }; UninstallJmplO7: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode _ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage _ SPARCManger.nullErrorMessage; jmplO7JmpInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: JmplO7JmpOffset[]]; jmplO7Instruction: SPARCArchitecture.SPARCInstruction ~ SPARCArchitecture.SetRd[ instruction: jmplO7JmpInstruction, rd: SPARCArchitecture.Register.out7]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplO7Instruction]]; RETURN; }; UninstallJmplG0: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address] ~ { errorCode: SPARCManger.ErrorCode _ SPARCManger.nullErrorCode; errorMessage: SPARCManger.ErrorMessage _ SPARCManger.nullErrorMessage; jmplG0JmpInstruction: SPARCArchitecture.SPARCInstruction ~ SPARCBreakWorldUtilities.SPARCInstructionFromBreakWorldAddress[ address: manger, displacement: JmplG0JmpOffset[]]; BreakWorldArchitecture.PokeInstruction[ pc: address, instruction: SPARCArchitecture.TargetInstructionFromSPARCInstruction[ instruction: jmplG0JmpInstruction]]; RETURN; }; SheepOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.NormalManger; mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; sheepAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.sheep; sheepCard: CARD32 ~ LOOPHOLE[sheepAddress]; offset _ (sheepCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; NormalContinueOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.NormalManger; mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; normalContinueAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.normalContinue; normalContinueCard: CARD32 ~ LOOPHOLE[normalContinueAddress]; offset _ (normalContinueCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; NormalNoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.NormalManger; mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; normalNoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.normalNoop; normalNoopCard: CARD32 ~ LOOPHOLE[normalNoopAddress]; offset _ (normalNoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; TagOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.NormalManger; mangerAddress: LONG POINTER TO SPARCManger.NormalManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; tagAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.tag; tagCard: CARD32 ~ LOOPHOLE[tagAddress]; offset _ (tagCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; DctiOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.BranchManger; mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; dctiAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.dcti; dctiCard: CARD32 ~ LOOPHOLE[dctiAddress]; offset _ (dctiCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; BranchDelayOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.BranchManger; mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchDelayAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.branchDelay; branchDelayCard: CARD32 ~ LOOPHOLE[branchDelayAddress]; offset _ (branchDelayCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; BranchContinueOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.BranchManger; mangerAddress: LONG POINTER TO SPARCManger.BranchManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; branchContinueAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.branchContinue; branchContinueCard: CARD32 ~ LOOPHOLE[branchContinueAddress]; offset _ (branchContinueCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CallAddrHiOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.CallManger; mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callAddrHiAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.callAddrHi; callAddrHiCard: CARD32 ~ LOOPHOLE[callAddrHiAddress]; offset _ (callAddrHiCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CallJmpOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.CallManger; mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callJmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.callJmp; callJmpCard: CARD32 ~ LOOPHOLE[callJmpAddress]; offset _ (callJmpCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CallNoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.CallManger; mangerAddress: LONG POINTER TO SPARCManger.CallManger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; callNoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.callNoop; callNoopCard: CARD32 ~ LOOPHOLE[callNoopAddress]; offset _ (callNoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplO7JmpOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.JmplO7Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7JmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.jmplO7Jmp; jmplO7JmpCard: CARD32 ~ LOOPHOLE[jmplO7JmpAddress]; offset _ (jmplO7JmpCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplO7NoopOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.JmplO7Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7NoopAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.jmplO7Noop; jmplO7NoopCard: CARD32 ~ LOOPHOLE[jmplO7NoopAddress]; offset _ (jmplO7NoopCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplO7PadOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.JmplO7Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplO7Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplO7PadAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.jmplO7Pad; jmplO7PadCard: CARD32 ~ LOOPHOLE[jmplO7PadAddress]; offset _ (jmplO7PadCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplG0JmpOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.JmplG0Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0JmpAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.jmplG0Jmp; jmplG0JmpCard: CARD32 ~ LOOPHOLE[jmplG0JmpAddress]; offset _ (jmplG0JmpCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplG0DelayOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.JmplG0Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0DelayAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.jmplG0Delay; jmplG0DelayCard: CARD32 ~ LOOPHOLE[jmplG0DelayAddress]; offset _ (jmplG0DelayCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; JmplG0PadOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { offset: TargetArchitecture.Displacement _ TargetArchitecture.nullDisplacement; manger: SPARCManger.JmplG0Manger; mangerAddress: LONG POINTER TO SPARCManger.JmplG0Manger ~ @manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; jmplG0PadAddress: LONG POINTER TO SPARCArchitecture.SPARCInstruction ~ @manger.jmplG0Pad; jmplG0PadCard: CARD32 ~ LOOPHOLE[jmplG0PadAddress]; offset _ (jmplG0PadCard - mangerCard) * BYTES[UNIT]; RETURN [offset]; }; CantInstall: PUBLIC ERROR [ code: SPARCManger.ErrorCode, message: SPARCManger.ErrorMessage] ~ CODE; CantUninstall: PUBLIC ERROR [ code: SPARCManger.ErrorCode, message: SPARCManger.ErrorMessage] ~ CODE; }. Z SPARCMangerImpl.mesa Copyright ำ 1990 by Xerox Corporation. All rights reserved. Peter B. Kessler, April 18, 1990 10:50:58 pm PDT Procedures Is this the only transformation of the instruction that's required link the patch into the running code. This better be atomic. Else you have a race in smashed memory! Is this the only transformation of the instruction that's required link the patch into the running code. This better be atomic. Else you have a race in smashed memory! link the patch into the running code. This better be atomic. Else you have a race in smashed memory! link the patch into the running code. This better be atomic. Else you have a race in smashed memory! Needs no relocation. link the patch into the running code. This better be atomic. Else you have a race in smashed memory! Is this the only transformation of the instruction that's required? This better be atomic. Else you have a race in smashed code! We don't need to replace the delay slot fortunately, since we wouldn't have time to. Is this the only transformation of the instruction that's required? This better be atomic. Else you have a race in smashed code! This better be atomic. Else you have a race in smashed code! This better be atomic. Else you have a race in smashed code! This better be atomic. Else you have a race in smashed code! Manger offsets: Errors ส– "cedar" style•NewlineDelimiter ™codešœ™K™˜>——šœ8˜8šœ/˜/KšœC˜C——K˜šœ4˜4Kšœ7˜7—šœ'˜'Kšœ ˜ Kšœ&˜&šœE˜EKšœ+˜+——K˜—˜Kšœ3˜3šœ'˜'Kšœ ˜ Kšœ"˜"šœE˜EKšœ'˜'——K˜—˜šœ+˜+Kšœœ$˜+Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ ˜ ——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœH˜HKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—Kšœ˜K˜—šŸœ œ‚œ˜ฎKšœ=˜=KšœF˜F˜4JšœM˜M—˜5JšœL˜L—Kšœ'˜'šœf˜fKšœ ˜ —šœB˜BKšœI˜I—K˜˜šœ2˜2JšœQ˜Q—šœ5˜5JšœM˜M—šœ.˜.šœ/˜/Kšœ9˜9——šœK˜KK˜Kšœ˜Kšœ˜šœ%˜%J˜J˜CJšœœ˜ Kšœ˜—K™B—K˜Kšœ˜šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ!˜!——š˜˜ Kšœ5˜:K˜——K˜—˜šœ@˜@šœ;˜;Kšœ'˜'——šœ5˜5šœ/˜/Kšœ@˜@——šœ=˜=šœ?˜?Kšœ'˜'——šœF˜Fšœ˜Kšœ$˜$Kšœ%˜%Kšœ˜šœ%˜%J˜˜J˜B—Jšœœ˜ Kšœ˜———K˜Kšœ;˜;šœ'˜'Kšœ ˜ Kšœ#˜#šœE˜EKšœ(˜(——š˜˜ Kšœ5˜:K˜——K˜—˜šœC˜Cšœ;˜;Kšœ*˜*——šœ8˜8šœ/˜/KšœC˜C——K˜šœ4˜4KšœA˜A—šœ'˜'Kšœ ˜ Kšœ&˜&šœE˜EKšœ+˜+——K˜—˜šœ+˜+Kšœœ$˜+Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ ˜ ——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœH˜HKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—K˜K˜—šŸœ œ‚œ˜ฌKšœ#˜#šœ2˜2JšœQ˜Q—šœ7˜7KšœL˜L—šœ5˜5KšœS˜S—K˜Fšœ4˜4Jšœœ%˜>—šœU˜UKšœC˜C—˜5KšœL˜L—K˜˜šœ0˜0Kšœ œ˜8Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ"˜"šœE˜EKšœ%˜%——K˜—˜šœ1˜1Kšœ+˜+Kšœ&œ˜>Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ"˜"——K˜—˜Kšœ/˜/šœ'˜'Kšœ ˜ Kšœ ˜ šœE˜EKšœ#˜#——K˜—˜šœ)˜)Kšœœ"˜)Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ˜——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœI˜IKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—K˜K˜—šŸœ œ‚œ˜ฎKšœ'˜'šœ5˜5JšœM˜M—˜5KšœL˜L—K˜˜šœ2˜2JšœQ˜Q—K˜šœ1˜1KšœB˜B—šœ'˜'Kšœ ˜ Kšœ!˜!šœE˜EKšœ&˜&——K˜—˜Kšœ3˜3šœ'˜'Kšœ ˜ Kšœ"˜"šœE˜EKšœ'˜'——K˜—˜Kšœ2˜2šœ'˜'Kšœ ˜ Kšœ!˜!šœE˜EKšœ&˜&——K˜—˜šœ+˜+Kšœœ$˜+Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ ˜ ——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœI˜IKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—K˜K˜—šŸœ œ‚œ˜ฎKšœ=˜=KšœF˜Fšœ5˜5JšœM˜M—˜5KšœL˜L—Kšœ'˜'šœf˜fKšœ ˜ ——˜˜šœ2˜2JšœQ˜Q—K˜šœ%˜%K™—šœ'˜'Kšœ ˜ Kšœ!˜!šœE˜EKšœ&˜&——K˜—˜šœ@˜@šœ;˜;Kšœ'˜'——šœ5˜5šœ/˜/Kšœ@˜@——šœ=˜=šœ?˜?Kšœ'˜'——šœF˜Fšœ˜Kšœ$˜$Kšœ%˜%Kšœ˜šœ%˜%J˜˜J˜B—Jšœœ˜ Kšœ˜———K˜Kšœ;˜;šœ'˜'Kšœ ˜ Kšœ#˜#šœE˜EKšœ(˜(——š˜˜ Kšœ5˜:K˜——K˜—˜Kšœ2˜2šœ'˜'Kšœ ˜ Kšœ!˜!šœE˜EKšœ&˜&——K˜—˜šœ+˜+Kšœœ$˜+Kšœ*˜*—šœ'˜'Kšœ ˜ Kšœ˜šœE˜EKšœ ˜ ——K˜—˜Kšœ%™%šœ4˜4KšœO˜O—šœH˜HKšœ/˜/—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™?—Kšœ˜—K˜K˜—šŸ œœ œ„˜Ÿšœ5˜5šœ?˜?Kšœ,˜,——K˜šœ˜%šœ'˜*K˜2K˜—šœ'˜*K˜2K˜—šœ%˜(K˜0K˜—šœ'˜*K˜2K˜—šœ'˜*Kšœ2˜2K˜—šœ˜ šœ˜Kšœ3˜3—Kšœ˜——K˜K˜—šŸœ œX˜rK˜=KšœF˜Fšœฯc ˜"šœ2˜2šœ?˜?Kšœ.˜.——˜5KšœL˜L—šœ/˜/šœ/˜/Kšœ:˜:——šœ5˜5KšœM˜M—šœM˜MKšœD˜Dšœ%˜%J˜J˜EJšœœ˜ Kšœ˜—K™C—K˜šœ'˜'Kšœ ˜ šœE˜EKšœ˜—K™=—š˜˜ Kšœ7˜