Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to see code of method which marked as MethodImplOptions.InternalCall?

Tags:

c#

.net

clr

When use ILSpy to check the code of System.String, I found there are some methods marked as MethodImplOptions.InternalCall such as:

[SecurityCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int nativeCompareOrdinalEx(string strA, int indexA, string strB, int indexB, int count);

I know MethodImplOptions.InternalCall means this method is implemented natively by the common language runtime to optimized code to improve performance.

My question is: Is that anyway can enable us to see the code marked as MethodImplOptions.InternalCall?

like image 440
2power10 Avatar asked May 16 '13 04:05

2power10


3 Answers

You'll need the source code for the CLR to see the implementation of these methods. That's a bit hard to come by, Microsoft doesn't publish it and it is not covered by the Reference Source.

As long as the method is "old", available since .NET 2.0, then you'll have a shot at it from the SSCLI20 source code. With a non-zero risk that you will be looking at an outdated version of the code of course. But good enough to get an idea what it looks like and often still accurate.

The starting point to start searching for the code is the clr/src/vm/ecall.cpp source code file. It contains the tables that the jitter searches for internal methods. The section that's relevant for nativeCompareOrdinalEx() looks like this:

FCFuncStart(gStringFuncs)
    FCDynamic("FastAllocateString", CORINFO_INTRINSIC_Illegal, ECall::FastAllocateString)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ArrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharArrayManaged)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ArrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharArrayStartLengthManaged)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrManaged)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrStartLengthManaged)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_Char_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharCountManaged)

    FCFuncElement("nativeCompareOrdinal", COMString::FCCompareOrdinal)     // <=== Here
    FCFuncElement("nativeCompareOrdinalWC", COMString::FCCompareOrdinalWC)
    FCIntrinsic("get_Length", COMString::Length, CORINFO_INTRINSIC_StringLength)
    // etc..
}

Note how the FCFuncElement has the method name as a string and a function pointer to the C++ method that implements the internal call. Grepping the source code tree then takes you to clr/src/vm/comstring.cpp. I won't bore everybody with the C++ code, just have a look for yourself.

/*================================CompareOrdinal===============================*/
FCIMPL3(INT32, COMString::FCCompareOrdinal, StringObject* strA, StringObject* strB, CLR_BOOL bIgnoreCase) {
    // Yadayada
    //...
}

Searching for CaseInsensitiveCompHelper() and FastCompareStringHelperAligned() takes you to the actual implementations of the, respectively, case-insensitive and case-sensitive comparison functions in the same source code file.

The only other thing notable about this is that CLR version 4 made some changes to this mechanism. Adding lots of new internal methods and supporting an entirely different additional interop mechanism through a [DllImport] attribute for a fake DLL named "QCall". There's no good way to see source for these additions that I know of.


UPDATE: source is now available from the CoreCLR project. The table was moved from ecall.cpp to ecalllist.h, the mechanics are still the same. Do keep in mind that this is the .NETCore version of the CLR, the desktop version source is still closed-source. The two version are however likely to have much in common.

like image 114
Hans Passant Avatar answered Sep 20 '22 13:09

Hans Passant


Since now CoreCLR is open source, so we could check out the internal code.

You could search COMString::CompareOrdinalEx keyword in stringnative.cpp to see the internal implementation.

like image 41
2power10 Avatar answered Sep 22 '22 13:09

2power10


As the help string says, they are "implemented in the CLR itself", so you'll need to consult its C++ sources or disassembly.

Generally, the files that comprise the CLR engine are a few native DLLs in the %WINDIR%\Microsoft.NET\Framework\<.NET engine version> folder, mostly mscor*.dll and clr.dll. The root .NET DLL, mscoree.dll, is in System32 but it seems to only act as a launcher.

Since the InternalCall method implementations are implementation details, there's no guarantee that those methods are implemented in a consistent way, e.g. that there's even some global registry of them.

E.g. disassembling shows that .NET 4 System.String's native methods are implemented in clr.dll and referenced in a directory-like structure while System.Deployment.Application.NativeMethods.IClrRuntimeInfo is backed by the CLRRuntimeInfoImpl COM class in mscoreei.dll, the methods simply being its virtual functions.

like image 25
ivan_pozdeev Avatar answered Sep 21 '22 13:09

ivan_pozdeev