Skip to content

Commit e1b589c

Browse files
author
Mike McLaughlin
authored
[release/6.0.x] Add System.Diagnostics.StackFrame.GetMethodInfoFromNativeIP API for VS4Mac (#61298)
* Add System.Diagnostics.StackFrame.GetMethodInfoFromNativeIP API for VS4Mac VS4Mac needs a way to symbolize managed IPs when rethrowing a native NSException from Objective C++. This is a short term API needed for the next 6.0 service release discoverable only through reflection. Issue: #61186 * Code review feedback * Remove unneccesary blank line
1 parent 08e0023 commit e1b589c

File tree

6 files changed

+53
-1
lines changed

6 files changed

+53
-1
lines changed

src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Text;
5+
using System.Reflection;
6+
using System.Runtime.CompilerServices;
57

68
namespace System.Diagnostics
79
{
@@ -50,5 +52,22 @@ private void BuildStackFrame(int skipFrames, bool needFileInfo)
5052
}
5153

5254
private static bool AppendStackFrameWithoutMethodBase(StringBuilder sb) => false;
55+
56+
/// <summary>
57+
/// Returns the MethodBase instance for the managed code IP address.
58+
///
59+
/// Warning: The implementation of this method has race for dynamic and collectible methods.
60+
/// </summary>
61+
/// <param name="ip">code address</param>
62+
/// <returns>MethodBase instance for the method or null if IP not found</returns>
63+
internal static MethodBase? GetMethodFromNativeIP(IntPtr ip)
64+
{
65+
RuntimeMethodHandleInternal method = StackTrace.GetMethodDescFromNativeIP(ip);
66+
67+
if (method.Value == IntPtr.Zero)
68+
return null;
69+
70+
return RuntimeType.GetMethodBase(null, method);
71+
}
5372
}
5473
}

src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Runtime.CompilerServices;
54
using System.Reflection;
5+
using System.Runtime.CompilerServices;
6+
using System.Runtime.InteropServices;
67

78
namespace System.Diagnostics
89
{
@@ -11,6 +12,9 @@ public partial class StackTrace
1112
[MethodImpl(MethodImplOptions.InternalCall)]
1213
internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception? e);
1314

15+
[DllImport(RuntimeHelpers.QCall)]
16+
internal static extern RuntimeMethodHandleInternal GetMethodDescFromNativeIP(IntPtr ip);
17+
1418
internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrames)
1519
{
1620
int iRetVal = 0;

src/coreclr/vm/debugdebugger.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,28 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal,
776776
}
777777
FCIMPLEND
778778

779+
MethodDesc* QCALLTYPE DebugStackTrace::GetMethodDescFromNativeIP(LPVOID ip)
780+
{
781+
QCALL_CONTRACT;
782+
783+
MethodDesc* pResult = nullptr;
784+
785+
BEGIN_QCALL;
786+
787+
// TODO: There is a race for dynamic and collectible methods here between getting
788+
// the MethodDesc here and when the managed wrapper converts it into a MethodBase
789+
// where the method could be collected.
790+
EECodeInfo codeInfo((PCODE)ip);
791+
if (codeInfo.IsValid())
792+
{
793+
pResult = codeInfo.GetMethodDesc();
794+
}
795+
796+
END_QCALL;
797+
798+
return pResult;
799+
}
800+
779801
FORCEINLINE void HolderDestroyStrongHandle(OBJECTHANDLE h) { if (h != NULL) DestroyStrongHandle(h); }
780802
typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, HolderDestroyStrongHandle, NULL> StrongHandleHolder;
781803

src/coreclr/vm/debugdebugger.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ class DebugStackTrace
158158
Object* pException
159159
);
160160

161+
static MethodDesc* QCALLTYPE GetMethodDescFromNativeIP(LPVOID ip);
162+
161163
static void GetStackFramesFromException(OBJECTREF * e, GetStackFramesData *pData, PTRARRAYREF * pDynamicMethodArray = NULL);
162164

163165
#ifndef DACCESS_COMPILE

src/coreclr/vm/ecalllist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ FCFuncEnd()
128128

129129
FCFuncStart(gDiagnosticsStackTrace)
130130
FCFuncElement("GetStackFramesInternal", DebugStackTrace::GetStackFramesInternal)
131+
QCFuncElement("GetMethodDescFromNativeIP", DebugStackTrace::GetMethodDescFromNativeIP)
131132
FCFuncEnd()
132133

133134
FCFuncStart(gEnvironmentFuncs)

src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,9 @@
44
<!-- Internal API used by tests only. -->
55
<method name="GetICUVersion" />
66
</type>
7+
<type fullname="System.Diagnostics.StackFrame">
8+
<!-- Used by VS4Mac via reflection to symbolize stack traces -->
9+
<method name="GetMethodFromNativeIP" />
10+
</type>
711
</assembly>
812
</linker>

0 commit comments

Comments
 (0)