如何查看标记为MethodImplOptions.InternalCall的方法代码

本文关键字:方法 代码 InternalCall MethodImplOptions 何查看 记为 | 更新日期: 2023-09-27 18:13:42

使用ILSpy检查系统代码时。字符串,我发现有一些方法标记为MethodImplOptions。内部调用,例如:

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

我知道MethodImplOptions。InternalCall意味着该方法由公共语言运行库本地实现,以优化代码以提高性能。

我的问题是:无论如何都可以使我们看到标记为MethodImplOptions.InternalCall的代码吗?

如何查看标记为MethodImplOptions.InternalCall的方法代码

您需要CLR的源代码才能看到这些方法的实现。这有点难得到,微软没有发布它,参考源代码也没有涵盖它。

只要方法是"旧的",从。net 2.0开始可用,那么您就可以从SSCLI20源代码中尝试它。当然,您将看到过时版本的代码的风险不是零。但足以让你知道它是什么样子的,而且通常仍然是准确的。

开始搜索代码的起始点是clr/src/vm/call.cpp源代码文件。它包含抖动搜索内部方法的表。与ativeecompareordinalex()相关的部分如下所示:

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..
}

注意FCFuncElement是如何将方法名作为字符串和函数指针指向实现内部调用的c++方法的。然后在源代码树中找到clr/src/vm/comstring.cpp。我不会用c++代码来烦大家,你自己看看吧。

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

搜索CaseInsensitiveCompHelper()和FastCompareStringHelperAligned()将带您在同一个源代码文件中分别看到大小写不敏感和大小写敏感比较函数的实际实现。

唯一值得注意的是CLR版本4对该机制做了一些更改。添加了许多新的内部方法,并通过一个名为"QCall"的假DLL的[DllImport]属性支持一个完全不同的额外互操作机制。据我所知,没有很好的方法来查看这些添加的源代码。


UPDATE:源代码现在可以从CoreCLR项目中获得。表从call.cpp移到了ecalllist.h,机制还是一样的。请记住,这是。net core版本的CLR,桌面版本的源代码仍然是闭源的。然而,这两个版本可能有很多共同之处。

由于现在CoreCLR是开源的,所以我们可以查看内部代码。

您可以在stringnative.cpp中搜索COMString::CompareOrdinalEx关键字查看内部实现

正如帮助字符串所说,它们是"在CLR本身中实现的",因此您需要查阅其c++源代码或反汇编。

一般来说,组成CLR引擎的文件是%WINDIR%'Microsoft.NET'Framework'<.NET engine version>文件夹中的一些本地dll,主要是mscor*.dllclr.dll。根。net DLL, mscoree.dll,在System32,但它似乎只作为一个启动器。

由于InternalCall方法实现是实现细节,因此无法保证这些方法以一致的方式实现,例如,甚至有一些全局注册表。

。拆解表明。net 4 System.String的原生方法是在clr.dll中实现的,并在一个类似目录的结构中引用,而System.Deployment.Application.NativeMethods.IClrRuntimeInfo是由mscoreei.dll中的CLRRuntimeInfoImpl COM类支持的,这些方法只是它的虚函数。