diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs index 9a51c47cb020e..576c1fe696be5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs @@ -11,15 +11,15 @@ namespace System.Diagnostics { public static partial class Debugger { + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DebugDebugger_Break")] + private static partial void BreakInternal(); + // Break causes a breakpoint to be signalled to an attached debugger. If no debugger // is attached, the user is asked if they want to attach a debugger. If yes, then the // debugger is launched. [MethodImpl(MethodImplOptions.NoInlining)] public static void Break() => BreakInternal(); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void BreakInternal(); - // Launch launches & attaches a debugger to the process. If a debugger is already attached, // nothing happens. // @@ -30,11 +30,6 @@ public static partial class Debugger // See code:NotifyOfCrossThreadDependency for more details. private sealed class CrossThreadDependencyNotification : ICustomDebuggerNotification { } - // Do not inline the slow path - [MethodImpl(MethodImplOptions.NoInlining)] - private static void NotifyOfCrossThreadDependencySlow() => - CustomNotification(new CrossThreadDependencyNotification()); - // Sends a notification to the debugger to indicate that execution is about to enter a path // involving a cross thread dependency. A debugger that has opted into this type of notification // can take appropriate action on receipt. For example, performing a funceval normally requires @@ -49,6 +44,14 @@ public static void NotifyOfCrossThreadDependency() { NotifyOfCrossThreadDependencySlow(); } + + // Do not inline the slow path + [MethodImpl(MethodImplOptions.NoInlining)] + static void NotifyOfCrossThreadDependencySlow() + { + var notify = new CrossThreadDependencyNotification(); + CustomNotification(ObjectHandleOnStack.Create(ref notify)); + } } [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DebugDebugger_Launch")] @@ -89,7 +92,7 @@ public static extern bool IsAttached // Posts a custom notification for the attached debugger. If there is no // debugger attached, has no effect. The debugger may or may not // report the notification depending on its settings. - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void CustomNotification(ICustomDebuggerNotification data); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DebugDebugger_CustomNotification")] + private static partial void CustomNotification(ObjectHandleOnStack data); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs index b68e4f2884b29..8c1850d31e840 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs @@ -30,9 +30,9 @@ internal StackFrame(StackFrameHelper stackFrameHelper, int skipFrames, bool need private void BuildStackFrame(int skipFrames, bool needFileInfo) { - StackFrameHelper StackF = new StackFrameHelper(null); + StackFrameHelper StackF = new StackFrameHelper(); - StackF.InitializeSourceInfo(0, needFileInfo, null); + StackF.InitializeSourceInfo(needFileInfo, null); int iNumOfFrames = StackF.GetNumberOfFrames(); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs index 8e90b6a2eec6c..f10af9c234712 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs @@ -13,7 +13,6 @@ namespace System.Diagnostics // VM\DebugDebugger.h. The binder will catch some of these layout problems. internal sealed class StackFrameHelper { - private Thread? targetThread; private int[]? rgiOffset; private int[]? rgiILOffset; @@ -48,9 +47,8 @@ private delegate void GetSourceLineInfoDelegate(Assembly? assembly, string assem [ThreadStatic] private static int t_reentrancy; - public StackFrameHelper(Thread? target) + public StackFrameHelper() { - targetThread = target; rgMethodHandle = null; rgiMethodToken = null; rgiOffset = null; @@ -85,9 +83,9 @@ public StackFrameHelper(Thread? target) // done by GetStackFramesInternal (on Windows for old PDB format). // - internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception? exception) + internal void InitializeSourceInfo(bool fNeedFileInfo, Exception? exception) { - StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception); + StackTrace.GetStackFramesInternal(this, fNeedFileInfo, exception); if (!fNeedFileInfo) return; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs index 26e002f990118..5d4bc6008e640 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs @@ -3,13 +3,17 @@ using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Diagnostics { public partial class StackTrace { - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception? e); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "StackTrace_GetStackFramesInternal")] + private static partial void GetStackFramesInternal(ObjectHandleOnStack sfh, [MarshalAs(UnmanagedType.Bool)] bool fNeedFileInfo, ObjectHandleOnStack e); + + internal static void GetStackFramesInternal(StackFrameHelper sfh, bool fNeedFileInfo, Exception? e) + => GetStackFramesInternal(ObjectHandleOnStack.Create(ref sfh), fNeedFileInfo, ObjectHandleOnStack.Create(ref e)); internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrames) { @@ -57,9 +61,9 @@ private void CaptureStackTrace(int skipFrames, bool fNeedFileInfo, Exception? e) { _methodsToSkip = skipFrames; - StackFrameHelper StackF = new StackFrameHelper(null); + StackFrameHelper StackF = new StackFrameHelper(); - StackF.InitializeSourceInfo(0, fNeedFileInfo, e); + StackF.InitializeSourceInfo(fNeedFileInfo, e); _numOfFrames = StackF.GetNumberOfFrames(); diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 8dbd2cf2ca058..778755481ddbf 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -3707,7 +3707,6 @@ void DacDbiInterfaceImpl::GetStackFramesFromException(VMPTR_Object vmObject, Dac DebugStackTrace::GetStackFramesData stackFramesData; stackFramesData.pDomain = NULL; - stackFramesData.skip = 0; stackFramesData.NumFramesRequested = 0; DebugStackTrace::GetStackFramesFromException(&objRef, &stackFramesData); @@ -3720,7 +3719,7 @@ void DacDbiInterfaceImpl::GetStackFramesFromException(VMPTR_Object vmObject, Dac for (INT32 index = 0; index < dacStackFramesLength; ++index) { - DebugStackTrace::DebugStackTraceElement const& currentElement = stackFramesData.pElements[index]; + DebugStackTrace::Element const& currentElement = stackFramesData.pElements[index]; DacExceptionCallStackData& currentFrame = dacStackFrames[index]; AppDomain* pDomain = AppDomain::GetCurrentDomain(); diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 8ed914cf31012..f2682725f0fd3 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -8849,7 +8849,7 @@ void Debugger::SendUserBreakpoint(Thread * thread) { THROWS; GC_TRIGGERS; - MODE_ANY; + MODE_PREEMPTIVE; PRECONDITION(thread != NULL); PRECONDITION(thread == ::GetThreadNULLOk()); diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index aef92ce036054..927b287844df7 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -468,7 +468,6 @@ BEGIN IDS_EE_INVALID_CA "Invalid custom attribute provided." IDS_EE_THREAD_CANNOT_GET "Unable to retrieve thread information." - IDS_EE_THREAD_BAD_STATE "Thread in invalid state." IDS_EE_THREAD_ABORT_WHILE_SUSPEND "Thread is suspended; attempting to abort." IDS_EE_NOVARIANTRETURN "PInvoke restriction: cannot return variants." diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h index 6962fdfec89b5..09bf78dfb93c4 100644 --- a/src/coreclr/dlls/mscorrc/resource.h +++ b/src/coreclr/dlls/mscorrc/resource.h @@ -233,7 +233,6 @@ #define IDS_EE_INVALID_CA 0x1a10 #define IDS_EE_THREAD_CANNOT_GET 0x1a15 -#define IDS_EE_THREAD_BAD_STATE 0x1a1b #define IDS_EE_THREAD_ABORT_WHILE_SUSPEND 0x1a1c #define IDS_EE_NOVARIANTRETURN 0x1a1d diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 38a05866ff3e2..6b00732ec1f90 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -757,7 +757,6 @@ DEFINE_METHOD(SAFE_HANDLE, DISPOSE_BOOL, Dispose, DEFINE_CLASS(SECURITY_EXCEPTION, Security, SecurityException) DEFINE_CLASS_U(Diagnostics, StackFrameHelper, StackFrameHelper) -DEFINE_FIELD_U(targetThread, StackFrameHelper, targetThread) DEFINE_FIELD_U(rgiOffset, StackFrameHelper, rgiOffset) DEFINE_FIELD_U(rgiILOffset, StackFrameHelper, rgiILOffset) DEFINE_FIELD_U(dynamicMethods, StackFrameHelper, dynamicMethods) diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index 988818d91d53d..abb873942abaa 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -40,12 +40,12 @@ // Else if a native debugger is attached, this should send a native break event (kernel32!DebugBreak) // Else, this should invoke Watson. // -FCIMPL0(void, DebugDebugger::Break) +extern "C" void QCALLTYPE DebugDebugger_Break() { - FCALL_CONTRACT; + QCALL_CONTRACT; #ifdef DEBUGGING_SUPPORTED - HELPER_METHOD_FRAME_BEGIN_0(); + BEGIN_QCALL; #ifdef _DEBUG { @@ -73,21 +73,17 @@ FCIMPL0(void, DebugDebugger::Break) // No managed debugger, but a native debug is attached. Explicitly fire a native user breakpoint. // Don't rely on Watson support since that may have a different policy. - // Toggle to preemptive before firing the debug event. This allows the debugger to suspend this + // Confirm we're in preemptive before firing the debug event. This allows the debugger to suspend this // thread at the debug event. - GCX_PREEMP(); + _ASSERTE(!GetThread()->PreemptiveGCDisabled()); // This becomes an unmanaged breakpoint, such as int 3. DebugBreak(); } - else - { - } - HELPER_METHOD_FRAME_END(); + END_QCALL; #endif // DEBUGGING_SUPPORTED } -FCIMPLEND extern "C" BOOL QCALLTYPE DebugDebugger_Launch() { @@ -230,44 +226,146 @@ FCIMPL0(FC_BOOL_RET, DebugDebugger::IsLogging) } FCIMPLEND -FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, - StackFrameHelper* pStackFrameHelperUNSAFE, - INT32 iSkip, - FC_BOOL_ARG fNeedFileInfo, - Object* pExceptionUNSAFE - ) +static StackWalkAction GetStackFramesCallback(CrawlFrame* pCf, VOID* data) { CONTRACTL { - FCALL_CHECK; - PRECONDITION(CheckPointer(pStackFrameHelperUNSAFE)); - PRECONDITION(CheckPointer(pExceptionUNSAFE, NULL_OK)); + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; } CONTRACTL_END; - STACKFRAMEHELPERREF pStackFrameHelper = (STACKFRAMEHELPERREF)ObjectToOBJECTREF(pStackFrameHelperUNSAFE); - OBJECTREF pException = ObjectToOBJECTREF(pExceptionUNSAFE); - PTRARRAYREF dynamicMethodArrayOrig = NULL; + // @todo: How do we know what kind of frame we have? + // Can we always assume FramedMethodFrame? + // NOT AT ALL!!!, but we can assume it's a function + // because we asked the stackwalker for it! + MethodDesc* pFunc = pCf->GetFunction(); - HELPER_METHOD_FRAME_BEGIN_2(pStackFrameHelper, pException); + DebugStackTrace::GetStackFramesData* pData = (DebugStackTrace::GetStackFramesData*)data; + if (pData->cElements >= pData->cElementsAllocated) + { + DebugStackTrace::Element* pTemp = new (nothrow) DebugStackTrace::Element[2*pData->cElementsAllocated]; + if (pTemp == NULL) + { + return SWA_ABORT; + } - GCPROTECT_BEGIN(dynamicMethodArrayOrig); + memcpy(pTemp, pData->pElements, pData->cElementsAllocated * sizeof(DebugStackTrace::Element)); - ASSERT(iSkip >= 0); + delete [] pData->pElements; + + pData->pElements = pTemp; + pData->cElementsAllocated *= 2; + } - GetStackFramesData data; + PCODE ip; + DWORD dwNativeOffset; - data.pDomain = GetAppDomain(); + if (pCf->IsFrameless()) + { + // Real method with jitted code. + dwNativeOffset = pCf->GetRelOffset(); + ip = GetControlPC(pCf->GetRegisterSet()); + } + else + { + ip = (PCODE)NULL; + dwNativeOffset = 0; + } + + // Pass on to InitPass2 that the IP has already been adjusted (decremented by 1) + INT flags = pCf->IsIPadjusted() ? STEF_IP_ADJUSTED : 0; + + pData->pElements[pData->cElements].InitPass1( + dwNativeOffset, + pFunc, + ip, + flags); + + // We'll init the IL offsets outside the TSL lock. + + ++pData->cElements; + + // check if we already have the number of frames that the user had asked for + if ((pData->NumFramesRequested != 0) && (pData->NumFramesRequested <= pData->cElements)) + { + return SWA_ABORT; + } + + return SWA_CONTINUE; +} + +static void GetStackFrames(DebugStackTrace::GetStackFramesData *pData) +{ + CONTRACTL + { + MODE_COOPERATIVE; + GC_TRIGGERS; + THROWS; + } + CONTRACTL_END; + + ASSERT (pData != NULL); + + pData->cElements = 0; + + // if the caller specified (< 20) frames are required, then allocate + // only that many + if ((pData->NumFramesRequested > 0) && (pData->NumFramesRequested < 20)) + { + pData->cElementsAllocated = pData->NumFramesRequested; + } + else + { + pData->cElementsAllocated = 20; + } + + // Allocate memory for the initial 'n' frames + pData->pElements = new DebugStackTrace::Element[pData->cElementsAllocated]; + GetThread()->StackWalkFrames(GetStackFramesCallback, pData, FUNCTIONSONLY | QUICKUNWIND, NULL); + + // Do a 2nd pass outside of any locks. + // This will compute IL offsets. + for (INT32 i = 0; i < pData->cElements; i++) + { + pData->pElements[i].InitPass2(); + } +} + +extern "C" void QCALLTYPE StackTrace_GetStackFramesInternal( + QCall::ObjectHandleOnStack stackFrameHelper, + BOOL fNeedFileInfo, + QCall::ObjectHandleOnStack exception) +{ + QCALL_CONTRACT; - data.skip = iSkip; + BEGIN_QCALL; - data.NumFramesRequested = pStackFrameHelper->iFrameCount; + GCX_COOP(); - if (pException == NULL) + struct { - // Thread is NULL if it's the current thread. - data.TargetThread = pStackFrameHelper->targetThread; - GetStackFrames(NULL, (void*)-1, &data); + STACKFRAMEHELPERREF pStackFrameHelper; + OBJECTREF pException; + PTRARRAYREF dynamicMethodArrayOrig; + } gc{}; + gc.pStackFrameHelper = NULL; + gc.pException = NULL; + gc.dynamicMethodArrayOrig = NULL; + GCPROTECT_BEGIN(gc); + gc.pStackFrameHelper = (STACKFRAMEHELPERREF)stackFrameHelper.Get(); + gc.pException = exception.Get(); + + DebugStackTrace::GetStackFramesData data; + + data.pDomain = GetAppDomain(); + + data.NumFramesRequested = gc.pStackFrameHelper->iFrameCount; + + if (gc.pException == NULL) + { + GetStackFrames(&data); } else { @@ -276,13 +374,17 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, // is thrown again (resetting the dynamic method array reference in the object) // that may result in resolver objects getting collected before they can be reachable again // (from the code below). - GetStackFramesFromException(&pException, &data, &dynamicMethodArrayOrig); + DebugStackTrace::GetStackFramesFromException(&gc.pException, &data, &gc.dynamicMethodArrayOrig); } - if (data.cElements != 0) + if (data.cElements == 0) + { + gc.pStackFrameHelper->iFrameCount = 0; + } + else { #if defined(FEATURE_ISYM_READER) && defined(FEATURE_COMINTEROP) - if (FC_ACCESS_BOOL(fNeedFileInfo)) + if (fNeedFileInfo) { // Calls to COM up ahead. EnsureComStarted(); @@ -291,59 +393,59 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, // Allocate memory for the MethodInfo objects BASEARRAYREF methodInfoArray = (BASEARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_I, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgMethodHandle), (OBJECTREF)methodInfoArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgMethodHandle), (OBJECTREF)methodInfoArray); // Allocate memory for the Offsets OBJECTREF offsets = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiOffset), (OBJECTREF)offsets); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiOffset), (OBJECTREF)offsets); // Allocate memory for the ILOffsets OBJECTREF ilOffsets = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiILOffset), (OBJECTREF)ilOffsets); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiILOffset), (OBJECTREF)ilOffsets); // Allocate memory for the array of assembly file names PTRARRAYREF assemblyPathArray = (PTRARRAYREF) AllocateObjectArray(data.cElements, g_pStringClass); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgAssemblyPath), (OBJECTREF)assemblyPathArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgAssemblyPath), (OBJECTREF)assemblyPathArray); // Allocate memory for the array of assemblies PTRARRAYREF assemblyArray = (PTRARRAYREF) AllocateObjectArray(data.cElements, g_pObjectClass); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgAssembly), (OBJECTREF)assemblyArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgAssembly), (OBJECTREF)assemblyArray); // Allocate memory for the LoadedPeAddress BASEARRAYREF loadedPeAddressArray = (BASEARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_I, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgLoadedPeAddress), (OBJECTREF)loadedPeAddressArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgLoadedPeAddress), (OBJECTREF)loadedPeAddressArray); // Allocate memory for the LoadedPeSize OBJECTREF loadedPeSizeArray = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLoadedPeSize), (OBJECTREF)loadedPeSizeArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiLoadedPeSize), (OBJECTREF)loadedPeSizeArray); // Allocate memory for the IsFileLayout flags OBJECTREF isFileLayouts = AllocatePrimitiveArray(ELEMENT_TYPE_BOOLEAN, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiIsFileLayout), (OBJECTREF)isFileLayouts); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiIsFileLayout), (OBJECTREF)isFileLayouts); // Allocate memory for the InMemoryPdbAddress BASEARRAYREF inMemoryPdbAddressArray = (BASEARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_I, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgInMemoryPdbAddress), (OBJECTREF)inMemoryPdbAddressArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgInMemoryPdbAddress), (OBJECTREF)inMemoryPdbAddressArray); // Allocate memory for the InMemoryPdbSize OBJECTREF inMemoryPdbSizeArray = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiInMemoryPdbSize), (OBJECTREF)inMemoryPdbSizeArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiInMemoryPdbSize), (OBJECTREF)inMemoryPdbSizeArray); // Allocate memory for the MethodTokens OBJECTREF methodTokens = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiMethodToken), (OBJECTREF)methodTokens); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiMethodToken), (OBJECTREF)methodTokens); // Allocate memory for the Filename string objects PTRARRAYREF filenameArray = (PTRARRAYREF) AllocateObjectArray(data.cElements, g_pStringClass); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgFilename), (OBJECTREF)filenameArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgFilename), (OBJECTREF)filenameArray); // Allocate memory for the LineNumbers OBJECTREF lineNumbers = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLineNumber), (OBJECTREF)lineNumbers); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiLineNumber), (OBJECTREF)lineNumbers); // Allocate memory for the ColumnNumbers OBJECTREF columnNumbers = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiColumnNumber), (OBJECTREF)columnNumbers); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiColumnNumber), (OBJECTREF)columnNumbers); // Allocate memory for the flag indicating if this frame represents the last one from a foreign // exception stack trace provided we have any such frames. Otherwise, set it to null. @@ -357,11 +459,11 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, { IsLastFrameFromForeignStackTraceFlags = AllocatePrimitiveArray(ELEMENT_TYPE_BOOLEAN, data.cElements); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace), (OBJECTREF)IsLastFrameFromForeignStackTraceFlags); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace), (OBJECTREF)IsLastFrameFromForeignStackTraceFlags); } else { - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace), NULL); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace), NULL); } // Determine if there are any dynamic methods in the stack trace. If there are, @@ -385,7 +487,7 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, if (iNumDynamics) { PTRARRAYREF dynamicDataArray = (PTRARRAYREF) AllocateObjectArray(iNumDynamics, g_pObjectClass); - SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->dynamicMethods), (OBJECTREF)dynamicDataArray); + SetObjectReference( (OBJECTREF *)&(gc.pStackFrameHelper->dynamicMethods), (OBJECTREF)dynamicDataArray); } int iNumValidFrames = 0; @@ -401,25 +503,25 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, _ASSERTE(pFunc->IsRuntimeMethodHandle()); // Method handle - size_t *pElem = (size_t*)pStackFrameHelper->rgMethodHandle->GetDataPtr(); + size_t *pElem = (size_t*)gc.pStackFrameHelper->rgMethodHandle->GetDataPtr(); pElem[iNumValidFrames] = (size_t)pFunc; // Native offset - CLR_I4 *pI4 = (CLR_I4 *)((I4ARRAYREF)pStackFrameHelper->rgiOffset)->GetDirectPointerToNonObjectElements(); + CLR_I4 *pI4 = (CLR_I4 *)((I4ARRAYREF)gc.pStackFrameHelper->rgiOffset)->GetDirectPointerToNonObjectElements(); pI4[iNumValidFrames] = data.pElements[i].dwOffset; // IL offset - CLR_I4 *pILI4 = (CLR_I4 *)((I4ARRAYREF)pStackFrameHelper->rgiILOffset)->GetDirectPointerToNonObjectElements(); + CLR_I4 *pILI4 = (CLR_I4 *)((I4ARRAYREF)gc.pStackFrameHelper->rgiILOffset)->GetDirectPointerToNonObjectElements(); pILI4[iNumValidFrames] = data.pElements[i].dwILOffset; // Assembly OBJECTREF pAssembly = pFunc->GetAssembly()->GetExposedObject(); - pStackFrameHelper->rgAssembly->SetAt(iNumValidFrames, pAssembly); + gc.pStackFrameHelper->rgAssembly->SetAt(iNumValidFrames, pAssembly); if (data.fDoWeHaveAnyFramesFromForeignStackTrace) { // Set the BOOL indicating if the frame represents the last frame from a foreign exception stack trace. - CLR_U1 *pIsLastFrameFromForeignExceptionStackTraceU1 = (CLR_U1 *)((BOOLARRAYREF)pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace) + CLR_U1 *pIsLastFrameFromForeignExceptionStackTraceU1 = (CLR_U1 *)((BOOLARRAYREF)gc.pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace) ->GetDirectPointerToNonObjectElements(); pIsLastFrameFromForeignExceptionStackTraceU1 [iNumValidFrames] = (CLR_U1)(data.pElements[i].flags & STEF_LAST_FRAME_FROM_FOREIGN_STACK_TRACE); } @@ -436,13 +538,13 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, OBJECTREF pResolver = pDMD->GetLCGMethodResolver()->GetManagedResolver(); _ASSERTE(pResolver != NULL); - ((PTRARRAYREF)pStackFrameHelper->dynamicMethods)->SetAt(iCurDynamic++, pResolver); + ((PTRARRAYREF)gc.pStackFrameHelper->dynamicMethods)->SetAt(iCurDynamic++, pResolver); } else if (pMethod->GetMethodTable()->Collectible()) { OBJECTREF pLoaderAllocator = pMethod->GetMethodTable()->GetLoaderAllocator()->GetExposedObject(); _ASSERTE(pLoaderAllocator != NULL); - ((PTRARRAYREF)pStackFrameHelper->dynamicMethods)->SetAt(iCurDynamic++, pLoaderAllocator); + ((PTRARRAYREF)gc.pStackFrameHelper->dynamicMethods)->SetAt(iCurDynamic++, pLoaderAllocator); } } @@ -467,7 +569,7 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, } #endif // Check if the user wants the filenumber, linenumber info and that it is possible. - if (!fIsEnc && FC_ACCESS_BOOL(fNeedFileInfo)) + if (!fIsEnc && fNeedFileInfo) { #ifdef FEATURE_ISYM_READER BOOL fPortablePDB = FALSE; @@ -658,15 +760,15 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, if (fFileInfoSet) { // Set the line and column numbers - CLR_I4 *pI4Line = (CLR_I4 *)((I4ARRAYREF)pStackFrameHelper->rgiLineNumber)->GetDirectPointerToNonObjectElements(); + CLR_I4 *pI4Line = (CLR_I4 *)((I4ARRAYREF)gc.pStackFrameHelper->rgiLineNumber)->GetDirectPointerToNonObjectElements(); pI4Line[iNumValidFrames] = sourceLine; - CLR_I4 *pI4Column = (CLR_I4 *)((I4ARRAYREF)pStackFrameHelper->rgiColumnNumber)->GetDirectPointerToNonObjectElements(); + CLR_I4 *pI4Column = (CLR_I4 *)((I4ARRAYREF)gc.pStackFrameHelper->rgiColumnNumber)->GetDirectPointerToNonObjectElements(); pI4Column[iNumValidFrames] = sourceColumn; // Set the file name OBJECTREF obj = (OBJECTREF) StringObject::NewString(wszFileName); - pStackFrameHelper->rgFilename->SetAt(iNumValidFrames, obj); + gc.pStackFrameHelper->rgFilename->SetAt(iNumValidFrames, obj); } } @@ -676,7 +778,7 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, #endif // FEATURE_ISYM_READER { // Save MethodToken for the function - CLR_I4 *pMethodToken = (CLR_I4 *)((I4ARRAYREF)pStackFrameHelper->rgiMethodToken)->GetDirectPointerToNonObjectElements(); + CLR_I4 *pMethodToken = (CLR_I4 *)((I4ARRAYREF)gc.pStackFrameHelper->rgiMethodToken)->GetDirectPointerToNonObjectElements(); pMethodToken[iNumValidFrames] = pMethod->GetMemberDef(); PEAssembly *pPEAssembly = pModule->GetPEAssembly(); @@ -686,17 +788,17 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, PTR_CVOID peAddress = pPEAssembly->GetLoadedImageContents(&peSize); // Save the PE address and size - PTR_CVOID *pLoadedPeAddress = (PTR_CVOID *)pStackFrameHelper->rgLoadedPeAddress->GetDataPtr(); + PTR_CVOID *pLoadedPeAddress = (PTR_CVOID *)gc.pStackFrameHelper->rgLoadedPeAddress->GetDataPtr(); pLoadedPeAddress[iNumValidFrames] = peAddress; - CLR_I4 *pLoadedPeSize = (CLR_I4 *)((I4ARRAYREF)pStackFrameHelper->rgiLoadedPeSize)->GetDirectPointerToNonObjectElements(); + CLR_I4 *pLoadedPeSize = (CLR_I4 *)((I4ARRAYREF)gc.pStackFrameHelper->rgiLoadedPeSize)->GetDirectPointerToNonObjectElements(); pLoadedPeSize[iNumValidFrames] = (CLR_I4)peSize; // Set flag indicating PE file in memory has the on disk layout if (!pPEAssembly->IsReflectionEmit()) { // This flag is only available for non-dynamic assemblies. - CLR_U1 *pIsFileLayout = (CLR_U1 *)((BOOLARRAYREF)pStackFrameHelper->rgiIsFileLayout)->GetDirectPointerToNonObjectElements(); + CLR_U1 *pIsFileLayout = (CLR_U1 *)((BOOLARRAYREF)gc.pStackFrameHelper->rgiIsFileLayout)->GetDirectPointerToNonObjectElements(); pIsFileLayout[iNumValidFrames] = (CLR_U1) pPEAssembly->GetLoadedLayout()->IsFlat(); } @@ -707,10 +809,10 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, MemoryRange range = stream->GetRawBuffer(); // Save the in-memory PDB address and size - PTR_VOID *pInMemoryPdbAddress = (PTR_VOID *)pStackFrameHelper->rgInMemoryPdbAddress->GetDataPtr(); + PTR_VOID *pInMemoryPdbAddress = (PTR_VOID *)gc.pStackFrameHelper->rgInMemoryPdbAddress->GetDataPtr(); pInMemoryPdbAddress[iNumValidFrames] = range.StartAddress(); - CLR_I4 *pInMemoryPdbSize = (CLR_I4 *)((I4ARRAYREF)pStackFrameHelper->rgiInMemoryPdbSize)->GetDirectPointerToNonObjectElements(); + CLR_I4 *pInMemoryPdbSize = (CLR_I4 *)((I4ARRAYREF)gc.pStackFrameHelper->rgiInMemoryPdbSize)->GetDirectPointerToNonObjectElements(); pInMemoryPdbSize[iNumValidFrames] = (CLR_I4)range.Size(); } else @@ -720,7 +822,7 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, if (!assemblyPath.IsEmpty()) { OBJECTREF obj = (OBJECTREF)StringObject::NewString(assemblyPath.GetUnicode()); - pStackFrameHelper->rgAssemblyPath->SetAt(iNumValidFrames, obj); + gc.pStackFrameHelper->rgAssemblyPath->SetAt(iNumValidFrames, obj); } } } @@ -729,20 +831,15 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, iNumValidFrames++; } - pStackFrameHelper->iFrameCount = iNumValidFrames; - } - else - { - pStackFrameHelper->iFrameCount = 0; + gc.pStackFrameHelper->iFrameCount = iNumValidFrames; } GCPROTECT_END(); - HELPER_METHOD_FRAME_END(); + END_QCALL; } -FCIMPLEND -extern MethodDesc* QCALLTYPE StackFrame_GetMethodDescFromNativeIP(LPVOID ip) +extern "C" MethodDesc* QCALLTYPE StackFrame_GetMethodDescFromNativeIP(LPVOID ip) { QCALL_CONTRACT; @@ -770,242 +867,39 @@ typedef Wrapper, HolderDestroyStrongHandle // receives a custom notification object from the target and sends it to the RS via // code:Debugger::SendCustomDebuggerNotification // Argument: dataUNSAFE - a pointer the custom notification object being sent -FCIMPL1(void, DebugDebugger::CustomNotification, Object * dataUNSAFE) +extern "C" void QCALLTYPE DebugDebugger_CustomNotification(QCall::ObjectHandleOnStack data) { - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - OBJECTREF pData = ObjectToOBJECTREF(dataUNSAFE); + QCALL_CONTRACT; #ifdef DEBUGGING_SUPPORTED // Send notification only if the debugger is attached - if (CORDebuggerAttached() ) - { - HELPER_METHOD_FRAME_BEGIN_PROTECT(pData); - - Thread * pThread = GetThread(); - AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); - - StrongHandleHolder objHandle = pAppDomain->CreateStrongHandle(pData); - MethodTable * pMT = pData->GetGCSafeMethodTable(); - Module * pModule = pMT->GetModule(); - DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); - mdTypeDef classToken = pMT->GetCl(); - - pThread->SetThreadCurrNotification(objHandle); - g_pDebugInterface->SendCustomDebuggerNotification(pThread, pDomainAssembly, classToken); - pThread->ClearThreadCurrNotification(); - - if (pThread->IsAbortRequested()) - { - pThread->HandleThreadAbort(); - } - - HELPER_METHOD_FRAME_END(); - } - -#endif // DEBUGGING_SUPPORTED - -} -FCIMPLEND - - -void DebugStackTrace::GetStackFramesHelper(Frame *pStartFrame, - void* pStopStack, - GetStackFramesData *pData - ) -{ - CONTRACTL - { - MODE_COOPERATIVE; - GC_TRIGGERS; - THROWS; - } - CONTRACTL_END; - - ASSERT (pData != NULL); - - pData->cElements = 0; - - // if the caller specified (< 20) frames are required, then allocate - // only that many - if ((pData->NumFramesRequested > 0) && (pData->NumFramesRequested < 20)) - { - pData->cElementsAllocated = pData->NumFramesRequested; - } - else - { - pData->cElementsAllocated = 20; - } - - // Allocate memory for the initial 'n' frames - pData->pElements = new DebugStackTraceElement[pData->cElementsAllocated]; - - if (pData->TargetThread == NULL || - pData->TargetThread->GetInternal() == GetThread()) - { - // Null target thread specifies current thread. - GetThread()->StackWalkFrames(GetStackFramesCallback, pData, FUNCTIONSONLY | QUICKUNWIND, pStartFrame); - } - else - { - Thread *pThread = pData->TargetThread->GetInternal(); - _ASSERTE (pThread != NULL); - - // Here's the timeline for the TS_SyncSuspended bit. - // 0) TS_SyncSuspended is not set. - // 1) The suspending thread grabs the thread store lock - // then puts in place trip wires for the suspendee (if it is in managed code) - // and releases the thread store lock. - // 2) The suspending thread waits for the "SafeEvent". - // 3) The suspendee continues execution until it tries to enter preemptive mode. - // If it trips over the wires put in place by the suspending thread, - // it will try to enter preemptive mode. - // 4) The suspendee sets TS_SyncSuspended and the "SafeEvent". - // 5) AT THIS POINT, IT IS SAFE TO WALK THE SUSPENDEE'S STACK. - // 6) The suspendee clears the TS_SyncSuspended flag. - // - // In other words, it is safe to trace the thread's stack IF we're holding the - // thread store lock AND TS_SyncSuspended is set. - // - // This is because: - // - If we were not holding the thread store lock, the thread could be resumed - // underneath us. - // - When TS_SyncSuspended is set, we race against it resuming execution. - - ThreadStoreLockHolder tsl; - - // We erect a barrier so that if the thread tries to disable preemptive GC, - // it could resume execution of managed code during our stack walk. - TSSuspendHolder shTrap; - - Thread::ThreadState state = pThread->GetSnapshotState(); - if (state & (Thread::TS_Unstarted|Thread::TS_Dead|Thread::TS_Detached)) - { - goto LSafeToTrace; - } - - COMPlusThrow(kThreadStateException, IDS_EE_THREAD_BAD_STATE); - - LSafeToTrace: - pThread->StackWalkFrames(GetStackFramesCallback, - pData, - FUNCTIONSONLY|ALLOW_ASYNC_STACK_WALK, - pStartFrame); - } - - // Do a 2nd pass outside of any locks. - // This will compute IL offsets. - for (INT32 i = 0; i < pData->cElements; i++) - { - pData->pElements[i].InitPass2(); - } - -} - - -void DebugStackTrace::GetStackFrames(Frame *pStartFrame, - void* pStopStack, - GetStackFramesData *pData - ) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - GetStackFramesHelper(pStartFrame, pStopStack, pData); -} - - -StackWalkAction DebugStackTrace::GetStackFramesCallback(CrawlFrame* pCf, VOID* data) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - GetStackFramesData* pData = (GetStackFramesData*)data; - - if (pData->skip > 0) - { - pData->skip--; - return SWA_CONTINUE; - } - - // @todo: How do we know what kind of frame we have? - // Can we always assume FramedMethodFrame? - // NOT AT ALL!!!, but we can assume it's a function - // because we asked the stackwalker for it! - MethodDesc* pFunc = pCf->GetFunction(); - - if (pData->cElements >= pData->cElementsAllocated) - { - - DebugStackTraceElement* pTemp = new (nothrow) DebugStackTraceElement[2*pData->cElementsAllocated]; - - if (!pTemp) - { - return SWA_ABORT; - } - - memcpy(pTemp, pData->pElements, pData->cElementsAllocated * sizeof(DebugStackTraceElement)); - - delete [] pData->pElements; - - pData->pElements = pTemp; - pData->cElementsAllocated *= 2; - } - - PCODE ip; - DWORD dwNativeOffset; - - if (pCf->IsFrameless()) - { - // Real method with jitted code. - dwNativeOffset = pCf->GetRelOffset(); - ip = GetControlPC(pCf->GetRegisterSet()); - } - else - { - ip = (PCODE)NULL; - dwNativeOffset = 0; - } + if (!CORDebuggerAttached()) + return; - // Pass on to InitPass2 that the IP has already been adjusted (decremented by 1) - INT flags = pCf->IsIPadjusted() ? STEF_IP_ADJUSTED : 0; + BEGIN_QCALL; - pData->pElements[pData->cElements].InitPass1( - dwNativeOffset, - pFunc, - ip, - flags); + GCX_COOP(); - // We'll init the IL offsets outside the TSL lock. + Thread * pThread = GetThread(); + AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); - ++pData->cElements; + StrongHandleHolder objHandle = pAppDomain->CreateStrongHandle(data.Get()); + MethodTable* pMT = data.Get()->GetGCSafeMethodTable(); + Module* pModule = pMT->GetModule(); + DomainAssembly* pDomainAssembly = pModule->GetDomainAssembly(); + mdTypeDef classToken = pMT->GetCl(); - // Since we may be asynchronously walking another thread's stack, - // check (frequently) for stack-buffer-overrun corruptions after - // any long operation - pCf->CheckGSCookies(); + pThread->SetThreadCurrNotification(objHandle); + g_pDebugInterface->SendCustomDebuggerNotification(pThread, pDomainAssembly, classToken); + pThread->ClearThreadCurrNotification(); - // check if we already have the number of frames that the user had asked for - if ((pData->NumFramesRequested != 0) && (pData->NumFramesRequested <= pData->cElements)) + if (pThread->IsAbortRequested()) { - return SWA_ABORT; + pThread->HandleThreadAbort(); } - return SWA_CONTINUE; + END_QCALL; +#endif // DEBUGGING_SUPPORTED } #endif // !DACCESS_COMPILE @@ -1057,7 +951,7 @@ void DebugStackTrace::GetStackFramesFromException(OBJECTREF * e, if (pData->cElements != 0) { // Allocate the memory to contain the data - pData->pElements = new DebugStackTraceElement[pData->cElements]; + pData->pElements = new Element[pData->cElements]; // Fill in the data for (unsigned i = 0; i < (unsigned)pData->cElements; i++) @@ -1123,7 +1017,7 @@ void DebugStackTrace::GetStackFramesFromException(OBJECTREF * e, // Init a stack-trace element. // Initialization done potentially under the TSL. -void DebugStackTrace::DebugStackTraceElement::InitPass1( +void DebugStackTrace::Element::InitPass1( DWORD dwNativeOffset, MethodDesc *pFunc, PCODE ip, @@ -1146,7 +1040,7 @@ void DebugStackTrace::DebugStackTraceElement::InitPass1( // Initialization done outside the TSL. // This may need to call locking operations that aren't safe under the TSL. -void DebugStackTrace::DebugStackTraceElement::InitPass2() +void DebugStackTrace::Element::InitPass2() { CONTRACTL { diff --git a/src/coreclr/vm/debugdebugger.h b/src/coreclr/vm/debugdebugger.h index fa630cbb46e28..bbf06268752c5 100644 --- a/src/coreclr/vm/debugdebugger.h +++ b/src/coreclr/vm/debugdebugger.h @@ -19,19 +19,15 @@ class DebugDebugger { public: - static FCDECL0(void, Break); static FCDECL0(FC_BOOL_RET, IsDebuggerAttached); - // receives a custom notification object from the target and sends it to the RS via - // code:Debugger::SendCustomDebuggerNotification - static FCDECL1(void, CustomNotification, Object * dataUNSAFE); - static FCDECL0(FC_BOOL_RET, IsLogging); }; +extern "C" void QCALLTYPE DebugDebugger_Break(); extern "C" BOOL QCALLTYPE DebugDebugger_Launch(); extern "C" void QCALLTYPE DebugDebugger_Log(INT32 Level, PCWSTR pwzModule, PCWSTR pwzMessage); - +extern "C" void QCALLTYPE DebugDebugger_CustomNotification(QCall::ObjectHandleOnStack data); class StackFrameHelper : public Object { @@ -39,7 +35,6 @@ class StackFrameHelper : public Object // Modifying the order or fields of this object may require other changes to the // classlib definition of the StackFrameHelper class. public: - THREADBASEREF targetThread; I4ARRAYREF rgiOffset; I4ARRAYREF rgiILOffset; PTRARRAYREF dynamicMethods; @@ -88,12 +83,7 @@ typedef StackFrameHelper* STACKFRAMEHELPERREF; class DebugStackTrace { public: - -#ifndef DACCESS_COMPILE -// the DAC directly uses the GetStackFramesData and DebugStackTraceElement types -private: -#endif // DACCESS_COMPILE - struct DebugStackTraceElement { + struct Element { DWORD dwOffset; // native offset DWORD dwILOffset; MethodDesc *pFunc; @@ -117,29 +107,25 @@ class DebugStackTrace public: - struct GetStackFramesData { - - // Used for the integer-skip version - INT32 skip; + struct GetStackFramesData + { INT32 NumFramesRequested; INT32 cElementsAllocated; INT32 cElements; - DebugStackTraceElement* pElements; + Element* pElements; THREADBASEREF TargetThread; AppDomain *pDomain; BOOL fDoWeHaveAnyFramesFromForeignStackTrace; - - GetStackFramesData() : skip(0), - NumFramesRequested (0), - cElementsAllocated(0), - cElements(0), - pElements(NULL), - TargetThread((THREADBASEREF)(TADDR)NULL) + GetStackFramesData() + : NumFramesRequested (0) + , cElementsAllocated(0) + , cElements(0) + , pElements(NULL) + , TargetThread((THREADBASEREF)(TADDR)NULL) + , fDoWeHaveAnyFramesFromForeignStackTrace(FALSE) { LIMITED_METHOD_CONTRACT; - fDoWeHaveAnyFramesFromForeignStackTrace = FALSE; - } ~GetStackFramesData() @@ -148,29 +134,14 @@ class DebugStackTrace } }; - static FCDECL4(void, - GetStackFramesInternal, - StackFrameHelper* pStackFrameHelper, - INT32 iSkip, - FC_BOOL_ARG fNeedFileInfo, - Object* pException - ); - static void GetStackFramesFromException(OBJECTREF * e, GetStackFramesData *pData, PTRARRAYREF * pDynamicMethodArray = NULL); - -#ifndef DACCESS_COMPILE -// the DAC directly calls GetStackFramesFromException -private: -#endif - - static void GetStackFramesHelper(Frame *pStartFrame, void* pStopStack, GetStackFramesData *pData); - - static void GetStackFrames(Frame *pStartFrame, void* pStopStack, GetStackFramesData *pData); - - static StackWalkAction GetStackFramesCallback(CrawlFrame* pCf, VOID* data); - }; +extern "C" void QCALLTYPE StackTrace_GetStackFramesInternal( + QCall::ObjectHandleOnStack stackFrameHelper, + BOOL fNeedFileInfo, + QCall::ObjectHandleOnStack exception); + extern "C" MethodDesc* QCALLTYPE StackFrame_GetMethodDescFromNativeIP(LPVOID ip); #endif // __DEBUG_DEBUGGER_h__ diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 7dc5e664dfd42..ab4ee21b7e61a 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -68,14 +68,8 @@ FCFuncStart(gStringFuncs) FCFuncEnd() FCFuncStart(gDiagnosticsDebugger) - FCFuncElement("BreakInternal", DebugDebugger::Break) FCFuncElement("get_IsAttached", DebugDebugger::IsDebuggerAttached) FCFuncElement("IsLogging", DebugDebugger::IsLogging) - FCFuncElement("CustomNotification", DebugDebugger::CustomNotification) -FCFuncEnd() - -FCFuncStart(gDiagnosticsStackTrace) - FCFuncElement("GetStackFramesInternal", DebugStackTrace::GetStackFramesInternal) FCFuncEnd() FCFuncStart(gEnvironmentFuncs) @@ -508,7 +502,6 @@ FCClassElement("RuntimeType", "System", gSystem_RuntimeType) FCClassElement("RuntimeTypeHandle", "System", gCOMTypeHandleFuncs) FCClassElement("Signature", "System", gSignatureNative) -FCClassElement("StackTrace", "System.Diagnostics", gDiagnosticsStackTrace) FCClassElement("Stream", "System.IO", gStreamFuncs) FCClassElement("String", "System", gStringFuncs) FCClassElement("StubHelpers", "System.StubHelpers", gStubHelperFuncs) diff --git a/src/coreclr/vm/eventreporter.cpp b/src/coreclr/vm/eventreporter.cpp index 9a4d01b8af971..8ffab60bbd94c 100644 --- a/src/coreclr/vm/eventreporter.cpp +++ b/src/coreclr/vm/eventreporter.cpp @@ -632,7 +632,6 @@ void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallS DebugStackTrace::GetStackFramesData stackFramesData; stackFramesData.pDomain = NULL; - stackFramesData.skip = 0; stackFramesData.NumFramesRequested = 0; DebugStackTrace::GetStackFramesFromException(&(gc.exObj), &stackFramesData); diff --git a/src/coreclr/vm/i386/jitinterfacex86.cpp b/src/coreclr/vm/i386/jitinterfacex86.cpp index 0b6607aff6d2a..f643365aae56f 100644 --- a/src/coreclr/vm/i386/jitinterfacex86.cpp +++ b/src/coreclr/vm/i386/jitinterfacex86.cpp @@ -96,25 +96,6 @@ extern "C" void STDCALL WriteBarrierAssert(BYTE* ptr, Object* obj) #endif // _DEBUG -FCDECL1(Object*, JIT_New, CORINFO_CLASS_HANDLE typeHnd_); - - -HCIMPL1(Object*, AllocObjectWrapper, MethodTable *pMT) -{ - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - OBJECTREF newObj = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_0(); // Set up a frame - newObj = AllocateObject(pMT); - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(newObj); -} -HCIMPLEND - /*********************************************************************/ #ifndef UNIX_X86_ABI extern "C" void* g_TailCallFrameVptr; @@ -361,6 +342,8 @@ void JIT_TrialAlloc::EmitNoAllocCode(CPUSTUBLINKER *psl, Flags flags) } } +FCDECL1(Object*, JIT_New, CORINFO_CLASS_HANDLE typeHnd_); + void *JIT_TrialAlloc::GenAllocSFast(Flags flags) { STANDARD_VM_CONTRACT; diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 215e2d34ef69a..c5f30adccfce9 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -83,8 +83,10 @@ static const Entry s_QCall[] = DllImportEntry(CustomAttribute_CreateCustomAttributeInstance) DllImportEntry(CustomAttribute_CreatePropertyOrFieldData) DllImportEntry(Enum_GetValuesAndNames) + DllImportEntry(DebugDebugger_Break) DllImportEntry(DebugDebugger_Launch) DllImportEntry(DebugDebugger_Log) + DllImportEntry(DebugDebugger_CustomNotification) DllImportEntry(Delegate_BindToMethodName) DllImportEntry(Delegate_BindToMethodInfo) DllImportEntry(Delegate_InitializeVirtualCallStub) @@ -138,6 +140,7 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeModule_GetFullyQualifiedName) DllImportEntry(RuntimeModule_GetTypes) DllImportEntry(RuntimeFieldHandle_GetRVAFieldInfo) + DllImportEntry(StackTrace_GetStackFramesInternal) DllImportEntry(StackFrame_GetMethodDescFromNativeIP) DllImportEntry(ModuleBuilder_GetStringConstant) DllImportEntry(ModuleBuilder_GetTypeRef) diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index 4a4bd2ff867fa..6aa3e04b00465 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -4267,12 +4267,6 @@ struct cdac_data static constexpr size_t DeadCount = offsetof(ThreadStore, m_DeadThreadCount); }; -struct TSSuspendHelper { - static void SetTrap() { ThreadStore::IncrementTrapReturningThreads(); } - static void UnsetTrap() { ThreadStore::DecrementTrapReturningThreads(); } -}; -typedef StateHolder TSSuspendHolder; - typedef StateHolder ThreadStoreLockHolder;