-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add IL Offset and Method Token to stacktrace #44013
Changes from 13 commits
c77d3be
a7f6060
99f96fa
90479a1
7b3f838
af7c84b
62350d8
c54d679
870543a
8ee5242
a3e2476
a10ebfc
c63a0c8
8c85326
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
|
||
class Program | ||
{ | ||
public static void Foo() | ||
{ | ||
throw new NullReferenceException(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> | ||
<TargetFrameworks>netstandard2.0</TargetFrameworks> | ||
<DebugType>None</DebugType> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="ExceptionTestAssembly.cs" /> | ||
</ItemGroup> | ||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,9 +3,13 @@ | |
|
||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Reflection.Emit; | ||
using System.Runtime.CompilerServices; | ||
using System.Text.RegularExpressions; | ||
using Microsoft.DotNet.RemoteExecutor; | ||
using Xunit; | ||
|
||
namespace System.Diagnostics | ||
|
@@ -300,6 +304,71 @@ public void ToString_NullFrame_ThrowsNullReferenceException() | |
Assert.Equal(Environment.NewLine, stackTrace.ToString()); | ||
} | ||
|
||
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] | ||
public void ToString_ShowILOffset() | ||
{ | ||
string AssemblyName = "ExceptionTestAssembly.dll"; | ||
string SourceTestAssemblyPath = Path.Combine(Environment.CurrentDirectory, AssemblyName); | ||
string regPattern = @":token 0x([a-f0-9]*)\+0x([a-f0-9]*)"; | ||
|
||
// Normal loading case | ||
RemoteExecutor.Invoke((asmPath, asmName, p) => | ||
{ | ||
AppContext.SetSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess not needed any more? And same in other test There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, the default value is true, but it can be changed. |
||
var asm = Assembly.LoadFrom(asmPath); | ||
try | ||
{ | ||
asm.GetType("Program").GetMethod("Foo").Invoke(null, null); | ||
} | ||
catch (Exception e) | ||
{ | ||
Assert.Contains(asmName, e.InnerException.StackTrace); | ||
Assert.True(Regex.Match(e.InnerException.StackTrace, p).Success); | ||
} | ||
}, SourceTestAssemblyPath, AssemblyName, regPattern).Dispose(); | ||
|
||
// Assembly.Load(Byte[]) case | ||
RemoteExecutor.Invoke((asmPath, asmName, p) => | ||
{ | ||
AppContext.SetSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true); | ||
var inMemBlob = File.ReadAllBytes(asmPath); | ||
var asm2 = Assembly.Load(inMemBlob); | ||
try | ||
{ | ||
asm2.GetType("Program").GetMethod("Foo").Invoke(null, null); | ||
} | ||
catch (Exception e) | ||
{ | ||
Assert.Contains(asmName, e.InnerException.StackTrace); | ||
Assert.True(Regex.Match(e.InnerException.StackTrace, p).Success); | ||
} | ||
}, SourceTestAssemblyPath, AssemblyName, regPattern).Dispose(); | ||
|
||
// AssmblyBuilder.DefineDynamicAssembly() case | ||
RemoteExecutor.Invoke((p) => | ||
{ | ||
AppContext.SetSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true); | ||
AssemblyName asmName = new AssemblyName("ExceptionTestAssembly"); | ||
AssemblyBuilder asmBldr = AssemblyBuilder.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run); | ||
ModuleBuilder modBldr = asmBldr.DefineDynamicModule(asmName.Name); | ||
TypeBuilder tBldr = modBldr.DefineType("Program"); | ||
MethodBuilder mBldr = tBldr.DefineMethod("Foo", MethodAttributes.Public | MethodAttributes.Static, null, null); | ||
ILGenerator ilGen = mBldr.GetILGenerator(); | ||
ilGen.ThrowException(typeof(NullReferenceException)); | ||
ilGen.Emit(OpCodes.Ret); | ||
Type t = tBldr.CreateType(); | ||
try | ||
{ | ||
t.InvokeMember("Foo", BindingFlags.InvokeMethod, null, null, null); | ||
} | ||
catch (Exception e) | ||
{ | ||
Assert.Contains("RefEmit_InMemoryManifestModule", e.InnerException.StackTrace); | ||
Assert.True(Regex.Match(e.InnerException.StackTrace, p).Success); | ||
} | ||
}, regPattern).Dispose(); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] | ||
private static StackTrace NoParameters() => new StackTrace(); | ||
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit please sort using statements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll fix