// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // // --------------------------------------------------------------------------- // zapsig.h // // Copyright (c) Microsoft 2002 // --------------------------------------------------------------------------- // // This module contains helper functions used to encode and manipulate // signatures for the zapper (ngen). // // --------------------------------------------------------------------------- #ifndef ZAPSIG_H #define ZAPSIG_H #include "common.h" #ifdef BINDER #include "typehandle.h" #endif //define function pointer type: EncodeModuleCallback // #ifdef BINDER typedef DWORD (*EncodeModuleCallback)(void* pModuleContext, MdilModule *pReferencedModule); #else typedef DWORD (*EncodeModuleCallback)(void* pModuleContext, Module *pReferencedModule); #endif enum { // return value when EncodeModule fails ENCODE_MODULE_FAILED = 0xffffffff, }; //define function pointer type: TokenDefinitionCallback // #ifdef BINDER typedef void (*TokenDefinitionCallback)(void* pModuleContext, MdilModule *pReferencedModule, DWORD index, mdToken* refToken); #else typedef void (*TokenDefinitionCallback)(void* pModuleContext, Module *pReferencedModule, DWORD index, mdToken* refToken); #endif class ZapSig { public: enum ExternalTokens { IllegalValue, NormalTokens, IbcTokens }; struct Context { #ifdef BINDER MdilModule * pInfoModule; // The tokens in this ZapSig are expressed relative to context.pInfoModule #else Module * pInfoModule; // The tokens in this ZapSig are expressed relative to context.pInfoModule #endif void * pModuleContext; // This is a code:Module* when we are resolving Ngen fixups or doing an Ibc Profiling run // and is a code:ZapImportTable* when we are running ngen ExternalTokens externalTokens; // When we see a ELEMENT_TYPE_MODULE_ZAPSIG this tells us what type of token follows. Module * GetZapSigModule() const { return (Module*) pModuleContext; } Context( #ifdef BINDER MdilModule* _pInfoModule, #else Module* _pInfoModule, #endif void* _pModuleContext, ExternalTokens _externalTokens) : pInfoModule(_pInfoModule), pModuleContext(_pModuleContext), externalTokens(_externalTokens) { LIMITED_METHOD_CONTRACT; _ASSERTE(externalTokens != IllegalValue); } Context( #ifdef BINDER MdilModule* _pInfoModule, #else Module* _pInfoModule, #endif Module* _pZapSigModule) : pInfoModule(_pInfoModule), pModuleContext((void*) _pZapSigModule), externalTokens(NormalTokens) { } }; public: ZapSig( #ifdef BINDER MdilModule * _pInfoModule, #else Module * _pInfoModule, #endif void * _pModuleContext, ExternalTokens _externalTokens, EncodeModuleCallback _pfnEncodeModule, TokenDefinitionCallback _pfnTokenDefinition) : context(_pInfoModule, _pModuleContext, _externalTokens), pfnEncodeModule(_pfnEncodeModule), pfnTokenDefinition(_pfnTokenDefinition) {} #ifdef FEATURE_PREJIT // Instance methods // Create a signature for a typeHandle // It can be decoded using MetaSig::GetTypeHandleThrowing // The tokens are espressed relative to this->pInfoModule // When (handle.GetModule() != this->pInfoModule), we escape // the signature with ELEMENT_TYPE_MODULE_ZAPSIG // followed by a to encode a temporary change of module // For Ibc Signatures the is one of the ibc defined tokens // For Ngen Fixup signatures the is for the external module // BOOL GetSignatureForTypeHandle(TypeHandle typeHandle, SigBuilder * pSigBuilder); // Static methods // Compare a type handle with a signature whose tokens are resolved with respect to pModule // pZapSigContext is used to resolve ELEMENT_TYPE_MODULE_ZAPSIG encodings static BOOL CompareSignatureToTypeHandle(PCCOR_SIGNATURE pSig, #ifdef BINDER MdilModule* pModule, #else Module* pModule, #endif TypeHandle handle, const ZapSig::Context * pZapSigContext); // Compare a type handle with a tagged pointer. Ensure that the common path is inlined into the caller. static FORCEINLINE BOOL CompareTaggedPointerToTypeHandle(Module * pModule, TADDR addr, TypeHandle handle) { WRAPPER_NO_CONTRACT; if (handle.AsTAddr() == addr) return TRUE; if (!CORCOMPILE_IS_POINTER_TAGGED(addr)) return FALSE; return CompareFixupToTypeHandle(pModule, addr, handle); } static BOOL CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle); static BOOL CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2); private: BOOL GetSignatureForTypeDesc(TypeDesc * desc, SigBuilder * pSigBuilder); // Returns element type when the typeHandle can be encoded using // using a single CorElementType value // This includes using ELEMENT_TYPE_CANON_ZAPSIG for the System.__Canon type // static CorElementType TryEncodeUsingShortcut(/* in */ MethodTable * pMT); #endif // FEATURE_PREJIT private: ZapSig::Context context; EncodeModuleCallback pfnEncodeModule; // Function Pointer to the EncodeModuleHelper TokenDefinitionCallback pfnTokenDefinition; // Function Pointer to the DefineTokenHelper public: //-------------------------------------------------------------------- // Static helper encode/decode helper methods static Module *DecodeModuleFromIndexes(Module *fromModule, DWORD assemblyIndex, DWORD moduleIndex); static Module *DecodeModuleFromIndexesIfLoaded(Module *fromModule, DWORD assemblyIndex, DWORD moduleIndex); // referencingModule is the module that references the type. // fromModule is the module in which the type is defined. // pBuffer contains the signature encoding for the type. // level is the class load level (see classloadlevel.h) to which the type should be loaded static TypeHandle DecodeType(Module *referencingModule, Module *fromModule, PCCOR_SIGNATURE pBuffer, ClassLoadLevel level = CLASS_LOADED); static MethodDesc *DecodeMethod(Module *referencingModule, Module *fromModule, PCCOR_SIGNATURE pBuffer, TypeHandle * ppTH = NULL); static FieldDesc *DecodeField(Module *referencingModule, Module *fromModule, PCCOR_SIGNATURE pBuffer, TypeHandle * ppTH = NULL); static BOOL EncodeMethod( MethodDesc *pMethod, Module *pInfoModule, SigBuilder *pSigBuilder, LPVOID pReferencingModule, ENCODEMODULE_CALLBACK pfnEncodeModule, DEFINETOKEN_CALLBACK pfnDefineToken, CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL); static void EncodeField( FieldDesc *pField, Module *pInfoModule, SigBuilder *pSigBuilder, LPVOID pReferencingModule, ENCODEMODULE_CALLBACK pfnEncodeModule, CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL); }; #endif // ZAPGSIG_H