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;
            }
        }