From 985cb8329d76f3b8334999581bebde62c54270e0 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Tue, 9 Nov 2021 08:31:46 -0800 Subject: [PATCH] Add System.Diagnostics.StackFrame.GetMethodFromNativeIP API for VS4Mac (#61289) * Add System.Diagnostics.StackFrame.GetMethodInfoFromNativeIP API for VS4Mac Issue: https://github.com/dotnet/runtime/issues/61186 --- .../src/System/Diagnostics/StackFrame.CoreCLR.cs | 23 ++++++++++++++++++++++ src/coreclr/vm/debugdebugger.cpp | 23 +++++++++++++++++++++- src/coreclr/vm/debugdebugger.h | 2 ++ src/coreclr/vm/qcallentrypoints.cpp | 1 + .../src/ILLink/ILLink.Descriptors.LibraryBuild.xml | 4 ++++ 5 files changed, 52 insertions(+), 1 deletion(-) 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 948ebd2..7863cb0 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 @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Diagnostics { @@ -50,5 +53,25 @@ namespace System.Diagnostics } private static bool AppendStackFrameWithoutMethodBase(StringBuilder sb) => false; + + [DllImport(RuntimeHelpers.QCall, EntryPoint = "StackFrame_GetMethodDescFromNativeIP")] + private static extern RuntimeMethodHandleInternal GetMethodDescFromNativeIP(IntPtr ip); + + /// + /// Returns the MethodBase instance for the managed code IP address. + /// + /// Warning: The implementation of this method has race for dynamic and collectible methods. + /// + /// code address + /// MethodBase instance for the method or null if IP not found + internal static MethodBase? GetMethodFromNativeIP(IntPtr ip) + { + RuntimeMethodHandleInternal method = GetMethodDescFromNativeIP(ip); + + if (method.Value == IntPtr.Zero) + return null; + + return RuntimeType.GetMethodBase(null, method); + } } } diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index fa55f3e..2ade537 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -297,7 +297,6 @@ FCIMPL0(FC_BOOL_RET, DebugDebugger::IsLogging) } FCIMPLEND - FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, StackFrameHelper* pStackFrameHelperUNSAFE, INT32 iSkip, @@ -778,6 +777,28 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, } FCIMPLEND +extern MethodDesc* QCALLTYPE StackFrame_GetMethodDescFromNativeIP(LPVOID ip) +{ + QCALL_CONTRACT; + + MethodDesc* pResult = nullptr; + + BEGIN_QCALL; + + // TODO: There is a race for dynamic and collectible methods here between getting + // the MethodDesc here and when the managed wrapper converts it into a MethodBase + // where the method could be collected. + EECodeInfo codeInfo((PCODE)ip); + if (codeInfo.IsValid()) + { + pResult = codeInfo.GetMethodDesc(); + } + + END_QCALL; + + return pResult; +} + FORCEINLINE void HolderDestroyStrongHandle(OBJECTHANDLE h) { if (h != NULL) DestroyStrongHandle(h); } typedef Wrapper, HolderDestroyStrongHandle, NULL> StrongHandleHolder; diff --git a/src/coreclr/vm/debugdebugger.h b/src/coreclr/vm/debugdebugger.h index 3c9fd17..b559531 100644 --- a/src/coreclr/vm/debugdebugger.h +++ b/src/coreclr/vm/debugdebugger.h @@ -171,4 +171,6 @@ private: }; +extern "C" MethodDesc* QCALLTYPE StackFrame_GetMethodDescFromNativeIP(LPVOID ip); + #endif // __DEBUG_DEBUGGER_h__ diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 22327cd..472a2c1 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -115,6 +115,7 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeModule_GetType) DllImportEntry(RuntimeModule_GetScopeName) DllImportEntry(RuntimeModule_GetFullyQualifiedName) + DllImportEntry(StackFrame_GetMethodDescFromNativeIP) DllImportEntry(ModuleBuilder_GetStringConstant) DllImportEntry(ModuleBuilder_GetTypeRef) DllImportEntry(ModuleBuilder_GetTokenFromTypeSpec) diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml index 53a41af..ee28b6e 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -4,5 +4,9 @@ + + + + -- 2.7.4