From be1aa1bf368dd47765d429ee0e557d8cb26f9bfd Mon Sep 17 00:00:00 2001 From: Steve MacLean Date: Tue, 22 Oct 2019 16:58:15 -0400 Subject: [PATCH] Fix step with stackalloc (#27246) (#27351) * 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 | 3 +- src/debug/di/rsfunction.cpp | 1 + src/debug/di/rspriv.h | 2 +- src/debug/ee/controller.cpp | 143 +++++++++++++++++++------------------------- src/debug/ee/controller.h | 13 ++-- src/debug/ee/frameinfo.cpp | 2 +- src/debug/ee/frameinfo.h | 8 +-- src/inc/regdisp.h | 2 +- 8 files changed, 77 insertions(+), 97 deletions(-) diff --git a/src/debug/di/module.cpp b/src/debug/di/module.cpp index 5fb335e..809d005 100644 --- a/src/debug/di/module.cpp +++ b/src/debug/di/module.cpp @@ -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); diff --git a/src/debug/di/rsfunction.cpp b/src/debug/di/rsfunction.cpp index 82ac875..7dca982 100644 --- a/src/debug/di/rsfunction.cpp +++ b/src/debug/di/rsfunction.cpp @@ -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); } diff --git a/src/debug/di/rspriv.h b/src/debug/di/rspriv.h index 6e4a93f..237af6b 100644 --- a/src/debug/di/rspriv.h +++ b/src/debug/di/rspriv.h @@ -5537,7 +5537,7 @@ private: RSSmartPtr 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; diff --git a/src/debug/ee/controller.cpp b/src/debug/ee/controller.cpp index a82666d..183bf3a 100644 --- a/src/debug/ee/controller.cpp +++ b/src/debug/ee/controller.cpp @@ -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(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(); diff --git a/src/debug/ee/controller.h b/src/debug/ee/controller.h index 7172662..0d4776d 100644 --- a/src/debug/ee/controller.h +++ b/src/debug/ee/controller.h @@ -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 diff --git a/src/debug/ee/frameinfo.cpp b/src/debug/ee/frameinfo.cpp index 4c0ef2b..3efbddd 100644 --- a/src/debug/ee/frameinfo.cpp +++ b/src/debug/ee/frameinfo.cpp @@ -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 { diff --git a/src/debug/ee/frameinfo.h b/src/debug/ee/frameinfo.h index c407902..990cf1b 100644 --- a/src/debug/ee/frameinfo.h +++ b/src/debug/ee/frameinfo.h @@ -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. diff --git a/src/inc/regdisp.h b/src/inc/regdisp.h index 4a7e57e..e43bd00 100644 --- a/src/inc/regdisp.h +++ b/src/inc/regdisp.h @@ -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); } -- 2.7.4