Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -699,19 +699,6 @@ internal static StackTraceMetadataCallbacks StackTraceCallbacksIfAvailable
}
}

public static string TryGetMethodDisplayStringFromIp(IntPtr ip)
{
StackTraceMetadataCallbacks callbacks = StackTraceCallbacksIfAvailable;
if (callbacks == null)
return null;

ip = RuntimeImports.RhFindMethodStartAddress(ip);
if (ip == IntPtr.Zero)
return null;

return callbacks.TryGetMethodNameFromStartAddress(ip, out _);
}

private static TypeLoaderCallbacks s_typeLoaderCallbacks;

public static object CreateThunksHeap(IntPtr commonStubAddress)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,7 @@ namespace Internal.Runtime.Augments
[CLSCompliant(false)]
public abstract class StackTraceMetadataCallbacks
{
/// <summary>
/// Helper function to format a given method address using the stack trace metadata.
/// Return null if stack trace information is not available.
/// </summary>
/// <param name="methodStartAddress">Memory address representing the start of a method</param>
/// <param name="isStackTraceHidden">Returns a value indicating whether the method should be hidden in stack traces</param>
/// <returns>Formatted method name or null if metadata for the method is not available</returns>
public abstract string TryGetMethodNameFromStartAddress(IntPtr methodStartAddress, out bool isStackTraceHidden);
public abstract string TryGetMethodStackFrameInfo(IntPtr methodStartAddress, int offset, bool needsFileInfo, out string owningType, out string genericArgs, out string methodSignature, out bool isStackTraceHidden, out string fileName, out int lineNumber);

public abstract DiagnosticMethodInfo TryGetDiagnosticMethodInfoFromStartAddress(IntPtr methodStartAddress);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@
<Compile Include="Internal\Runtime\CompilerServices\MethodNameAndSignature.cs" />
<Compile Include="Internal\Runtime\CompilerServices\OpenMethodResolver.cs" />
<Compile Include="Internal\Runtime\TypeLoaderExceptionHelper.cs" />
<Compile Include="Internal\DeveloperExperience\DeveloperExperience.cs" />
<Compile Include="Internal\Runtime\Augments\RuntimeAugments.cs" />
<Compile Include="Internal\Runtime\Augments\TypeLoaderCallbacks.cs" />
<Compile Include="Internal\Runtime\Augments\StackTraceMetadataCallbacks.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
using System.Runtime.CompilerServices;
using System.Text;

using Internal.DeveloperExperience;

namespace System
{
internal unsafe struct CrashInfo
Expand Down Expand Up @@ -257,7 +255,7 @@ private bool WriteStackFrame(StackFrame frame, int maxNameSize)
if (!WriteHexValue("offset"u8, frame.GetNativeOffset()))
return false;

string method = DeveloperExperience.GetMethodName(ip, out _, out _);
string method = frame.GetCrashInfoString();
if (method != null)
{
if (!WriteStringValue("name"u8, method, maxNameSize))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
using System.Runtime.CompilerServices;
using System.Security;

using Internal.DeveloperExperience;

namespace System.Diagnostics
{
// .NET Native-specific Debug implementation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Text;

using Internal.DeveloperExperience;
using Internal.Reflection.Augments;
using Internal.Runtime.Augments;

namespace System.Diagnostics
{
Expand Down Expand Up @@ -36,6 +38,18 @@ public partial class StackFrame
/// </summary>
private bool _noMethodBaseAvailable;

private bool _isStackTraceHidden;

// If stack trace metadata is available, _methodOwningType is the namespace-qualified name of the owning type,
// _methodName is the name of the method, _methodGenericArgs are generic arguments, and _methodSignature is the list of parameters
// without braces. StackTrace will format this as `{_methodOwningType}.{_methodName}<{_genericArgs}>({_methodSignature}).
// We keep this separate because StackFrame.ToString is defined as returning _methodName[{_genericArgs}].
// If stack trace metadata is unavailable, only _methodName is populated and contains the "{fileNameWithoutExtension}!<BaseAddress>+0x{rva:x}"
private string _methodOwningType;
private string _methodName;
private string _methodGenericArgs;
private string _methodSignature;

/// <summary>
/// Returns the method the frame is executing
/// </summary>
Expand Down Expand Up @@ -103,16 +117,30 @@ private void InitializeForIpAddress(IntPtr ipAddress, bool needFileInfo)
IntPtr methodStartAddress = RuntimeImports.RhFindMethodStartAddress(ipAddress);

_nativeOffset = (int)((nint)_ipAddress - (nint)methodStartAddress);
_ilOffset = StackFrame.OFFSET_UNKNOWN;

DeveloperExperience.Default.TryGetILOffsetWithinMethod(_ipAddress, out _ilOffset);
StackTraceMetadataCallbacks stackTraceCallbacks = RuntimeAugments.StackTraceCallbacksIfAvailable;
if (stackTraceCallbacks != null)
{
_methodName = stackTraceCallbacks.TryGetMethodStackFrameInfo(methodStartAddress, _nativeOffset, needFileInfo, out _methodOwningType, out _methodGenericArgs, out _methodSignature, out _isStackTraceHidden, out _fileName, out _lineNumber);
}

if (needFileInfo)
if (_methodName == null)
{
DeveloperExperience.Default.TryGetSourceLineInfo(
_ipAddress,
out _fileName,
out _lineNumber,
out _columnNumber);
// If we don't have precise information, try to map it at least back to the right module.
string moduleFullFileName = RuntimeAugments.TryGetFullPathToApplicationModule(_ipAddress, out IntPtr moduleBase);

// Without any callbacks or the ability to map ip correctly we better admit that we don't know
if (string.IsNullOrEmpty(moduleFullFileName))
{
_methodName = "<unknown>";
}
else
{
ReadOnlySpan<char> fileNameWithoutExtension = Path.GetFileNameWithoutExtension(moduleFullFileName.AsSpan());
int rva = (int)(_ipAddress - moduleBase);
_methodName = $"{fileNameWithoutExtension}!<BaseAddress>+0x{rva:x}";
}
}
}
}
Expand Down Expand Up @@ -156,7 +184,13 @@ internal bool HasMethod()
/// </summary>
private bool AppendStackFrameWithoutMethodBase(StringBuilder builder)
{
builder.Append(DeveloperExperience.Default.CreateStackTraceString(_ipAddress, includeFileInfo: false, out _));
builder.Append(_methodName);
if (_methodGenericArgs != null)
{
builder.Append('<');
builder.Append(_methodGenericArgs);
builder.Append('>');
}
return true;
}

Expand All @@ -175,14 +209,25 @@ internal void AppendToStackTrace(StringBuilder builder)
{
if (_ipAddress != Exception.EdiSeparator)
{
string s = DeveloperExperience.Default.CreateStackTraceString(_ipAddress, _needFileInfo, out bool isStackTraceHidden);
if (!isStackTraceHidden)
if (!_isStackTraceHidden)
{
// Passing a default string for "at" in case SR.UsingResourceKeys() is true
// as this is a special case and we don't want to have "Word_At" on stack traces.
string word_At = SR.UsingResourceKeys() ? "at" : SR.Word_At;
// We also want to pass in a default for inFileLineNumber.
string inFileLineNum = SR.UsingResourceKeys() ? "in {0}:line {1}" : SR.StackTrace_InFileLineNumber;
builder.Append(" ").Append(word_At).Append(' ');
builder.AppendLine(s);

AppendCommonStringRepresenation(builder, allowFallback: true);

if (_fileName != null)
{
// tack on " in c:\tmp\MyFile.cs:line 5"
builder.Append(' ');
builder.AppendFormat(CultureInfo.InvariantCulture, inFileLineNum, _fileName, _lineNumber);
}

builder.AppendLine();
}
}
if (_isLastFrameFromForeignExceptionStackTrace)
Expand All @@ -193,5 +238,36 @@ internal void AppendToStackTrace(StringBuilder builder)
SR.Exception_EndStackTraceFromPreviousThrow);
}
}

private void AppendCommonStringRepresenation(StringBuilder builder, bool allowFallback)
{
if (_methodOwningType != null)
{
builder.Append(_methodOwningType);
builder.Append('.');
builder.Append(_methodName);
if (_methodGenericArgs != null)
{
builder.Append('[');
builder.Append(_methodGenericArgs);
builder.Append(']');
}
builder.Append('(');
builder.Append(_methodSignature);
builder.Append(')');
}
else if (allowFallback)
{
Debug.Assert(_methodSignature == null);
builder.Append(_methodName);
}
}

internal string GetCrashInfoString()
{
StringBuilder sb = new StringBuilder();
AppendCommonStringRepresenation(sb, allowFallback: false);
return sb.Length > 0 ? sb.ToString() : null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
using System.Runtime.CompilerServices;
using System.Threading;

using Internal.DeveloperExperience;

namespace System
{
public static partial class Environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,7 @@ public static MethodInfo GetDelegateMethodInfo(Delegate del)
{
if (!ReflectionExecution.ExecutionEnvironment.TryGetMethodForOriginalLdFtnResult(originalLdFtnResult, ref typeOfFirstParameterIfInstanceDelegate, out methodHandle, out genericMethodTypeArgumentHandles))
{
ReflectionExecution.ExecutionEnvironment.GetFunctionPointerAndInstantiationArgumentForOriginalLdFtnResult(originalLdFtnResult, out IntPtr ip, out IntPtr _);

string methodDisplayString = RuntimeAugments.TryGetMethodDisplayStringFromIp(ip);
if (methodDisplayString == null)
throw new NotSupportedException(SR.DelegateGetMethodInfo_NoDynamic);
else
throw new NotSupportedException(SR.Format(SR.DelegateGetMethodInfo_NoDynamic_WithDisplayString, methodDisplayString));
Comment on lines -60 to -66
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If any of this is reached, it's a compiler bug - it should no longer be possible to get a delegate that points to managed code that doesn't have MethodInfo. We don't need to fetch the method name from stack trace data for error messages. It's not expected that users will need to write RD.XML for this anymore.

throw new NotSupportedException(SR.DelegateGetMethodInfo_NoDynamic);
}
}
return (MethodInfo)ExecutionDomain.GetMethod(typeOfFirstParameterIfInstanceDelegate, methodHandle, genericMethodTypeArgumentHandles);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,6 @@
<data name="DelegateGetMethodInfo_NoDynamic" xml:space="preserve">
<value>Cannot retrieve a MethodInfo for this delegate because the method it targeted was not enabled for metadata.</value>
</data>
<data name="DelegateGetMethodInfo_NoDynamic_WithDisplayString" xml:space="preserve">
<value>Cannot retrieve a MethodInfo for this delegate because the method it targeted ({0}) was not enabled for metadata.</value>
</data>
<data name="DelegateGetMethodInfo_NoInstantiation" xml:space="preserve">
<value>Cannot retrieve a MethodInfo for this delegate because the necessary generic instantiation was not metadata-enabled.</value>
</data>
Expand Down
Loading