runtime icon indicating copy to clipboard operation
runtime copied to clipboard

.NET CLR profiling API does not return ELEMENT_TYPE_GENERICINST on generic method

Open yanshof opened this issue 3 years ago • 1 comments

Description

I'm using .NET CLR profiling API to get fully qualified names of invoked methods, including the type of return value and arguments list. To get this information, I'm using JITCompilationStarted callback. I managed to get the required information except for the case when the function of the non-generic class has the function with Generic arguments

example

public class NotGenericClass
   {
    public void IfNull(Object obj)
    {
        if (obj == null)
        {
            Console.WriteLine("obj is null");
        }
    }

// not show that this method is generic 
public void CheckList<T>(List<string> listString)
{
    foreach (var item in listString)
    {
        Console.WriteLine(item);
    }
}

// not show that this method is generic and the return param type will be void (ELEMENT_TYPE_VOID) or bool ( ELEMENT_TYPE_BOOLEAN )
public object CheckList1<T>(IList<T> listString)
{
    foreach (var item in listString)
    {
        Console.WriteLine(item);
    }

    return new object();
}

// always return 1 argument count - and not show that this method is generic 
public void Check<T>(T item, int t, int e)
{
    Console.WriteLine(item);
}

}

In this case, on JITCompilationStarted I'm receiving the parameter type "void" and in some cases, the return value will be different than what I expected.

If the class is generic there is no such problem.

Also during debugging and parsing PCCOR_SIGNATURE I see that there is 1 parameter that the function has - even if there is more than one parameter. And the 'CorElementType' that I expect to get as ELEMENT_TYPE_GENERICINST is different in the situation when the method is generic, class is not generic

Reproduction Steps

  1. run the code on C# side - and wait on the profiler to receive the call for JITCompilationStarted

  2. by using the IMetaDataImport::GetMethodProps find the number of the parameter of the called function ( functionID is one of the parameters of the JITCompilationStarted ) parameter

Expected behavior

  1. the number of the parameters suppose to be the number of the parameter on the method
  2. if the parameter is generic ( <T > line in the example ) - I expect to see the ELEMENT_TYPE_GENERICINST on the PCCOR_SIGNATURE as i see on the generic class

Actual behavior

  1. The number of the parameters is wrong
  2. parameter type will be not Generic type ( ELEMENT_TYPE_GENERICINST )

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

yanshof avatar Sep 20 '22 16:09 yanshof

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

Tagging subscribers to this area: @tommcdon See info in area-owners.md if you want to be subscribed.

Issue Details

Description

I'm using .NET CLR profiling API to get fully qualified names of invoked methods, including the type of return value and arguments list. To get this information, I'm using JITCompilationStarted callback. I managed to get the required information except for the case when the function of the non-generic class has the function with Generic arguments

example

public class NotGenericClass
   {
    public void IfNull(Object obj)
    {
        if (obj == null)
        {
            Console.WriteLine("obj is null");
        }
    }

// not show that this method is generic 
public void CheckList<T>(List<string> listString)
{
    foreach (var item in listString)
    {
        Console.WriteLine(item);
    }
}

// not show that this method is generic and the return param type will be void (ELEMENT_TYPE_VOID) or bool ( ELEMENT_TYPE_BOOLEAN )
public object CheckList1<T>(IList<T> listString)
{
    foreach (var item in listString)
    {
        Console.WriteLine(item);
    }

    return new object();
}

// always return 1 argument count - and not show that this method is generic 
public void Check<T>(T item, int t, int e)
{
    Console.WriteLine(item);
}

}

In this case, on JITCompilationStarted I'm receiving the parameter type "void" and in some cases, the return value will be different than what I expected.

If the class is generic there is no such problem.

Also during debugging and parsing PCCOR_SIGNATURE I see that there is 1 parameter that the function has - even if there is more than one parameter. And the 'CorElementType' that I expect to get as ELEMENT_TYPE_GENERICINST is different in the situation when the method is generic, class is not generic

Reproduction Steps

  1. run the code on C# side - and wait on the profiler to receive the call for JITCompilationStarted

  2. by using the IMetaDataImport::GetMethodProps find the number of the parameter of the called function ( functionID is one of the parameters of the JITCompilationStarted ) parameter

Expected behavior

  1. the number of the parameters suppose to be the number of the parameter on the method
  2. if the parameter is generic ( <T > line in the example ) - I expect to see the ELEMENT_TYPE_GENERICINST on the PCCOR_SIGNATURE as i see on the generic class

Actual behavior

  1. The number of the parameters is wrong
  2. parameter type will be not Generic type ( ELEMENT_TYPE_GENERICINST )

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Author: yanshof
Assignees: -
Labels:

area-Diagnostics-coreclr, untriaged

Milestone: -

ghost avatar Sep 20 '22 18:09 ghost

@davmason please take a look

tommcdon avatar Sep 21 '22 02:09 tommcdon

Hey @tommcdon Can you please confirm that this is indeed an issue?

amit-hadari avatar Sep 21 '22 13:09 amit-hadari

Hey @tommcdon Can you please confirm that this is indeed an issue?

Hi @amit-hadari! I've asked @davmason to take a look

tommcdon avatar Sep 21 '22 14:09 tommcdon

Hi @amit-hadari @yanshof,

Could you post what you get from parsing the PCCOR_SIGNATURE? When you say the number is wrong and the type is not ELEMENT_TYPE_GENERICINST, what is the number and type you get?

Just to set expectations, it is very unlikely that this is a bug in the runtime. The metadata code is very old and hardly ever changes so bugs are unlikely. Usually when dealing with the metadata code you end up finding out whatever quirk is happening and updating your parser accordingly.

davmason avatar Sep 30 '22 11:09 davmason

Yes, the number that will receive is an enum of ELEMENT_TYPE_VOID or ELEMENT_TYPE_BOOLEAN (ELEMENT_TYPE_VOID is 0x1 and ELEMENT_TYPE_BOOLEAN is 0x2) and it happened on a class that is not generic but contain a generic method ( like i added to the issue above ). I don't find any information/documentation on how .net generates code in this case - on a regular class with the generic method.

the parser is made according to the calling Convention ( IMAGE_CEE_CS_CALLCONV_HASTHIS or IMAGE_CEE_CS_CALLCONV_DEFAULT or IMAGE_CEE_CS_CALLCONV_GENERIC ( but also possible to get the value of 48 that is without clear enum )

yanshof avatar Sep 30 '22 18:09 yanshof

My recollection is that if the method signature has the generic flag in the first byte (0x10), then immediately following is the number of generic parameters. When you see 0x1 or 0x2, that should be the generic parameter count. After that you should see the actual parameter count, return type, and parameter list.

Let me know if that matches what you're seeing, it's been quite a while since I last looked at the signature parsing code.

davmason avatar Sep 30 '22 21:09 davmason

This issue has been marked needs-author-action and may be missing some important information.

ghost avatar Oct 11 '22 08:10 ghost