Exemple #1
0
        uint ScanStackSegment(ref CalleeSaveLocations calleeSaves,
                              UIntPtr returnAddr,
                              UIntPtr *fp,
                              UIntPtr *sp,
                              TransitionRecord *stopMarker,
                              NonNullReferenceVisitor VisitThreadReference,
                              NonNullReferenceVisitor VisitPinnedReference,
                              Thread thread)
        // BUGBUG: Remove thread argument when ThreadContext is on stack!
        {
            uint numStackFrames = 0;

            while (true)
            {
#if SINGULARITY
                if (returnAddr >= LinkStackFunctionsBegin &&
                    returnAddr <= LinkStackFunctionsLimit)
                {
                    if (returnAddr >= LinkStackBegin &&
                        returnAddr <= LinkStackLimit)
                    {
                        returnAddr = SkipLinkStackFrame(ref fp, ref sp);
                    }
                    else if (returnAddr >= UnlinkStackBegin &&
                             returnAddr <= UnlinkStackLimit)
                    {
                        returnAddr = SkipUnlinkStackFrame(ref fp, ref sp);
                    }
                    else if (returnAddr >= LinkStackStubsBegin &&
                             returnAddr <= LinkStackStubsLimit)
                    {
                        returnAddr = SkipLinkStackStubFrame(ref fp, ref sp);
                    }
                    else
                    {
                        VTable.NotReached("Unexpected link stack function");
                    }
                }
#endif

                // Exit loop if we have reached the of the stack segment
                if (fp >= stopMarker && sp < stopMarker)
                {
                    break;
                }
                int tableIndex = CallSiteTableNumber(returnAddr);
                if (tableIndex < 0)
                {
                    break;
                }
                int callSiteSet = CallSiteSetNumber(returnAddr, tableIndex);
                if (callSiteSet < 0)
                {
                    break;
                }
                ushort *callSiteToIndexTable =
                    callSetSiteNumberToIndex[tableIndex];
                int activationIndex = (int)callSiteToIndexTable[callSiteSet];
                VTable.Assert(activationIndex >= 0);
                CompressedFrameDescriptor *descriptorTable =
                    activationDescriptorTable[tableIndex];
                CompressedFrameDescriptor frameDescriptor =
                    descriptorTable[activationIndex];
                bool done = WalkStackFrame(ref fp, ref sp, ref calleeSaves,
                                           ref returnAddr,
                                           VisitThreadReference,
                                           VisitPinnedReference,
                                           frameDescriptor,
                                           stopMarker, thread);
                if (done)
                {
                    break;
                }
                numStackFrames++;
            }
            calleeSaves.ClearCalleeSaves();
            return(numStackFrames);
        }
Exemple #2
0
        bool WalkStackFrame(ref UIntPtr *framePointer,
                            ref UIntPtr *stackPointer,
                            ref CalleeSaveLocations calleeSaves,
                            ref UIntPtr returnAddr,
                            NonNullReferenceVisitor threadReferenceVisitor,
                            NonNullReferenceVisitor pinnedReferenceVisitor,
                            CompressedFrameDescriptor smallFrameDescriptor,
                            TransitionRecord *stopMarker,
                            Thread thread)
        // BUGBUG: Remove thread argument when ThreadContext is on stack!
        {
            FrameDescriptor frameDescriptor =
                new FrameDescriptor(smallFrameDescriptor);

            if (frameDescriptor.isFramePointerOmitted)
            {
                framePointer = stackPointer + frameDescriptor.frameSize;
            }
            if (FrameContainsTransitionRecord(framePointer, stackPointer,
                                              stopMarker))
            {
                return(true);    // true: done
            }
            switch (frameDescriptor.argumentTag)
            {
            case FrameDescriptor.ESCAPE32_TAG: {
                int *table       = (int *)frameDescriptor.argumentMaskOrTable;
                int  count       = table[0];
                int  pinnedCount = table[1];
                int *offsets     = &table[2];
                if (threadReferenceVisitor != null)
                {
                    for (int i = 0; i < count; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(loc);
                            VisitIfNotContext(thread, threadReferenceVisitor, loc);
                        }
                    }
                }
                if (frameDescriptor.hasPinnedVariables &&
                    pinnedReferenceVisitor != null)
                {
                    offsets = &offsets[count];
                    for (int i = 0; i < pinnedCount; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            pinnedReferenceVisitor.Visit(loc);
                        }
                    }
                }
                break;
            }

            case FrameDescriptor.ESCAPE16_TAG: {
                short *table       = (short *)frameDescriptor.argumentMaskOrTable;
                int    count       = table[0];
                int    pinnedCount = table[1];
                short *offsets     = &table[2];
                if (threadReferenceVisitor != null)
                {
                    for (int i = 0; i < count; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(loc);
                            VisitIfNotContext(thread, threadReferenceVisitor, loc);
                        }
                    }
                }
                if (frameDescriptor.hasPinnedVariables &&
                    pinnedReferenceVisitor != null)
                {
                    offsets = &offsets[count];
                    for (int i = 0; i < pinnedCount; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            pinnedReferenceVisitor.Visit(loc);
                        }
                    }
                }
                break;
            }

            case FrameDescriptor.ESCAPE8_TAG: {
                sbyte *table       = (sbyte *)frameDescriptor.argumentMaskOrTable;
                int    count       = table[0];
                int    pinnedCount = table[1];
                sbyte *offsets     = &table[2];
                if (threadReferenceVisitor != null)
                {
                    for (int i = 0; i < count; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(loc);
                            VisitIfNotContext(thread, threadReferenceVisitor, loc);
                        }
                    }
                }
                if (frameDescriptor.hasPinnedVariables &&
                    pinnedReferenceVisitor != null)
                {
                    offsets = &offsets[count];
                    for (int i = 0; i < pinnedCount; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            pinnedReferenceVisitor.Visit(loc);
                        }
                    }
                }
                break;
            }

            case FrameDescriptor.COMPRESSED_MASK_TAG: {
                // Process the arguments
                int inBetweenSlotsAbove =
                    frameDescriptor.inBetweenSlotsAbove;
                uint    stackArgSize = frameDescriptor.argumentCount;
                UIntPtr mask         = frameDescriptor.argumentMaskOrTable;
                if (threadReferenceVisitor != null && stackArgSize > 0)
                {
                    UIntPtr *argumentPointer =
                        framePointer + stackArgSize - 1 + inBetweenSlotsAbove;
                    for (int i = 0; mask != 0 && i < stackArgSize; i++)
                    {
                        if ((mask & 0x1) != 0 &&
                            *argumentPointer != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(p);
                            VisitIfNotContext(thread, threadReferenceVisitor,
                                              argumentPointer);
                        }
                        mask >>= 1;
                        argumentPointer--;
                    }
                }
                else
                {
                    for (int i = 0; mask != 0 && i < stackArgSize; i++)
                    {
                        mask >>= 1;
                    }
                }
                // Process the local variables
                if (threadReferenceVisitor != null)
                {
                    int transitionRecordSize =
                        frameDescriptor.hasTransitionRecord ?
                        sizeof(TransitionRecord) / sizeof(UIntPtr) :
                        0;
                    int registerCount =
                        CountBits(frameDescriptor.calleeSaveMask);
                    int inBetweenSlotsBelow =
                        frameDescriptor.inBetweenSlotsBelow;
                    UIntPtr *variablePtr =
                        framePointer - inBetweenSlotsBelow - registerCount
                        - transitionRecordSize - 1;    // -1 because FP is pointing in "above" region.
                    while (mask != UIntPtr.Zero)
                    {
                        if ((mask & 0x1) != 0 &&
                            *variablePtr != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(p);
                            VisitIfNotContext(thread, threadReferenceVisitor,
                                              variablePtr);
                        }
                        mask >>= 1;
                        variablePtr--;
                    }
                }
                break;
            }

            default: {
                VTable.NotReached("FrameDescriptor mask switch failed");
                break;
            }
            }
            if (frameDescriptor.calleeSaveValueMask != 0 &&
                threadReferenceVisitor != null)
            {
                calleeSaves.ScanLiveRegs(frameDescriptor.calleeSaveValueMask,
                                         threadReferenceVisitor);
            }

#if X86 || AMD64 || ISA_IX86 || ISA_IX64
            UIntPtr nextReturnAddr;
            if (frameDescriptor.isFramePointerOmitted)
            {
                nextReturnAddr = *framePointer;
                stackPointer   = framePointer + 1;
            }
            else
            {
                nextReturnAddr = *(framePointer + 1);
                stackPointer   = framePointer + 2;
            }
#elif ARM || ISA_ARM
            // CompressedFrameDescriptor is the target specific portion.
            // This will be refactored to FrameDescriptor via partial classes.
            UIntPtr nextReturnAddr = CompressedFrameDescriptor.NextCallSite(frameDescriptor.isFramePointerOmitted, framePointer, out stackPointer);
#else
#error Unknown Architecture
#endif

            // In Singularity, the final return address of a thread is zero
            if (nextReturnAddr != UIntPtr.Zero)
            {
                calleeSaves.PopFrame(framePointer,
                                     frameDescriptor.calleeSaveMask,
                                     frameDescriptor.isFramePointerOmitted,
                                     frameDescriptor.hasTransitionRecord);
            }
            else
            {
                calleeSaves.ClearFrame(frameDescriptor.calleeSaveMask,
                                       frameDescriptor.isFramePointerOmitted);
            }
            UIntPtr *calcedfp = (UIntPtr *)calleeSaves.GetFramePointer();
            if (calcedfp != null)
            {
                framePointer = calcedfp;
            }
            returnAddr = nextReturnAddr;
            return(false); // false: not done scanning: proceed to next frame
        }