1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5// ---------------------------------------------------------------------------
6// zapsig.h
7// ---------------------------------------------------------------------------
8//
9// This module contains helper functions used to encode and manipulate
10// signatures for the zapper (ngen).
11//
12
13// ---------------------------------------------------------------------------
14
15
16#ifndef ZAPSIG_H
17#define ZAPSIG_H
18
19#include "common.h"
20
21typedef DWORD(*ENCODEMODULE_CALLBACK)(LPVOID pModuleContext, CORINFO_MODULE_HANDLE moduleHandle);
22typedef DWORD (*EncodeModuleCallback)(void* pModuleContext, Module *pReferencedModule);
23enum {
24 // return value when EncodeModule fails
25 ENCODE_MODULE_FAILED = 0xffffffff,
26};
27
28typedef void(*DEFINETOKEN_CALLBACK)(LPVOID pModuleContext, CORINFO_MODULE_HANDLE moduleHandle, DWORD index, mdTypeRef* token);
29typedef void (*TokenDefinitionCallback)(void* pModuleContext, Module *pReferencedModule, DWORD index, mdToken* refToken);
30
31class ZapSig
32{
33public:
34 enum ExternalTokens
35 {
36 IllegalValue,
37 NormalTokens,
38 IbcTokens
39 };
40
41 struct Context
42 {
43 Module * pInfoModule; // The tokens in this ZapSig are expressed relative to context.pInfoModule
44 void * pModuleContext; // This is a code:Module* when we are resolving Ngen fixups or doing an Ibc Profiling run
45 // and is a code:ZapImportTable* when we are running ngen
46 ExternalTokens externalTokens; // When we see a ELEMENT_TYPE_MODULE_ZAPSIG this tells us what type of token follows.
47
48 Module * GetZapSigModule() const { return (Module*) pModuleContext; }
49
50 Context(
51 Module* _pInfoModule,
52 void* _pModuleContext, ExternalTokens _externalTokens)
53 : pInfoModule(_pInfoModule),
54 pModuleContext(_pModuleContext),
55 externalTokens(_externalTokens)
56 { LIMITED_METHOD_CONTRACT; _ASSERTE(externalTokens != IllegalValue); }
57
58 Context(
59 Module* _pInfoModule,
60 Module* _pZapSigModule)
61 : pInfoModule(_pInfoModule),
62 pModuleContext((void*) _pZapSigModule),
63 externalTokens(NormalTokens)
64 { }
65 };
66
67public:
68
69 ZapSig(
70 Module * _pInfoModule,
71 void * _pModuleContext,
72 ExternalTokens _externalTokens,
73 EncodeModuleCallback _pfnEncodeModule,
74 TokenDefinitionCallback _pfnTokenDefinition)
75
76 : context(_pInfoModule, _pModuleContext, _externalTokens),
77 pfnEncodeModule(_pfnEncodeModule),
78 pfnTokenDefinition(_pfnTokenDefinition)
79 {}
80
81#ifdef FEATURE_PREJIT
82
83 // Instance methods
84
85 // Create a signature for a typeHandle
86 // It can be decoded using MetaSig::GetTypeHandleThrowing
87 // The tokens are espressed relative to this->pInfoModule
88 // When (handle.GetModule() != this->pInfoModule), we escape
89 // the signature with ELEMENT_TYPE_MODULE_ZAPSIG <id-num>
90 // followed by a <token> to encode a temporary change of module
91 // For Ibc Signatures the <token> is one of the ibc defined tokens
92 // For Ngen Fixup signatures the <token> is for the external module
93 //
94 BOOL GetSignatureForTypeHandle(TypeHandle typeHandle,
95 SigBuilder * pSigBuilder);
96
97 // Static methods
98
99 // Compare a type handle with a signature whose tokens are resolved with respect to pModule
100 // pZapSigContext is used to resolve ELEMENT_TYPE_MODULE_ZAPSIG encodings
101 static BOOL CompareSignatureToTypeHandle(PCCOR_SIGNATURE pSig,
102 Module* pModule,
103 TypeHandle handle,
104 const ZapSig::Context * pZapSigContext);
105
106 // Compare a type handle with a tagged pointer. Ensure that the common path is inlined into the caller.
107 static FORCEINLINE BOOL CompareTaggedPointerToTypeHandle(Module * pModule, TADDR addr, TypeHandle handle)
108 {
109 WRAPPER_NO_CONTRACT;
110 if (handle.AsTAddr() == addr)
111 return TRUE;
112 if (!CORCOMPILE_IS_POINTER_TAGGED(addr))
113 return FALSE;
114 return CompareFixupToTypeHandle(pModule, addr, handle);
115 }
116
117 static BOOL CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle);
118
119 static BOOL CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2);
120
121private:
122 BOOL GetSignatureForTypeDesc(TypeDesc * desc, SigBuilder * pSigBuilder);
123
124 // Returns element type when the typeHandle can be encoded using
125 // using a single CorElementType value
126 // This includes using ELEMENT_TYPE_CANON_ZAPSIG for the System.__Canon type
127 //
128 static CorElementType TryEncodeUsingShortcut(/* in */ MethodTable * pMT);
129
130#endif // FEATURE_PREJIT
131
132private:
133
134 ZapSig::Context context;
135
136 EncodeModuleCallback pfnEncodeModule; // Function Pointer to the EncodeModuleHelper
137 TokenDefinitionCallback pfnTokenDefinition; // Function Pointer to the DefineTokenHelper
138
139public:
140 //--------------------------------------------------------------------
141 // Static helper encode/decode helper methods
142
143 static Module *DecodeModuleFromIndex(Module *fromModule,
144 DWORD index);
145
146 static Module *DecodeModuleFromIndexIfLoaded(Module *fromModule,
147 DWORD index);
148
149 // referencingModule is the module that references the type.
150 // fromModule is the module in which the type is defined.
151 // pBuffer contains the signature encoding for the type.
152 // level is the class load level (see classloadlevel.h) to which the type should be loaded
153 static TypeHandle DecodeType(
154 Module *referencingModule,
155 Module *fromModule,
156 PCCOR_SIGNATURE pBuffer,
157 ClassLoadLevel level = CLASS_LOADED);
158
159 static MethodDesc *DecodeMethod(
160 Module *referencingModule,
161 Module *fromModule,
162 PCCOR_SIGNATURE pBuffer,
163 TypeHandle *ppTH = NULL);
164
165 static MethodDesc *DecodeMethod(
166 Module *referencingModule,
167 Module *fromModule,
168 PCCOR_SIGNATURE pBuffer,
169 SigTypeContext *pContext,
170 TypeHandle *ppTH = NULL,
171 PCCOR_SIGNATURE *ppOwnerTypeSpecWithVars = NULL,
172 PCCOR_SIGNATURE *ppMethodSpecWithVars = NULL);
173
174 static FieldDesc *DecodeField(
175 Module *referencingModule,
176 Module *fromModule,
177 PCCOR_SIGNATURE pBuffer,
178 TypeHandle *ppTH = NULL);
179
180 static FieldDesc *DecodeField(
181 Module *pReferencingModule,
182 Module *pInfoModule,
183 PCCOR_SIGNATURE pBuffer,
184 SigTypeContext *pContext,
185 TypeHandle *ppTH = NULL);
186
187 static BOOL EncodeMethod(
188 MethodDesc *pMethod,
189 Module *pInfoModule,
190 SigBuilder *pSigBuilder,
191 LPVOID pReferencingModule,
192 ENCODEMODULE_CALLBACK pfnEncodeModule,
193 DEFINETOKEN_CALLBACK pfnDefineToken,
194 CORINFO_RESOLVED_TOKEN *pResolvedToken = NULL,
195 CORINFO_RESOLVED_TOKEN *pConstrainedResolvedToken = NULL,
196 BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE);
197
198 static void EncodeField(
199 FieldDesc *pField,
200 Module *pInfoModule,
201 SigBuilder *pSigBuilder,
202 LPVOID pReferencingModule,
203 ENCODEMODULE_CALLBACK pfnEncodeModule,
204 CORINFO_RESOLVED_TOKEN *pResolvedToken = NULL,
205 BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE);
206
207};
208
209#endif // ZAPGSIG_H
210