private ArmStackFrame FrameByRegisterType(TArmRegisterType aRegister) { ArmStackFrame ret = null; // ArmStackFrame[] frames = iArmEngine.StackFrames; foreach (ArmStackFrame frame in frames) { if (frame.IsRegisterBasedEntry && frame.AssociatedRegister == aRegister) { ret = frame; break; } } // return(ret); }
private ArmStackFrame FrameByStackAddress(uint aAddress) { ArmStackFrame ret = null; // ArmStackFrame[] frames = iArmEngine.StackFrames; foreach (ArmStackFrame frame in frames) { if (frame.Address == aAddress) { ret = frame; break; } } // return(ret); }
private void MakeInitialSeedStackFramesFromRegisterValues() { if (!iAlreadySavedInitialRegisterFrames) { ArmRegisterCollection regs = CPU.Registers; // Make PC stack frame ArmStackFrame framePC = new ArmStackFrame(TArmRegisterType.EArmReg_PC); framePC.Data = regs[TArmRegisterType.EArmReg_PC].Value; // Make LR stack frame ArmStackFrame frameLR = new ArmStackFrame(TArmRegisterType.EArmReg_LR); frameLR.Data = regs[TArmRegisterType.EArmReg_LR].Value; // Save 'em SaveStackFrames(framePC, frameLR); // Don't do this again iAlreadySavedInitialRegisterFrames = true; } }
public bool Process() { // We need SP, LR, PC, CPSR CheckRequiredRegistersAvailable(); // Debug info PrintInitialInfo(); // Make initial stack frames for seed registers MakeInitialSeedStackFramesFromRegisterValues(); // Get sp ArmRegister sp = CPU[TArmRegisterType.EArmReg_SP]; uint initialSPValue = sp.Value; // Create Prologue object that will establish the instructions for the // function and also identify operations that might affect SP and LR. ArmPrologueHelper Prologue = new ArmPrologueHelper(this); Prologue.Build(); // Create a new stack frame for this function call ArmStackFrame stackFrame = new ArmStackFrame(Prologue); // We save the stack address which contained the popped link register // during the previous cycle. If possible, use that value. If it // hasn't been set, then assume we obtained the link register from the // previous 4 bytes of stack (according to the current value of SP). long stackAddressAssociatedWithCurrentFrame = iLastLinkRegisterStackAddress; if (stackAddressAssociatedWithCurrentFrame == KLinkRegisterWasNotPushedOnStack) { // We're always four bytes behind the current SP stackAddressAssociatedWithCurrentFrame = sp - 4; } stackFrame.Address = (uint)stackAddressAssociatedWithCurrentFrame; stackFrame.Data = iStackInterface.StackValueAtAddress(stackFrame.Address); Trace("Creating Stack Frame [" + stackFrame.Address.ToString("x8") + "] = 0x" + stackFrame.Data.ToString("x8") + " = " + SymbolString(stackFrame.Data)); // Can now adjust stack pointer based upon the number of stack-adjusting // instructions during the Prologue phase. uint stackAdjustment = (uint)(Prologue.NumberOfWordsPushedOnStack * 4); sp.Value += stackAdjustment; Trace("stack adjusted by: 0x" + stackAdjustment.ToString("x8")); // We're hoping that the link register was pushed on the stack somewhere // during the function preamble. If that was the case, then as we processed // each instruction, we'll have updated the register offsets so that we know // the offset to the link register from the perspective of the starting stack // address for the function. uint lrOffsetInWords = Prologue.OffsetValues[TArmRegisterType.EArmReg_LR]; Trace(string.Format("LR offset on stack is: 0x{0:x8}", lrOffsetInWords * 4)); GetNewLRValue(lrOffsetInWords, Prologue); // Update the PC to point to the new function address (which we obtain // from LR) uint oldPCValue = CPU.PC; ChangePCToLRAddress(); uint newPCValue = CPU.PC; Trace(string.Format("oldPCValue: 0x{0:x8}, newPCValue: 0x{1:x8}, fn: {2}", oldPCValue, newPCValue, SymbolViewText[newPCValue])); // Decide if we are in thumb or ARM mode after switching functions UpdateInstructionSet(newPCValue); // Return true if we moved to a new function bool gotNewFunction = (oldPCValue != CPU.PC); Trace("gotNewFunction: " + gotNewFunction); // Save stack frame SaveStackFrames(stackFrame); // Increment iteration ++iIterationNumber; // Do we have more to do? bool moreToDo = gotNewFunction && (CPU.PC > 0); // Done Trace("moreToDo: " + moreToDo); return(moreToDo); }
private void CreateStackOutput() { // Get the source data we need to reconstruct and signal we're about to start StackSourceData sourceData = base.SourceData; // Get the output data sink StackOutputData outputData = base.OutputData; outputData.Clear(); outputData.AlgorithmName = Name; // Get the address range of the stack pointer data AddressRange pointerRange = base.Engine.AddressInfo.StackPointerRange; AddressRange pointerRangeExtended = base.Engine.AddressInfo.StackPointerRangeWithExtensionArea; foreach (DataBufferUint sourceEntry in sourceData.GetUintEnumerator()) { // Check if it is within the stack domain, taking into account // our extended range if (pointerRangeExtended.Contains(sourceEntry.Address)) { StackOutputEntry outputEntry = new StackOutputEntry(sourceEntry.Address, sourceEntry.Uint, base.DebugEngineView); // Is it the element that corresponds to the current value of SP? bool isCurrentSPEntry = (outputEntry.AddressRange.Contains(base.Engine.AddressInfo.Pointer)); // Is it within the pure 'stack pointer' address range? bool outsidePureStackPointerRange = !pointerRange.Contains(sourceEntry.Address); outputEntry.IsOutsideCurrentStackRange = outsidePureStackPointerRange; // Is it a ghost? if (outputEntry.Symbol != null) { ArmStackFrame realStackFrame = FrameByStackAddress(sourceEntry.Address); outputEntry.IsAccurate = (realStackFrame != null); outputEntry.IsGhost = (realStackFrame == null); } // Save entry EmitElement(outputEntry); // If we're inside the stack address range, then poke in the PC and LR values if (isCurrentSPEntry) { outputEntry.IsCurrentStackPointerEntry = true; // Working bottom up, so LR should go on the stack first ArmStackFrame stackFrameLR = FrameByRegisterType(TArmRegisterType.EArmReg_LR); if (stackFrameLR != null) { StackOutputEntry entryLR = new StackOutputEntry(0, stackFrameLR.Data, base.DebugEngineView); entryLR.IsRegisterBasedEntry = true; entryLR.IsOutsideCurrentStackRange = true; entryLR.AssociatedRegister = stackFrameLR.AssociatedRegister; EmitElement(entryLR); } // Then the PC... ArmStackFrame stackFramePC = FrameByRegisterType(TArmRegisterType.EArmReg_PC); if (stackFramePC != null) { StackOutputEntry entryPC = new StackOutputEntry(0, stackFramePC.Data, base.DebugEngineView); entryPC.IsRegisterBasedEntry = true; entryPC.IsOutsideCurrentStackRange = true; entryPC.AssociatedRegister = stackFramePC.AssociatedRegister; EmitElement(entryPC); } } } else { // Nope, ignore it... } NotifyEvent(TEvent.EReadingProgress); ++iDWordIndex; } }