Come vedere il codice del metodo contrassegnato come MethodImplOptions.InternalCall?

Quando utilizzo ILSpy per verificare il codice di System.String, ho trovato alcuni metodi contrassegnati come MethodImplOptions.InternalCall come:

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

Conosco MethodImplOptions.InternalCall significa che questo metodo è implementato in modo nativo dal Common Language Runtime al codice ottimizzato per migliorare le prestazioni.

La mia domanda è: è che comunque ci può consentire di vedere il codice contrassegnato come MethodImplOptions.InternalCall?

Avrai bisogno del codice sorgente per il CLR per vedere l’implementazione di questi metodi. È un po ‘difficile da trovare, Microsoft non lo pubblica e non è coperto dalla Reference Source.

Finché il metodo è “vecchio”, disponibile da .NET 2.0, avrai una possibilità dal codice sorgente SSCLI20 . Con un rischio diverso da zero vedrete ovviamente una versione obsoleta del codice. Ma abbastanza buono per avere un’idea di ciò che sembra e spesso ancora preciso.

Il punto di partenza per iniziare a cercare il codice è il file di codice sorgente clr / src / vm / ecall.cpp. Contiene le tabelle in cui il jitter ricerca i metodi interni. La sezione pertinente per nativeCompareOrdinalEx () ha il seguente aspetto:

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

Nota come FCFuncElement ha il nome del metodo come stringa e un puntatore alla funzione del metodo C ++ che implementa la chiamata interna. Fare un grepping dell'albero del codice sorgente ti porta quindi a clr / src / vm / comstring.cpp. Non annoierò tutti con il codice C ++, ma dai un'occhiata.

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

La ricerca di CaseInsensitiveCompHelper () e FastCompareStringHelperAligned () porta alle effettive implementazioni delle funzioni di confronto, rispettivamente, maiuscole e minuscole e maiuscole e minuscole nello stesso file di codice sorgente.

L'unica altra cosa degna di nota a riguardo è che CLR versione 4 ha apportato alcune modifiche a questo meccanismo. Aggiunta di molti nuovi metodi interni e supporto di un meccanismo di interoperabilità aggiuntivo completamente diverso attraverso un attributo [DllImport] per una falsa DLL chiamata "QCall". Non c'è un buon modo per vedere la fonte di queste aggiunte che io conosca.


UPDATE: source è ora disponibile dal progetto CoreCLR . La tabella è stata spostata da ecall.cpp in ecalllist.h, i meccanismi sono sempre gli stessi. Tieni presente che questa è la versione .NETCore del CLR, l'origine della versione desktop è ancora closed-source. Tuttavia, è probabile che le due versioni abbiano molto in comune.

Poiché ora CoreCLR è open source , è ansible verificare il codice interno.

Puoi cercare COMString::CompareOrdinalEx keyword in stringnative.cpp per vedere l’implementazione interna.

Come dice la stringa di aiuto, sono “implementati nel CLR stesso”, quindi dovrai consultare i suoi sorgenti o il suo sassembly C ++.

Generalmente, i file che comprendono il motore CLR sono alcune DLL native nella %WINDIR%\Microsoft.NET\Framework\<.NET engine version> , principalmente mscor*.dll e clr.dll . La radice .NET DLL, mscoree.dll , è in System32 ma sembra funzionare solo come un launcher.

Poiché le implementazioni del metodo InternalCall sono dettagli di implementazione, non è ansible garantire che tali metodi siano implementati in modo coerente, ad esempio che siano presenti anche alcuni registri globali.

Ad esempio, il disassemblaggio mostra che i metodi nativi di .NET 4 System.String sono implementati in clr.dll e fanno riferimento a una struttura simile a una directory mentre System.Deployment.Application.NativeMethods.IClrRuntimeInfo è supportato dalla class COM mscoreei.dll in mscoreei.dll , i metodi semplicemente sono le sue funzioni virtuali.