-
Notifications
You must be signed in to change notification settings - Fork 387
Fix !clrstack trimming method names with angle brackets when DML is enabled #5594
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
base: main
Are you sure you want to change the base?
Changes from all commits
924ccd5
aaa79ae
4f13197
4817020
a713dd4
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 |
|---|---|---|
|
|
@@ -5518,6 +5518,37 @@ WString MethodNameFromIP(CLRDATA_ADDRESS ip, BOOL bSuppressLines, BOOL bAssembly | |
| return methodOutput; | ||
| } | ||
|
|
||
| WString DmlEscape(const WString &input) | ||
| { | ||
| const WCHAR *str = input.c_str(); | ||
| size_t len = input.GetLength(); | ||
| WString result; | ||
|
|
||
| for (size_t i = 0; i < len; i++) | ||
| { | ||
| if (str[i] == L'<') | ||
| { | ||
| result += W("<"); | ||
| } | ||
| else if (str[i] == L'>') | ||
| { | ||
| result += W(">"); | ||
| } | ||
| else if (str[i] == L'&') | ||
| { | ||
| result += W("&"); | ||
| } | ||
| else | ||
| { | ||
| // Append single character | ||
| WCHAR temp[2] = { str[i], L'\0' }; | ||
| result += temp; | ||
| } | ||
|
Comment on lines
+5527
to
+5546
|
||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| HRESULT GetGCRefs(ULONG osID, SOSStackRefData **ppRefs, unsigned int *pRefCnt, SOSStackRefError **ppErrors, unsigned int *pErrCount) | ||
| { | ||
| if (ppRefs == NULL || pRefCnt == NULL) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System; | ||
| using System.Threading.Tasks; | ||
|
|
||
| public class AsyncMainTest | ||
| { | ||
| public static async Task<int> Main(string[] args) | ||
| { | ||
| DivideData data = new() | ||
| { | ||
| Numerator = 16, | ||
| Denominator = 0, | ||
| }; | ||
|
|
||
| Console.WriteLine($"{data.Numerator}/{data.Denominator} = {await DivideAsync(data)}"); | ||
| return 0; | ||
| } | ||
|
|
||
| static async Task<int> DivideAsync(DivideData data) | ||
| { | ||
| await Task.Delay(10); | ||
| return data.Numerator / data.Denominator; | ||
| } | ||
| } | ||
|
|
||
| public class DivideData | ||
| { | ||
| public int Numerator { get; set; } | ||
| public int Denominator { get; set; } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework Condition="'$(BuildProjectFramework)' != ''">$(BuildProjectFramework)</TargetFramework> | ||
| <TargetFrameworks Condition="'$(BuildProjectFramework)' == ''">$(SupportedSubProcessTargetFrameworks)</TargetFrameworks> | ||
| </PropertyGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,14 @@ | ||||||||||
| # | ||||||||||
| # Tests that ClrStack properly displays async Main method names with angle brackets when DML is enabled | ||||||||||
| # | ||||||||||
|
|
||||||||||
| CONTINUE | ||||||||||
|
|
||||||||||
| LOADSOS | ||||||||||
|
|
||||||||||
| # Verify that ClrStack with /d (DML enabled) properly displays async method name with angle brackets | ||||||||||
| SOSCOMMAND:ClrStack /d | ||||||||||
| VERIFY:.*OS Thread Id:\s+0x<HEXVAL>\s+.* | ||||||||||
| VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ | ||||||||||
| # Verify that the method name contains <Main> and is not trimmed to Main> | ||||||||||
| VERIFY:.*AsyncMainTest\.<Main>\(.*\).* | ||||||||||
|
Comment on lines
+13
to
+14
|
||||||||||
| # Verify that the method name contains <Main> and is not trimmed to Main> | |
| VERIFY:.*AsyncMainTest\.<Main>\(.*\).* | |
| # Verify that the method name contains <Main> (escaped as <Main> with DML) and is not trimmed to Main> | |
| VERIFY:.*AsyncMainTest\.<Main>\(.*\).* |
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.
The DmlEscape function has a performance concern. On each iteration, it creates a temporary 2-character array and concatenates it to the result string, which can be inefficient for longer strings due to repeated memory allocations. Consider using
result.Reserve()to pre-allocate space, or accumulate characters in a buffer before appending them to the result string.