Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/6.0.x] Add System.Diagnostics.StackFrame.GetMethodInfoFromNativeIP API for VS4Mac #61298

Merged
merged 3 commits into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<type fullname="Internal.Runtime.InteropServices.InMemoryAssemblyLoader">
<method name="LoadInMemoryAssembly" />
</type>

eerhardt marked this conversation as resolved.
Show resolved Hide resolved
</assembly>

<!-- The private Event methods are accessed by private reflection in the base EventSource class. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -50,5 +52,22 @@ private void BuildStackFrame(int skipFrames, bool needFileInfo)
}

private static bool AppendStackFrameWithoutMethodBase(StringBuilder sb) => false;

/// <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 = StackTrace.GetMethodDescFromNativeIP(ip);

if (method.Value == IntPtr.Zero)
return null;

return RuntimeType.GetMethodBase(null, method);
}
}
}
Original file line number Diff line number Diff line change
@@ -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
{
Expand All @@ -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;
Expand Down
22 changes: 22 additions & 0 deletions src/coreclr/vm/debugdebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, HolderDestroyStrongHandle, NULL> StrongHandleHolder;

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/debugdebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ FCFuncEnd()

FCFuncStart(gDiagnosticsStackTrace)
FCFuncElement("GetStackFramesInternal", DebugStackTrace::GetStackFramesInternal)
QCFuncElement("GetMethodDescFromNativeIP", DebugStackTrace::GetMethodDescFromNativeIP)
FCFuncEnd()

FCFuncStart(gEnvironmentFuncs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>