Fix trigger for tier 1 call counting delay (#17477)
[platform/upstream/coreclr.git] / src / binder / clrprivbindercoreclr.cpp
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 #include "common.h"
6 #include "assemblybinder.hpp"
7 #include "clrprivbindercoreclr.h"
8 #include "clrprivbinderutil.h"
9
10 using namespace BINDER_SPACE;
11
12 //=============================================================================
13 // Helper functions
14 //-----------------------------------------------------------------------------
15
16 HRESULT CLRPrivBinderCoreCLR::BindAssemblyByNameWorker(BINDER_SPACE::AssemblyName *pAssemblyName,
17                                                        BINDER_SPACE::Assembly **ppCoreCLRFoundAssembly,
18                                                        bool excludeAppPaths)
19 {
20     VALIDATE_ARG_RET(pAssemblyName != nullptr && ppCoreCLRFoundAssembly != nullptr);
21     HRESULT hr = S_OK;
22     
23 #ifdef _DEBUG
24     // MSCORLIB should be bound using BindToSystem
25     _ASSERTE(!pAssemblyName->IsMscorlib());
26 #endif
27
28     hr = AssemblyBinder::BindAssembly(&m_appContext,
29                                       pAssemblyName,
30                                       NULL,
31                                       NULL,
32                                       FALSE, //fNgenExplicitBind,
33                                       FALSE, //fExplicitBindToNativeImage,
34                                       excludeAppPaths,
35                                       ppCoreCLRFoundAssembly);
36     if (!FAILED(hr))
37     {
38         (*ppCoreCLRFoundAssembly)->SetBinder(this);
39     }
40     
41     return hr;
42 }
43
44 // ============================================================================
45 // CLRPrivBinderCoreCLR implementation
46 // ============================================================================
47 HRESULT CLRPrivBinderCoreCLR::BindAssemblyByName(IAssemblyName     *pIAssemblyName,
48                                                  ICLRPrivAssembly **ppAssembly)
49 {
50     HRESULT hr = S_OK;
51     VALIDATE_ARG_RET(pIAssemblyName != nullptr && ppAssembly != nullptr);
52     
53     EX_TRY
54     {
55         *ppAssembly = nullptr;
56
57         ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly;
58         ReleaseHolder<AssemblyName> pAssemblyName;
59
60         SAFE_NEW(pAssemblyName, AssemblyName);
61         IF_FAIL_GO(pAssemblyName->Init(pIAssemblyName));
62         
63         hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, false /* excludeAppPaths */);
64
65 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
66         if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) ||
67             (hr == FUSION_E_APP_DOMAIN_LOCKED) || (hr == FUSION_E_REF_DEF_MISMATCH))
68         {
69             // If we are here, one of the following is possible:
70             //
71             // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR
72             // 2) An assembly with the same simple name was already loaded in the context of the current binder but we ran into a Ref/Def
73             //    mismatch (either due to version difference or strong-name difference).
74             //
75             // Thus, if default binder has been overridden, then invoke it in an attempt to perform the binding for it make the call
76             // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly
77             // that has been loaded.
78
79             // Attempt to resolve the assembly via managed TPA ALC instance if one exists
80             INT_PTR pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext();
81             if (pManagedAssemblyLoadContext != NULL)
82             {
83               hr = AssemblyBinder::BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, pAssemblyName, pIAssemblyName, 
84               NULL, &pCoreCLRFoundAssembly);
85               if (SUCCEEDED(hr))
86               {
87                   // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance.
88                   // In such a case, we will not overwrite the binding context (which would be wrong since it would not
89                   // be present in the cache of the current binding context).
90                   if (pCoreCLRFoundAssembly->GetBinder() == NULL)
91                   {
92                       pCoreCLRFoundAssembly->SetBinder(this);
93                   }
94               }
95             }
96         }
97 #endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
98         
99         IF_FAIL_GO(hr);
100
101         *ppAssembly = pCoreCLRFoundAssembly.Extract();
102
103 Exit:;        
104     }
105     EX_CATCH_HRESULT(hr);
106
107     return hr;
108 }
109
110 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
111 HRESULT CLRPrivBinderCoreCLR::BindUsingPEImage( /* in */ PEImage *pPEImage, 
112                                                             /* in */ BOOL fIsNativeImage, 
113                                                             /* [retval][out] */ ICLRPrivAssembly **ppAssembly)
114 {
115     HRESULT hr = S_OK;
116
117     EX_TRY
118     {
119         ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly;
120         ReleaseHolder<BINDER_SPACE::AssemblyName> pAssemblyName;        
121         ReleaseHolder<IMDInternalImport> pIMetaDataAssemblyImport;
122         
123         PEKIND PeKind = peNone;
124         
125         // Get the Metadata interface
126         DWORD dwPAFlags[2];
127         IF_FAIL_GO(BinderAcquireImport(pPEImage, &pIMetaDataAssemblyImport, dwPAFlags, fIsNativeImage));
128         IF_FAIL_GO(AssemblyBinder::TranslatePEToArchitectureType(dwPAFlags, &PeKind));
129         
130         _ASSERTE(pIMetaDataAssemblyImport != NULL);
131         
132         // Using the information we just got, initialize the assemblyname
133         SAFE_NEW(pAssemblyName, AssemblyName);
134         IF_FAIL_GO(pAssemblyName->Init(pIMetaDataAssemblyImport, PeKind));
135         
136         // Validate architecture
137         if (!BINDER_SPACE::Assembly::IsValidArchitecture(pAssemblyName->GetArchitecture()))
138         {
139             IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
140         }
141         
142         // Ensure we are not being asked to bind to a TPA assembly
143         //
144         // Easy out for mscorlib
145         if (pAssemblyName->IsMscorlib())
146         {
147             IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
148         }
149
150         {
151             SString& simpleName = pAssemblyName->GetSimpleName();
152             SimpleNameToFileNameMap * tpaMap = GetAppContext()->GetTpaList();
153             if (tpaMap->LookupPtr(simpleName.GetUnicode()) != NULL)
154             {
155                 // The simple name of the assembly being requested to be bound was found in the TPA list.
156                 // Now, perform the actual bind to see if the assembly was really in the TPA assembly list or not.
157                 hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */);
158                 if (SUCCEEDED(hr))
159                 {
160                     if (pCoreCLRFoundAssembly->GetIsInGAC())
161                     {
162                         *ppAssembly = pCoreCLRFoundAssembly.Extract();
163                         goto Exit;                        
164                     }
165                 }
166             }
167             
168             hr = AssemblyBinder::BindUsingPEImage(&m_appContext, pAssemblyName, pPEImage, PeKind, pIMetaDataAssemblyImport, &pCoreCLRFoundAssembly);
169             if (hr == S_OK)
170             {
171                 _ASSERTE(pCoreCLRFoundAssembly != NULL);
172                 pCoreCLRFoundAssembly->SetBinder(this);
173                 *ppAssembly = pCoreCLRFoundAssembly.Extract();
174             }
175         }
176 Exit:;        
177     }
178     EX_CATCH_HRESULT(hr);
179
180     return hr;
181 }
182 #endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
183
184 HRESULT CLRPrivBinderCoreCLR::VerifyBind(IAssemblyName        *AssemblyName,
185                                          ICLRPrivAssembly     *pAssembly,
186                                          ICLRPrivAssemblyInfo *pAssemblyInfo)
187 {
188     return E_FAIL;
189 }
190          
191 HRESULT CLRPrivBinderCoreCLR::GetBinderFlags(DWORD *pBinderFlags)
192 {
193     if (pBinderFlags == NULL)
194         return E_INVALIDARG;
195     *pBinderFlags = BINDER_NONE;
196     return S_OK;
197 }
198          
199 HRESULT CLRPrivBinderCoreCLR::GetBinderID( 
200         UINT_PTR *pBinderId)
201 {
202     *pBinderId = reinterpret_cast<UINT_PTR>(this); 
203     return S_OK;
204 }
205          
206 HRESULT CLRPrivBinderCoreCLR::FindAssemblyBySpec( 
207             LPVOID pvAppDomain,
208             LPVOID pvAssemblySpec,
209             HRESULT *pResult,
210             ICLRPrivAssembly **ppAssembly)
211 {
212     // We are not using a cache at this level
213     // However, assemblies bound by the CoreCLR binder is already cached in the
214     // AppDomain and will be resolved from there if required
215     return E_FAIL;
216 }
217
218 HRESULT CLRPrivBinderCoreCLR::SetupBindingPaths(SString  &sTrustedPlatformAssemblies,
219                                                 SString  &sPlatformResourceRoots,
220                                                 SString  &sAppPaths,
221                                                 SString  &sAppNiPaths)
222 {
223     HRESULT hr = S_OK;
224     
225     EX_TRY
226     {
227         hr = m_appContext.SetupBindingPaths(sTrustedPlatformAssemblies, sPlatformResourceRoots, sAppPaths, sAppNiPaths, TRUE /* fAcquireLock */);
228     }
229     EX_CATCH_HRESULT(hr);
230     return hr;
231 }
232
233 bool CLRPrivBinderCoreCLR::IsInTpaList(const SString &sFileName)
234 {
235     bool fIsFileOnTpaList = false;
236     
237     TpaFileNameHash * tpaFileNameMap = m_appContext.GetTpaFileNameList();
238     if (tpaFileNameMap != nullptr)
239     {
240         const FileNameMapEntry *pTpaEntry = tpaFileNameMap->LookupPtr(sFileName.GetUnicode());
241         fIsFileOnTpaList = (pTpaEntry != nullptr);
242     }
243     
244     return fIsFileOnTpaList;
245 }
246
247 // See code:BINDER_SPACE::AssemblyBinder::GetAssembly for info on fNgenExplicitBind
248 // and fExplicitBindToNativeImage, and see code:CEECompileInfo::LoadAssemblyByPath
249 // for an example of how they're used.
250 HRESULT CLRPrivBinderCoreCLR::Bind(SString           &assemblyDisplayName,
251                                    LPCWSTR            wszCodeBase,
252                                    PEAssembly        *pParentAssembly,
253                                    BOOL               fNgenExplicitBind,
254                                    BOOL               fExplicitBindToNativeImage,
255                                    ICLRPrivAssembly **ppAssembly)
256 {
257     HRESULT hr = S_OK;
258     VALIDATE_ARG_RET(ppAssembly != NULL);
259
260     AssemblyName assemblyName;
261     
262     ReleaseHolder<AssemblyName> pAssemblyName;
263     
264     if (!assemblyDisplayName.IsEmpty())
265     {
266         // AssemblyDisplayName can be empty if wszCodeBase is specified.
267         SAFE_NEW(pAssemblyName, AssemblyName);
268         IF_FAIL_GO(pAssemblyName->Init(assemblyDisplayName));
269     }
270     
271     EX_TRY
272     {
273         ReleaseHolder<BINDER_SPACE::Assembly> pAsm;
274         hr = AssemblyBinder::BindAssembly(&m_appContext,
275                                           pAssemblyName,
276                                           wszCodeBase,
277                                           pParentAssembly,
278                                           fNgenExplicitBind,
279                                           fExplicitBindToNativeImage,
280                                           false, // excludeAppPaths
281                                           &pAsm);
282         if(SUCCEEDED(hr))
283         {
284             _ASSERTE(pAsm != NULL);
285             pAsm->SetBinder(this);
286             *ppAssembly = pAsm.Extract();
287         }
288     }
289     EX_CATCH_HRESULT(hr);
290     
291 Exit:    
292     return hr;
293 }
294
295 #ifndef CROSSGEN_COMPILE
296 HRESULT CLRPrivBinderCoreCLR::PreBindByteArray(PEImage  *pPEImage, BOOL fInspectionOnly)
297 {
298     HRESULT hr = S_OK;
299     VALIDATE_ARG_RET(pPEImage != NULL);
300
301     EX_TRY
302     {
303         hr = AssemblyBinder::PreBindByteArray(&m_appContext, pPEImage, fInspectionOnly);
304     }
305     EX_CATCH_HRESULT(hr);
306     
307     return hr;
308 }
309 #endif // CROSSGEN_COMPILE