Fix step with stackalloc (#27246) (#27351)
authorSteve MacLean <Steve.MacLean@microsoft.com>
Tue, 22 Oct 2019 20:58:15 +0000 (16:58 -0400)
committerGitHub <noreply@github.com>
Tue, 22 Oct 2019 20:58:15 +0000 (16:58 -0400)
* Make ControllerStackInfo::m_returnFrame private

* Make ControllerStackInfo always capture a return frame

In case the active frame has no managed caller, capture
the unmanaged frame

* Fix step over stackalloc

Generalize handling of stack allocations and stepping

* Fix GetFunctionFromToken() argument checking

Check token type is a method before creating a CordbFunction.

Add extra assert to check for invalid tokens

src/debug/di/module.cpp
src/debug/di/rsfunction.cpp
src/debug/di/rspriv.h
src/debug/ee/controller.cpp
src/debug/ee/controller.h
src/debug/ee/frameinfo.cpp
src/debug/ee/frameinfo.h
src/inc/regdisp.h

index 5fb335e..809d005 100644 (file)
@@ -1550,7 +1550,8 @@ HRESULT CordbModule::GetFunctionFromToken(mdMethodDef token,
         RSLockHolder lockHolder(GetProcess()->GetProcessLock());
 
         // Check token is valid.
-        if ((token == mdMethodDefNil) || 
+        if ((token == mdMethodDefNil) ||
+            (TypeFromToken(token) != mdtMethodDef) ||
             (!GetMetaDataImporter()->IsValidToken(token)))
         {
             ThrowHR(E_INVALIDARG);
index 82ac875..7dca982 100644 (file)
@@ -49,6 +49,7 @@ CordbFunction::CordbFunction(CordbModule * m,
     m_methodSigParserCached = SigParser(NULL, 0);
 
     _ASSERTE(enCVersion >= CorDB_DEFAULT_ENC_FUNCTION_VERSION);
+    _ASSERTE(TypeFromToken(m_MDToken) == mdtMethodDef);
 }
 
 
index 6e4a93f..237af6b 100644 (file)
@@ -5537,7 +5537,7 @@ private:
     RSSmartPtr<CordbNativeCode> m_nativeCode;
 
     // Metadata Token for the IL function. Scoped to m_module.
-    mdMethodDef              m_MDToken;
+    const mdMethodDef        m_MDToken;
 
     // EnC version number of this instance
     SIZE_T                   m_dwEnCVersionNumber; 
index a82666d..183bf3a 100644 (file)
@@ -336,8 +336,8 @@ void ControllerStackInfo::GetStackInfo(
 
     if (result == SWA_DONE)
     {
-        _ASSERTE(!m_returnFound);
-        m_returnFrame = m_activeFrame;
+        _ASSERTE(!HasReturnFrame()); // We didn't find a managed return frame
+        _ASSERTE(HasReturnFrame(true)); // All threads have at least one unmanaged frame
     }
 }
 
@@ -418,14 +418,6 @@ StackWalkAction ControllerStackInfo::WalkStack(FrameInfo *pInfo, void *data)
 
         if (i->m_activeFound )
         {
-            // We care if the current frame is unmanaged (in case a managed stepper is initiated
-            // on a thread currently in unmanaged code). But since we can't step-out to UM frames, 
-            // we can just skip them in the stack walk.
-            if (!pInfo->managed)
-            {
-                return SWA_CONTINUE;
-            }
-        
             if (pInfo->chainReason == CHAIN_CLASS_INIT)
                 i->m_specialChainReason = pInfo->chainReason;
 
@@ -439,7 +431,9 @@ StackWalkAction ControllerStackInfo::WalkStack(FrameInfo *pInfo, void *data)
 
                 i->m_returnFound = true;
 
-                return SWA_ABORT;
+                // We care if the current frame is unmanaged
+                // Continue unless we found a managed return frame.
+                return pInfo->managed ? SWA_ABORT : SWA_CONTINUE;
             }
         }
         else
@@ -2483,10 +2477,10 @@ bool DebuggerController::MatchPatch(Thread *thread,
         // !!! This check should really be != , but there is some ambiguity about which frame is the parent frame
         // in the destination returned from Frame::TraceFrame, so this allows some slop there.
 
-        if (info.HasReturnFrame() && IsCloserToLeaf(info.m_returnFrame.fp, patch->fp))
+        if (info.HasReturnFrame() && IsCloserToLeaf(info.GetReturnFrame().fp, patch->fp))
         {
             LOG((LF_CORDB, LL_INFO10000, "Patch hit but frame not matched at %p (current=%p, patch=%p)\n",
-                patch->address, info.m_returnFrame.fp.GetSPValue(), patch->fp.GetSPValue()));
+                patch->address, info.GetReturnFrame().fp.GetSPValue(), patch->fp.GetSPValue()));
 
             return false;
         }
@@ -3761,14 +3755,14 @@ bool DebuggerController::DispatchTraceCall(Thread *thread,
                         _ASSERTE(info.HasReturnFrame());
 
                         // This check makes sure that we don't do this logic for inlined frames.
-                        if (info.m_returnFrame.md->IsILStub())
+                        if (info.GetReturnFrame().md->IsILStub())
                         {
                             // Make sure that the frame pointer of the active frame is actually
                             // the address of an exit frame.
                             _ASSERTE( (static_cast<Frame*>(info.m_activeFrame.fp.GetSPValue()))->GetFrameType()
                                       == Frame::TYPE_EXIT );
-                            _ASSERTE(!info.m_returnFrame.HasChainMarker());
-                            fpToCheck = info.m_returnFrame.fp;
+                            _ASSERTE(!info.GetReturnFrame().HasChainMarker());
+                            fpToCheck = info.GetReturnFrame().fp;
                         }
                     }
 
@@ -5094,14 +5088,14 @@ bool DebuggerStepper::IsRangeAppropriate(ControllerStackInfo *info)
         return false;
     }
 
-    FrameInfo *realFrame;
+    const FrameInfo *realFrame;
 
 #if defined(WIN64EXCEPTIONS)
     bool fActiveFrameIsFunclet = info->m_activeFrame.IsNonFilterFuncletFrame();
 
     if (fActiveFrameIsFunclet)
     {
-        realFrame = &(info->m_returnFrame);
+        realFrame = &(info->GetReturnFrame());
     }
     else
 #endif // WIN64EXCEPTIONS
@@ -5121,40 +5115,23 @@ bool DebuggerStepper::IsRangeAppropriate(ControllerStackInfo *info)
     }
 
 #if defined(WIN64EXCEPTIONS)
-    // There are two scenarios which make this function more complicated on WIN64.
+    // There are three scenarios which make this function more complicated on WIN64.
     // 1)  We initiate a step in the parent method or a funclet but end up stepping into another funclet closer to the leaf.
     //      a)  start in the parent method
     //      b)  start in a funclet
     // 2)  We initiate a step in a funclet but end up stepping out to the parent method or a funclet closer to the root.
     //      a) end up in the parent method
     //      b) end up in a funclet
+    // 3)  We initiate a step and then change stack allocation within the method or funclet
     // In both cases the range of the stepper should still be appropriate.
 
     bool fValidParentMethodFP = (m_fpParentMethod != LEAF_MOST_FRAME);
 
-    if (fActiveFrameIsFunclet)
-    {
-        // Scenario 1a
-        if (m_fp == info->m_returnFrame.fp)
-        {
-            LOG((LF_CORDB,LL_INFO10000, "DS::IRA: returning TRUE\n"));
-            return true;
-        }
-        // Scenario 1b & 2b have the same condition
-        else if (fValidParentMethodFP && (m_fpParentMethod == info->m_returnFrame.fp))
-        {
-            LOG((LF_CORDB,LL_INFO10000, "DS::IRA: returning TRUE\n"));
-            return true;
-        }
-    }
-    else
+    // All scenarios have the same condition
+    if (fValidParentMethodFP && (m_fpParentMethod == info->GetReturnFrame(true).fp))
     {
-        // Scenario 2a
-        if (fValidParentMethodFP && (m_fpParentMethod == info->m_activeFrame.fp))
-        {
-            LOG((LF_CORDB,LL_INFO10000, "DS::IRA: returning TRUE\n"));
-            return true;
-        }
+        LOG((LF_CORDB,LL_INFO10000, "DS::IRA: (parent SP) returning TRUE\n"));
+        return true;
     }
 #endif // WIN64EXCEPTIONS
 
@@ -5225,7 +5202,7 @@ bool DebuggerStepper::DetectHandleInterceptors(ControllerStackInfo *info)
 {
     LOG((LF_CORDB,LL_INFO10000,"DS::DHI: Start DetectHandleInterceptors\n"));
     LOG((LF_CORDB,LL_INFO10000,"DS::DHI: active frame=0x%08x, has return frame=%d, return frame=0x%08x m_reason:%d\n",
-         info->m_activeFrame.frame, info->HasReturnFrame(), info->m_returnFrame.frame, m_reason));
+         info->m_activeFrame.frame, info->HasReturnFrame(), info->GetReturnFrame().frame, m_reason));
 
     // If this is a normal step, then we want to continue stepping, even if we
     // are in an interceptor.
@@ -5246,7 +5223,7 @@ bool DebuggerStepper::DetectHandleInterceptors(ControllerStackInfo *info)
             if (!((CorDebugIntercept)info->m_activeFrame.frame->GetInterception() & Frame::Interception(m_rgfInterceptStop)))
             {
                 LOG((LF_CORDB,LL_INFO10000,"DS::DHI: Stepping out b/c of excluded frame type:0x%x\n",
-                     info->m_returnFrame. frame->GetInterception()));
+                     info->m_activeFrame.frame->GetInterception()));
 
                 fAttemptStepOut = true;
             }
@@ -5260,14 +5237,14 @@ bool DebuggerStepper::DetectHandleInterceptors(ControllerStackInfo *info)
 
         if ((m_reason == STEP_EXCEPTION_FILTER) ||
             (info->HasReturnFrame() &&
-            info->m_returnFrame.frame != NULL &&
-            info->m_returnFrame.frame != FRAME_TOP &&
-            info->m_returnFrame.frame->GetInterception() != Frame::INTERCEPTION_NONE))
+            info->GetReturnFrame().frame != NULL &&
+            info->GetReturnFrame().frame != FRAME_TOP &&
+            info->GetReturnFrame().frame->GetInterception() != Frame::INTERCEPTION_NONE))
         {
             if (m_reason == STEP_EXCEPTION_FILTER)
             {
                 // Exceptions raised inside of the EE by COMPlusThrow, FCThrow, etc will not
-                // insert an ExceptionFrame, and hence info->m_returnFrame.frame->GetInterception()
+                // insert an ExceptionFrame, and hence info->GetReturnFrame().frame->GetInterception()
                 // will not be accurate. Hence we use m_reason instead
 
                 if (!(Frame::INTERCEPTION_EXCEPTION & Frame::Interception(m_rgfInterceptStop)))
@@ -5276,10 +5253,10 @@ bool DebuggerStepper::DetectHandleInterceptors(ControllerStackInfo *info)
                     fAttemptStepOut = true;
                 }
             }
-            else if (!(info->m_returnFrame.frame->GetInterception() & Frame::Interception(m_rgfInterceptStop)))
+            else if (!(info->GetReturnFrame().frame->GetInterception() & Frame::Interception(m_rgfInterceptStop)))
             {
                 LOG((LF_CORDB,LL_INFO10000,"DS::DHI: Stepping out b/c of excluded return frame type:0x%x\n",
-                     info->m_returnFrame.frame->GetInterception()));
+                     info->GetReturnFrame().frame->GetInterception()));
 
                 fAttemptStepOut = true;
             }
@@ -5994,7 +5971,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
             AddBindAndActivateNativeManagedPatch(info->m_activeFrame.md,
                      ji,
                      offset,
-                     info->m_returnFrame.fp,
+                     info->GetReturnFrame().fp,
                      NULL);
             return true;
         }
@@ -6013,7 +5990,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
             AddBindAndActivateNativeManagedPatch(info->m_activeFrame.md,
                      ji,
                      offset,
-                     info->m_returnFrame.fp,
+                     info->GetReturnFrame().fp,
                      NULL);
             return true;
 
@@ -6031,7 +6008,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
                 AddBindAndActivateNativeManagedPatch(info->m_activeFrame.md,
                          ji,
                          CodeRegionInfo::GetCodeRegionInfo(ji, info->m_activeFrame.md).AddressToOffset(walker.GetNextIP()),
-                         info->m_returnFrame.fp,
+                         info->GetReturnFrame().fp,
                          NULL);
                 return true;
             }
@@ -6043,7 +6020,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
                     AddBindAndActivateNativeManagedPatch(info->m_activeFrame.md, 
                                                          ji, 
                                                          offset, 
-                                                         info->m_returnFrame.fp, 
+                                                         info->GetReturnFrame().fp,
                                                          NULL);
                     return true;
                 }
@@ -6061,7 +6038,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
                     AddBindAndActivateNativeManagedPatch(info->m_activeFrame.md,
                              ji,
                              offset,
-                             info->m_returnFrame.fp,
+                             info->GetReturnFrame().fp,
                              NULL);
 
                     LOG((LF_CORDB,LL_INFO10000,"DS0x%x m_reason=STEP_CALL 2\n",
@@ -6084,7 +6061,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
                 AddBindAndActivateNativeManagedPatch(info->m_activeFrame.md,
                          ji,
                          offset,
-                         info->m_returnFrame.fp,
+                         info->GetReturnFrame().fp,
                          NULL);
 
                 LOG((LF_CORDB,LL_INFO10000,"DS 0x%x m_reason=STEP_CALL4\n",this));
@@ -6103,7 +6080,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
                 AddBindAndActivateNativeManagedPatch(info->m_activeFrame.md,
                     ji,
                     offset,
-                    info->m_returnFrame.fp,
+                    info->GetReturnFrame().fp,
                     NULL);
                 return true;
             }
@@ -6197,31 +6174,31 @@ void DebuggerStepper::TrapStepOut(ControllerStackInfo *info, bool fForceTraditio
         _ASSERTE(info->HasReturnFrame());
         
 #ifdef _TARGET_ARM_
-        while (info->HasReturnFrame() && info->m_activeFrame.md != info->m_returnFrame.md)
+        while (info->HasReturnFrame() && info->m_activeFrame.md != info->GetReturnFrame().md)
         {
             StackTraceTicket ticket(info);
-            returnInfo.GetStackInfo(ticket, GetThread(), info->m_returnFrame.fp, NULL);
+            returnInfo.GetStackInfo(ticket, GetThread(), info->GetReturnFrame().fp, NULL);
             info = &returnInfo;
         }
         
         _ASSERTE(info->HasReturnFrame());
 #endif
 
-        _ASSERTE(info->m_activeFrame.md == info->m_returnFrame.md);
+        _ASSERTE(info->m_activeFrame.md == info->GetReturnFrame().md);
 
         if (m_eMode == cStepOut)
         {
             StackTraceTicket ticket(info);
-            returnInfo.GetStackInfo(ticket, GetThread(), info->m_returnFrame.fp, NULL);
+            returnInfo.GetStackInfo(ticket, GetThread(), info->GetReturnFrame().fp, NULL);
             info = &returnInfo;
         }
         else
         {
-            _ASSERTE(info->m_returnFrame.managed);
-            _ASSERTE(info->m_returnFrame.frame == NULL);
+            _ASSERTE(info->GetReturnFrame().managed);
+            _ASSERTE(info->GetReturnFrame().frame == NULL);
 
-            MethodDesc *md = info->m_returnFrame.md;
-            dji = info->m_returnFrame.GetJitInfoFromFrame();
+            MethodDesc *md = info->GetReturnFrame().md;
+            dji = info->GetReturnFrame().GetJitInfoFromFrame();
 
             // The return value of a catch funclet is the control PC to resume to.
             // The return value of a finally funclet has no meaning, so we need to check
@@ -6236,17 +6213,17 @@ void DebuggerStepper::TrapStepOut(ControllerStackInfo *info, bool fForceTraditio
             {
                 SIZE_T reloffset = dji->m_codeRegionInfo.AddressToOffset((BYTE*)resumePC);
 
-                AddBindAndActivateNativeManagedPatch(info->m_returnFrame.md,
+                AddBindAndActivateNativeManagedPatch(info->GetReturnFrame().md,
                     dji,
                     reloffset,
-                    info->m_returnFrame.fp,
+                    info->GetReturnFrame().fp,
                     NULL);
 
                 LOG((LF_CORDB, LL_INFO10000,
                      "DS::TSO:normally managed code AddPatch"
                      " in %s::%s, offset 0x%x, m_reason=%d\n",
-                     info->m_returnFrame.md->m_pszDebugClassName,
-                     info->m_returnFrame.md->m_pszDebugMethodName,
+                     info->GetReturnFrame().md->m_pszDebugClassName,
+                     info->GetReturnFrame().md->m_pszDebugMethodName,
                      reloffset, m_reason));
 
                 // Do not set m_reason to STEP_RETURN here.  Logically, the funclet and the parent method are the
@@ -6289,7 +6266,7 @@ void DebuggerStepper::TrapStepOut(ControllerStackInfo *info, bool fForceTraditio
         // not to report the managed frame that was at the same SP. However the unmanaged
         // frame might be used in the mixed-mode step out case so I don't suppress it
         // there.
-        returnInfo.GetStackInfo(ticket, GetThread(), info->m_returnFrame.fp, NULL, !(m_rgfMappingStop & STOP_UNMANAGED));
+        returnInfo.GetStackInfo(ticket, GetThread(), info->GetReturnFrame().fp, NULL, !(m_rgfMappingStop & STOP_UNMANAGED));
         info = &returnInfo;
 
 #ifdef _DEBUG
@@ -6353,7 +6330,7 @@ void DebuggerStepper::TrapStepOut(ControllerStackInfo *info, bool fForceTraditio
                 AddBindAndActivateNativeManagedPatch(info->m_activeFrame.md,
                     dji,
                     reloffset,
-                    info->m_returnFrame.fp,
+                    info->GetReturnFrame().fp,
                     NULL);
 
                 LOG((LF_CORDB, LL_INFO10000,
@@ -6508,11 +6485,11 @@ void DebuggerStepper::TrapStepOut(ControllerStackInfo *info, bool fForceTraditio
                 LOG((LF_CORDB, LL_INFO10000,
                  "DS::TSO: Setting unmanaged trace patch at 0x%x(%x)\n",
                      GetControlPC(&(info->m_activeFrame.registers)),
-                     info->m_returnFrame.fp.GetSPValue()));
+                     info->GetReturnFrame().fp.GetSPValue()));
 
 
                 AddAndActivateNativePatchForAddress((CORDB_ADDRESS_TYPE *)GetControlPC(&(info->m_activeFrame.registers)),
-                         info->m_returnFrame.fp,
+                         info->GetReturnFrame().fp,
                          FALSE,
                          TRACE_UNMANAGED);
 
@@ -6566,16 +6543,16 @@ void DebuggerStepper::StepOut(FramePointer fp, StackTraceTicket ticket)
     m_fp = info.m_activeFrame.fp;
 #if defined(WIN64EXCEPTIONS)
     // We need to remember the parent method frame pointer here so that we will recognize
-    // the range of the stepper as being valid when we return to the parent method.
-    if (info.m_activeFrame.IsNonFilterFuncletFrame())
+    // the range of the stepper as being valid when we return to the parent method or stackalloc.
+    if (info.HasReturnFrame(true))
     {
-        m_fpParentMethod = info.m_returnFrame.fp;
+        m_fpParentMethod = info.GetReturnFrame(true).fp;
     }
 #endif // WIN64EXCEPTIONS
 
     m_eMode = cStepOut;
 
-    _ASSERTE((fp == LEAF_MOST_FRAME) || (info.m_activeFrame.md != NULL) || (info.m_returnFrame.md != NULL));
+    _ASSERTE((fp == LEAF_MOST_FRAME) || (info.m_activeFrame.md != NULL) || (info.GetReturnFrame().md != NULL));
 
     TrapStepOut(&info);
     EnableUnwind(m_fp);
@@ -6837,7 +6814,7 @@ bool DebuggerStepper::Step(FramePointer fp, bool in,
     info.GetStackInfo(ticket, thread, fp, context);
 
     _ASSERTE((fp == LEAF_MOST_FRAME) || (info.m_activeFrame.md != NULL) ||
-             (info.m_returnFrame.md != NULL));
+             (info.GetReturnFrame().md != NULL));
 
     m_stepIn = in;
 
@@ -6905,10 +6882,10 @@ bool DebuggerStepper::Step(FramePointer fp, bool in,
         m_fp = info.m_activeFrame.fp;
 #if defined(WIN64EXCEPTIONS)
         // We need to remember the parent method frame pointer here so that we will recognize
-        // the range of the stepper as being valid when we return to the parent method.
-        if (info.m_activeFrame.IsNonFilterFuncletFrame())
+        // the range of the stepper as being valid when we return to the parent method or stackalloc.
+        if (info.HasReturnFrame(true))
         {
-            m_fpParentMethod = info.m_returnFrame.fp;
+            m_fpParentMethod = info.GetReturnFrame(true).fp;
         }
 #endif // WIN64EXCEPTIONS
     }
@@ -7600,8 +7577,8 @@ void DebuggerStepper::PrepareForSendEvent(StackTraceTicket ticket)
 #if !defined(WIN64EXCEPTIONS)
             IsCloserToRoot(m_fpStepInto, csi.m_activeFrame.fp)
 #else
-            IsCloserToRoot(m_fpStepInto, (csi.m_activeFrame.IsNonFilterFuncletFrame() ? csi.m_returnFrame.fp : csi.m_activeFrame.fp))
-#endif // WIN64EXCEPTIONS
+            IsCloserToRoot(m_fpStepInto, (csi.m_activeFrame.IsNonFilterFuncletFrame() ? csi.GetReturnFrame().fp : csi.m_activeFrame.fp))
+#endif // FEATURE_EH_FUNCLETS
            )
 
         {
@@ -7815,7 +7792,7 @@ bool DebuggerJMCStepper::TrapStepInHelper(
     AddBindAndActivateNativeManagedPatch(pInfo->m_activeFrame.md,
              dji,
              offset,
-             pInfo->m_returnFrame.fp,
+             pInfo->GetReturnFrame().fp,
              NULL);
 
     EnableMethodEnter();
index 7172662..0d4776d 100644 (file)
@@ -140,15 +140,15 @@ private:
  *  FrameInfo m_activeFrame:   A FrameInfo
  *      describing the target frame.  This should always be valid after a
  *      call to GetStackInfo.
+ *
+ *  private:
+ *  bool m_activeFound:  Set to true if we found the target frame.
+ *  bool m_returnFound:  Set to true if we found the target's return frame.
  * 
  *  FrameInfo m_returnFrame:   A FrameInfo
  *      describing the frame above the target frame, if  target's
  *      return frame were found (call HasReturnFrame() to see if this is
  *      valid). Otherwise, this will be the same as m_activeFrame, above
- *
- * private:
- * bool m_activeFound:  Set to true if we found the target frame.
- * bool m_returnFound:  Set to true if we found the target's return frame.
  */
 class ControllerStackInfo
 {
@@ -165,7 +165,6 @@ public:
     bool                    m_targetFrameFound;
 
     FrameInfo               m_activeFrame;
-    FrameInfo               m_returnFrame;
 
     CorDebugChainReason     m_specialChainReason;
 
@@ -199,8 +198,9 @@ public:
     //bool ControllerStackInfo::HasReturnFrame()  Returns
     //      true if m_returnFrame is valid.  Returns false
     //      if m_returnFrame is set to m_activeFrame
-    bool HasReturnFrame() {LIMITED_METHOD_CONTRACT;  return m_returnFound; }
+    bool HasReturnFrame(bool allowUnmanaged = false) {LIMITED_METHOD_CONTRACT;  return m_returnFound && (allowUnmanaged || m_returnFrame.managed); }
 
+    FrameInfo& GetReturnFrame(bool allowUnmanaged = false) {LIMITED_METHOD_CONTRACT; return HasReturnFrame(allowUnmanaged) ? m_returnFrame : m_activeFrame; }
     // This function "undoes" an unwind, i.e. it takes the active frame (the current frame)
     // and sets it to be the return frame (the caller frame).  Currently it is only used by
     // the stepper to step out of an LCG method.  See DebuggerStepper::DetectHandleLCGMethods()
@@ -213,6 +213,7 @@ private:
 
     bool                    m_activeFound;
     bool                    m_returnFound;
+    FrameInfo               m_returnFrame;
 
     // A ridiculous flag that is targetting a very narrow fix at issue 650903
     // (4.5.1/Blue).  This is set for the duration of a stackwalk designed to
index 4c0ef2b..3efbddd 100644 (file)
@@ -585,7 +585,7 @@ void FrameInfo::AssertValid()
 // Get the DJI associated w/ this frame. This is a convenience function.
 // This is recommended over using MethodDescs because DJI's are version-aware.
 //-----------------------------------------------------------------------------
-DebuggerJitInfo * FrameInfo::GetJitInfoFromFrame()
+DebuggerJitInfo * FrameInfo::GetJitInfoFromFrame() const
 {
     CONTRACTL
     {
index c407902..990cf1b 100644 (file)
@@ -130,7 +130,7 @@ public:
 
     // Does this FrameInfo represent a method frame? (aka a frameless frame)
     // This may be combined w/ both StubFrames and ChainMarkers.
-    bool HasMethodFrame() { return md != NULL && !internal; }
+    bool HasMethodFrame() const { return md != NULL && !internal; }
 
     // Is this frame for a stub?
     // This is mutually exclusive w/ Chain Markers.
@@ -138,14 +138,14 @@ public:
     // M2U transition may have the Method for the Managed Wrapper for the unmanaged call.
     // Stub frames map to internal frames on the RS.  They use the same enum 
     // (CorDebugInternalFrameType) to represent the type of the frame.
-    bool HasStubFrame() { return eStubFrameType != STUBFRAME_NONE; }
+    bool HasStubFrame() const { return eStubFrameType != STUBFRAME_NONE; }
 
     // Does this FrameInfo mark the start of a new chain? (A Frame info may both
     // start a chain and represent a method)
-    bool HasChainMarker() { return chainReason != CHAIN_NONE; }
+    bool HasChainMarker() const { return chainReason != CHAIN_NONE; }
 
     // Helper functions for retrieving the DJI and the DMI
-    DebuggerJitInfo * GetJitInfoFromFrame();
+    DebuggerJitInfo * GetJitInfoFromFrame() const;
     DebuggerMethodInfo * GetMethodInfoFromFrameOrThrow();
 
     // Debug helper which nops in retail; and asserts invariants in debug.
index 7875edf..546ce28 100644 (file)
@@ -48,7 +48,7 @@ struct REGDISPLAY_BASE {
     TADDR ControlPC;
 };
 
-inline PCODE GetControlPC(REGDISPLAY_BASE *pRD) {
+inline PCODE GetControlPC(const REGDISPLAY_BASE *pRD) {
     LIMITED_METHOD_DAC_CONTRACT;
     return (PCODE)(pRD->ControlPC);
 }