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 948ebd2537230d..3cfc7cc193ec1f 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,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Text;
+using System.Reflection;
+using System.Runtime.CompilerServices;
namespace System.Diagnostics
{
@@ -50,5 +52,22 @@ private void BuildStackFrame(int skipFrames, bool needFileInfo)
}
private static bool AppendStackFrameWithoutMethodBase(StringBuilder sb) => false;
+
+ ///
+ /// 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 = StackTrace.GetMethodDescFromNativeIP(ip);
+
+ if (method.Value == IntPtr.Zero)
+ return null;
+
+ return RuntimeType.GetMethodBase(null, method);
+ }
}
}
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 9bef9fb72fae58..d82bbaf7e1e342 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
@@ -1,8 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Runtime.CompilerServices;
using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
namespace System.Diagnostics
{
@@ -11,6 +12,9 @@ public partial class StackTrace
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception? e);
+ [DllImport(RuntimeHelpers.QCall)]
+ internal static extern RuntimeMethodHandleInternal GetMethodDescFromNativeIP(IntPtr ip);
+
internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrames)
{
int iRetVal = 0;
diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp
index e21939990405c2..f08e5107b13812 100644
--- a/src/coreclr/vm/debugdebugger.cpp
+++ b/src/coreclr/vm/debugdebugger.cpp
@@ -776,6 +776,28 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal,
}
FCIMPLEND
+MethodDesc* QCALLTYPE DebugStackTrace::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 cba432e3d8e5f2..2673f90717a695 100644
--- a/src/coreclr/vm/debugdebugger.h
+++ b/src/coreclr/vm/debugdebugger.h
@@ -158,6 +158,8 @@ class DebugStackTrace
Object* pException
);
+ static MethodDesc* QCALLTYPE GetMethodDescFromNativeIP(LPVOID ip);
+
static void GetStackFramesFromException(OBJECTREF * e, GetStackFramesData *pData, PTRARRAYREF * pDynamicMethodArray = NULL);
#ifndef DACCESS_COMPILE
diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h
index c83248c00e2d0d..363ae6f6cfa7cc 100644
--- a/src/coreclr/vm/ecalllist.h
+++ b/src/coreclr/vm/ecalllist.h
@@ -128,6 +128,7 @@ FCFuncEnd()
FCFuncStart(gDiagnosticsStackTrace)
FCFuncElement("GetStackFramesInternal", DebugStackTrace::GetStackFramesInternal)
+ QCFuncElement("GetMethodDescFromNativeIP", DebugStackTrace::GetMethodDescFromNativeIP)
FCFuncEnd()
FCFuncStart(gEnvironmentFuncs)
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 53a41aff8c935a..ee28b6e38cfe61 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 @@
+
+
+
+