Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 9, 2025

Problem

When !clrstack encountered method names containing angle brackets (e.g., Program.<Main>(System.String[])), it incorrectly trimmed the content between the brackets, displaying Program.(System.String[]) instead. This issue affected async methods, local functions, and other compiler-generated methods that use angle brackets in their names.

Both ClrMD and WinDbg (ICorDebug + IMetaDataReader) correctly returned the full method name including angle brackets.

Root Cause

When DML (Debugger Markup Language) is enabled, the <> characters were being interpreted as DML tags rather than literal text. The PrintThread function in strike.cpp was passing unescaped method names to TableOutput, causing the content between angle brackets to be treated as markup and stripped from the output.

Solution

This PR adds proper DML escaping for method and frame names:

  1. Implemented DmlEscape() function in util.cpp that escapes special characters:

    • <&lt;
    • >&gt;
    • &&amp;
  2. Applied escaping in PrintThread() in strike.cpp:

    • Method names from MethodNameFromIP() are DML-escaped when IsDMLEnabled() returns true
    • Frame names from GetFrameFromAddress() receive the same treatment for consistency
  3. Added test coverage with an AsyncMain test case that uses async Main method to verify angle brackets are preserved in the output

Example

Before:

Child SP       IP               Call Site
00000000       00000000         Program.(System.String[])

After:

Child SP       IP               Call Site
00000000       00000000         Program.<Main>(System.String[])

Impact

This is a minimal, surgical fix that only affects method/frame name display when DML is enabled. The changes ensure backward compatibility while correctly handling special characters in method names.

Fixes #4996

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 80zvsblobprodcus35.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/diagnostics/diagnostics/.dotnet/dotnet msbuild /m /nologo /clp:Summary /v:minimal /nr:true /warnaserror /p:TreatWarningsAsErrors=true /p:ContinuousIntegrationBuild=false /home/REDACTED/work/diagnostics/diagnostics/eng/native-prereqs.proj /bl:/home/REDACTED/work/diagnostics/diagnostics/artifacts/log/Debug/GenerateVersion.binlog /t:Build /restore /p:Configuration=Debug /p:TargetOS=linux /p:TargetArch=x64 /p:TargetRid=linux-x64 /p:Platform=x64 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>!clrstack reports incorrect method names when <> is encountered</issue_title>
<issue_description>When !clrstack encounters Program.<Main>(System.String[]), it trims the method name to: Program.(System.String[]). Both ClrMD and WinDbg (ICorDebug + IMetaDataReader) correctly return Program.<Main>(System.String[]).

I verified this with the main branch. I think the issue is that ClrStackImpl::PrintThread does not DML escape the MethodNameFromIP string we pass to TableOutput. It's not clear whether we should be specifically escaping in PrintThread or if TableOutput should do that.

To repro, create a .Net 8 app (preview), and add this code, and debug the resulting crash dump (or any async Main):

DivideData data = new()
{
    Numerator = 16,
    Denominator = 0,
};

Console.WriteLine($"{data.Numerator}/{data.Denominator} = {await DivideAsync(data)}");

static async Task<int> DivideAsync(DivideData divData)
{
    await Task.Delay(1000);

    return divData.Numerator / divData.Denominator;
}

class DivideData
{
    public int Numerator { get; set; }
    public int Denominator { get; set; }
}

(I'm working on other stuff at the moment, can't take this issue in the next two weeks. I was going to submit a quick fix, but there's not a globally defined DmlEscape.)</issue_description>

<agent_instructions>In strike.cpp, the PrintThread function calls into MethodNameFromIP in order to supply what gets written out. Properly format the string it returns so that <> is not trimmed.</agent_instructions>

Comments on the Issue (you are @copilot in this section)

Fixes #4314

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@Copilot Copilot AI changed the title [WIP] Fix method name trimming in clrstack reports Fix !clrstack trimming method names with angle brackets when DML is enabled Oct 9, 2025
@Copilot Copilot AI requested a review from steveisok October 9, 2025 01:51
Copilot finished work on behalf of steveisok October 9, 2025 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

!clrstack reports incorrect method names when <> is encountered

2 participants