Add System.Diagnostics.StackFrame.GetMethodFromNativeIP API for VS4Mac (#61289)
authorMike McLaughlin <mikem@microsoft.com>
Tue, 9 Nov 2021 16:31:46 +0000 (08:31 -0800)
committerGitHub <noreply@github.com>
Tue, 9 Nov 2021 16:31:46 +0000 (08:31 -0800)
* Add System.Diagnostics.StackFrame.GetMethodInfoFromNativeIP API for VS4Mac

Issue: https://github.com/dotnet/runtime/issues/61186

src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs
src/coreclr/vm/debugdebugger.cpp
src/coreclr/vm/debugdebugger.h
src/coreclr/vm/qcallentrypoints.cpp
src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml

index 948ebd2..7863cb0 100644 (file)
@@ -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);
+
+        /// <summary>
+        /// Returns the MethodBase instance for the managed code IP address.
+        ///
+        /// Warning: The implementation of this method has race for dynamic and collectible methods.
+        /// </summary>
+        /// <param name="ip">code address</param>
+        /// <returns>MethodBase instance for the method or null if IP not found</returns>
+        internal static MethodBase? GetMethodFromNativeIP(IntPtr ip)
+        {
+            RuntimeMethodHandleInternal method = GetMethodDescFromNativeIP(ip);
+
+            if (method.Value == IntPtr.Zero)
+                return null;
+
+            return RuntimeType.GetMethodBase(null, method);
+        }
     }
 }
index fa55f3e..2ade537 100644 (file)
@@ -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<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, HolderDestroyStrongHandle, NULL> StrongHandleHolder;
 
index 3c9fd17..b559531 100644 (file)
@@ -171,4 +171,6 @@ private:
 
 };
 
+extern "C" MethodDesc* QCALLTYPE StackFrame_GetMethodDescFromNativeIP(LPVOID ip);
+
 #endif  // __DEBUG_DEBUGGER_h__
index 22327cd..472a2c1 100644 (file)
@@ -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)
index 53a41af..ee28b6e 100644 (file)
@@ -4,5 +4,9 @@
       <!-- Internal API used by tests only. -->
       <method name="GetICUVersion" />
     </type>
+    <type fullname="System.Diagnostics.StackFrame">
+      <!-- Used by VS4Mac via reflection to symbolize stack traces -->
+      <method name="GetMethodFromNativeIP" />
+    </type>
   </assembly>
 </linker>