Fix trigger for tier 1 call counting delay (#17477)
[platform/upstream/coreclr.git] / src / binder / assembly.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 //
6 // Assembly.cpp
7 //
8
9
10 //
11 // Implements the Assembly class
12 //
13 // ============================================================
14 #include "common.h"
15 #include "clrprivbinderutil.h"
16 #include "assembly.hpp"
17 #include "utils.hpp"
18
19 namespace BINDER_SPACE
20 {
21     namespace
22     {
23         BOOL IsPlatformArchicture(PEKIND kArchitecture)
24         {
25             return ((kArchitecture != peMSIL) && (kArchitecture != peNone));
26         }
27
28         HRESULT GetAssemblyRefTokens(IMDInternalImport        *pMDImport,
29                                      mdAssembly              **ppAssemblyRefTokens,
30                                      DWORD                    *pdwCAssemblyRefTokens)
31         {
32             HRESULT hr = S_OK;
33
34             _ASSERTE(pMDImport != NULL);
35             _ASSERTE(ppAssemblyRefTokens != NULL);
36             _ASSERTE(pdwCAssemblyRefTokens != NULL);
37
38             mdAssembly *pAssemblyRefTokens = NULL;
39             COUNT_T assemblyRefCount;
40             
41             HENUMInternalHolder hEnumAssemblyRef(pMDImport);
42             IF_FAIL_GO(hEnumAssemblyRef.EnumInitNoThrow(mdtAssemblyRef, mdTokenNil));
43             
44             assemblyRefCount = hEnumAssemblyRef.EnumGetCount();
45
46             pAssemblyRefTokens = new (nothrow) mdAssemblyRef[assemblyRefCount];
47             if (pAssemblyRefTokens == NULL)
48             {
49                 IF_FAIL_GO(E_OUTOFMEMORY);
50             }
51             ZeroMemory(pAssemblyRefTokens, assemblyRefCount * sizeof(mdAssemblyRef));
52
53             for (COUNT_T i = 0; i < assemblyRefCount; i++)
54             {
55                 bool ret = hEnumAssemblyRef.EnumNext(&(pAssemblyRefTokens[i]));
56                 _ASSERTE(ret);
57             }
58
59             *ppAssemblyRefTokens = pAssemblyRefTokens;
60             pAssemblyRefTokens = NULL;
61
62             *pdwCAssemblyRefTokens= assemblyRefCount;
63             hr = S_OK;
64     
65 Exit:
66             SAFE_DELETE_ARRAY(pAssemblyRefTokens);    
67
68             return hr;
69         }
70     };
71
72     STDMETHODIMP Assembly::QueryInterface(REFIID   riid,
73                                           void   **ppv)
74     {
75         HRESULT hr = S_OK;
76
77         if (ppv == NULL)
78         {
79             hr = E_POINTER;
80         }    
81         else
82         {
83             if (IsEqualIID(riid, IID_IUnknown))
84             {
85                 AddRef();
86                 *ppv = static_cast<IUnknown *>(this);
87             }
88             else
89             {
90                 *ppv = NULL;
91                 hr = E_NOINTERFACE;
92             }
93         }
94
95         return hr;
96     }
97
98     STDMETHODIMP_(ULONG) Assembly::AddRef()
99     {
100         return InterlockedIncrement(&m_cRef);
101     }
102
103     STDMETHODIMP_(ULONG) Assembly::Release()
104     {
105         ULONG ulRef = InterlockedDecrement(&m_cRef);
106
107         if (ulRef == 0) 
108         {
109             delete this;
110         }
111
112         return ulRef;
113     }
114
115     Assembly::Assembly()
116     {
117         m_cRef = 1;
118         m_pPEImage = NULL;
119         m_pNativePEImage = NULL;
120         m_pAssemblyName = NULL;
121         m_pMDImport = NULL;
122         m_pAssemblyRefTokens = NULL;
123         m_dwCAssemblyRefTokens = static_cast<DWORD>(-1);
124         m_dwAssemblyFlags = FLAG_NONE;
125         m_pBinder = NULL;
126     }
127
128     Assembly::~Assembly()
129     {
130         BINDER_LOG_ASSEMBLY_NAME(L"destructing assembly", m_pAssemblyName);
131
132         if (m_pPEImage != NULL)
133         {
134             BinderReleasePEImage(m_pPEImage);
135             m_pPEImage = NULL;
136         }
137
138 #ifdef  FEATURE_PREJIT
139         if (m_pNativePEImage != NULL)
140         {
141             BinderReleasePEImage(m_pNativePEImage);
142             m_pNativePEImage = NULL;
143         }
144 #endif
145
146         SAFE_RELEASE(m_pAssemblyName);
147         SAFE_RELEASE(m_pMDImport);
148         SAFE_DELETE_ARRAY(m_pAssemblyRefTokens);
149     }
150
151     HRESULT Assembly::Init(
152                            IMDInternalImport       *pIMetaDataAssemblyImport,
153                            PEKIND                   PeKind,
154                            PEImage                 *pPEImage,
155                            PEImage                 *pNativePEImage,
156                            SString                 &assemblyPath,
157                            BOOL                     fInspectionOnly,
158                            BOOL                     fIsInGAC)
159     {
160         HRESULT hr = S_OK;
161         BINDER_LOG_ENTER(L"Assembly::Init");
162
163         ReleaseHolder<AssemblyName> pAssemblyName;
164         SAFE_NEW(pAssemblyName, AssemblyName);
165
166         // Get assembly name def from meta data import and store it for later refs access
167         IF_FAIL_GO(pAssemblyName->Init(pIMetaDataAssemblyImport, PeKind));
168         SetMDImport(pIMetaDataAssemblyImport);
169         if (!fIsInGAC)
170         {
171             GetPath().Set(assemblyPath);
172         }
173
174         BINDER_LOG_ASSEMBLY_NAME(L"AssemblyNameDef", pAssemblyName);
175         BINDER_LOG_STRING(L"System Architecture",
176                           AssemblyName::ArchitectureToString(GetSystemArchitecture()));
177
178         // Safe architecture for validation
179         PEKIND kAssemblyArchitecture;
180         kAssemblyArchitecture = pAssemblyName->GetArchitecture();
181         SetInspectionOnly(fInspectionOnly);
182         SetIsInGAC(fIsInGAC);
183         SetPEImage(pPEImage);
184         SetNativePEImage(pNativePEImage);
185         pAssemblyName->SetIsDefinition(TRUE);
186
187         // Now take ownership of assembly names
188         SetAssemblyName(pAssemblyName.Extract(), FALSE /* fAddRef */);
189
190         // Finally validate architecture
191         if (!fInspectionOnly && !IsValidArchitecture(kAssemblyArchitecture))
192         {
193             // Assembly image can't be executed on this platform
194             IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
195         }
196
197     Exit:
198         BINDER_LOG_LEAVE_HR(L"Assembly::Init", hr);
199         return hr;
200     }
201
202     HRESULT Assembly::GetMVID(GUID *pMVID)
203     {
204         // Zero init the GUID incase we fail
205         ZeroMemory(pMVID, sizeof(GUID));
206         
207         return m_pMDImport->GetScopeProps(NULL, pMVID);
208     }
209     
210     HRESULT Assembly::GetNextAssemblyNameRef(DWORD          nIndex,
211                                              AssemblyName **ppAssemblyName)
212     {
213         HRESULT hr = S_OK;
214         BINDER_LOG_ENTER(L"Assembly::GetNextAssemblyNameRef");
215
216         if (ppAssemblyName == NULL)
217         {
218             IF_FAIL_GO(E_INVALIDARG);
219         }
220         else if (GetNbAssemblyRefTokens() == static_cast<DWORD>(-1))
221         {
222             mdAssembly *pAssemblyRefTokens = NULL;
223             DWORD dwCAssemblyRefTokens = 0;
224
225             IF_FAIL_GO(BINDER_SPACE::GetAssemblyRefTokens(GetMDImport(),
226                                                           &pAssemblyRefTokens,
227                                                           &dwCAssemblyRefTokens));
228
229             if (InterlockedCompareExchangeT(&m_pAssemblyRefTokens,
230                                             pAssemblyRefTokens,
231                                             NULL))
232             {
233                 SAFE_DELETE_ARRAY(pAssemblyRefTokens);
234             }
235             SetNbAsssemblyRefTokens(dwCAssemblyRefTokens);
236         }
237
238         _ASSERTE(GetNbAssemblyRefTokens() != static_cast<DWORD>(-1));
239
240         // Verify input index
241         if (nIndex >= GetNbAssemblyRefTokens())
242         {
243             IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS));
244         }
245         else
246         {
247             ReleaseHolder<AssemblyName> pAssemblyName;
248
249             SAFE_NEW(pAssemblyName, AssemblyName);
250             IF_FAIL_GO(pAssemblyName->Init(GetMDImport(),
251                                            peNone,
252                                            GetAssemblyRefTokens()[nIndex],
253                                            FALSE /* fIsDefinition */));
254
255             *ppAssemblyName = pAssemblyName.Extract();
256         }
257
258     Exit:
259         BINDER_LOG_LEAVE_HR(L"Assembly::GetNextAssemblyNameRef", hr);
260         return hr;
261     }
262
263     /* static */
264     PEKIND Assembly::GetSystemArchitecture()
265     {
266 #if defined(_TARGET_X86_)
267         return peI386;
268 #elif defined(_TARGET_AMD64_) 
269         return peAMD64;
270 #elif defined(_TARGET_ARM_) 
271         return peARM;
272 #elif defined(_TARGET_ARM64_) 
273         return peARM64;
274 #else
275         PORTABILITY_ASSERT("Assembly::GetSystemArchitecture");
276 #endif
277     }
278     
279     /* static */
280     BOOL Assembly::IsValidArchitecture(PEKIND kArchitecture)
281     {
282         if (!IsPlatformArchicture(kArchitecture))
283             return TRUE;
284
285         return (kArchitecture == GetSystemArchitecture());
286     }
287     
288     // --------------------------------------------------------------------
289     // ICLRPrivAssembly methods
290     // --------------------------------------------------------------------
291     LPCWSTR Assembly::GetSimpleName() 
292     {
293         AssemblyName *pAsmName = GetAssemblyName();
294         return (pAsmName == nullptr ? nullptr : pAsmName->GetSimpleName());
295     }
296
297     HRESULT Assembly::BindAssemblyByName(IAssemblyName * pIAssemblyName, ICLRPrivAssembly ** ppAssembly)
298     {
299         return (m_pBinder == NULL) ? E_FAIL : m_pBinder->BindAssemblyByName(pIAssemblyName, ppAssembly);
300     }
301
302     HRESULT Assembly::FindAssemblyBySpec(
303                 LPVOID pvAppDomain,
304                 LPVOID pvAssemblySpec,
305                 HRESULT * pResult,
306                 ICLRPrivAssembly ** ppAssembly)
307     { 
308         return (m_pBinder == NULL) ? E_FAIL : m_pBinder->FindAssemblyBySpec(pvAppDomain, pvAssemblySpec, pResult, ppAssembly); 
309     }
310
311     HRESULT Assembly::VerifyBind (
312                 IAssemblyName * pIAssemblyName,
313                 ICLRPrivAssembly *pAssembly,
314                 ICLRPrivAssemblyInfo *pAssemblyInfo)
315     {
316         return (m_pBinder == NULL) ? E_FAIL : m_pBinder->VerifyBind(pIAssemblyName, pAssembly, pAssemblyInfo);
317     }
318
319     HRESULT Assembly::GetBinderID(UINT_PTR *pBinderId)
320     {
321         return (m_pBinder == NULL) ? E_FAIL : m_pBinder->GetBinderID(pBinderId);
322     }
323  
324     HRESULT Assembly::GetBinderFlags(DWORD *pBinderFlags)
325     {
326         return (m_pBinder == NULL) ? E_FAIL : m_pBinder->GetBinderFlags(pBinderFlags);
327     }
328
329     HRESULT Assembly::IsShareable(
330         BOOL * pbIsShareable)
331     {
332         if(pbIsShareable == nullptr)
333             return E_INVALIDARG;
334
335         *pbIsShareable = GetIsSharable();
336         return S_OK;
337     }
338
339     HRESULT Assembly::GetAvailableImageTypes(
340         LPDWORD pdwImageTypes)
341     {
342         HRESULT hr = E_FAIL;
343
344         if(pdwImageTypes == nullptr)
345             return E_INVALIDARG;
346
347         *pdwImageTypes = ASSEMBLY_IMAGE_TYPE_ASSEMBLY;
348
349         return S_OK;
350     }
351
352     HRESULT Assembly::GetImageResource(
353         DWORD dwImageType,
354         DWORD * pdwImageType,
355         ICLRPrivResource ** ppIResource)
356     {
357         HRESULT hr = S_OK;
358         if(ppIResource == nullptr)
359             return E_INVALIDARG;
360
361         if ((dwImageType & ASSEMBLY_IMAGE_TYPE_ASSEMBLY) == ASSEMBLY_IMAGE_TYPE_ASSEMBLY)
362         {
363             *ppIResource = clr::SafeAddRef(&m_clrPrivRes);
364             if (pdwImageType != nullptr)
365                 *pdwImageType = ASSEMBLY_IMAGE_TYPE_ASSEMBLY;
366         }
367         else
368         {
369             hr = CLR_E_BIND_IMAGE_UNAVAILABLE;
370         }
371         
372         return hr;
373     }
374
375     // get parent pointer from nested type
376     #define GetPThis() ((BINDER_SPACE::Assembly*)(((PBYTE)this) - offsetof(BINDER_SPACE::Assembly, m_clrPrivRes)))
377     
378     HRESULT Assembly::CLRPrivResourceAssembly::QueryInterface(REFIID riid, void ** ppv)
379     {
380         HRESULT hr = S_OK;
381         VALIDATE_ARG_RET(ppv != NULL);
382         
383         if (IsEqualIID(riid, IID_IUnknown))
384         {
385             AddRef();
386             *ppv = this;
387         }
388                 else if (IsEqualIID(riid, __uuidof(ICLRPrivResource)))
389                 {
390                         AddRef();
391                         // upcasting is safe
392                         *ppv = static_cast<ICLRPrivResource *>(this);
393                 }
394         else if (IsEqualIID(riid, __uuidof(ICLRPrivResourceAssembly)))
395         {
396             AddRef();
397             *ppv = static_cast<ICLRPrivResourceAssembly *>(this);
398         }
399         else
400         {
401             *ppv = NULL;
402             hr = E_NOINTERFACE;
403         }
404         
405         return hr;
406     }
407  
408     ULONG Assembly::CLRPrivResourceAssembly::AddRef()
409     {
410         return GetPThis()->AddRef();
411     }
412
413     ULONG Assembly::CLRPrivResourceAssembly::Release()
414     {
415         return GetPThis()->Release();
416     }
417
418     HRESULT Assembly::CLRPrivResourceAssembly::GetResourceType(IID *pIID)
419     {
420         VALIDATE_ARG_RET(pIID != nullptr);
421         *pIID = __uuidof(ICLRPrivResourceAssembly);
422         return S_OK;
423     }
424     
425     HRESULT Assembly::CLRPrivResourceAssembly::GetAssembly(LPVOID *ppAssembly)
426     {
427         VALIDATE_ARG_RET(ppAssembly != nullptr);
428         AddRef();
429         *ppAssembly = GetPThis();
430         return S_OK; 
431     }
432     
433 }
434