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 "ildasmpch.h"
6
7#include <metadata.h>
8#include <utilcode.h>
9#include "debugmacros.h"
10#include "dasm_sz.h"
11#include "ceeload.h"
12
13extern PELoader *g_pPELoader;
14
15unsigned SizeOfValueType(mdToken tk, IMDInternalImport* pImport)
16{
17 unsigned ret = 0xFFFFFFFF;
18 if((TypeFromToken(tk)==mdtTypeDef)&&RidFromToken(tk)&&pImport)
19 {
20 DWORD dwAttrs;
21 mdToken tkExtends;
22 if (FAILED(pImport->GetTypeDefProps(tk, &dwAttrs, &tkExtends)))
23 {
24 return ret;
25 }
26 if(!(IsTdInterface(dwAttrs)||IsTdAbstract(dwAttrs)||IsTdImport(dwAttrs)))
27 {
28 mdToken tkField;
29 DWORD dwFieldAttrs;
30 unsigned uFieldSize;
31 ULONG ulPack=0,
32 ulSize = 0,
33 ulInstFieldSize = 0;
34
35 if (FAILED(pImport->GetClassPackSize(tk,&ulPack))) ulPack = 0;
36 if (FAILED(pImport->GetClassTotalSize(tk,&ulSize))) ulSize = 0;
37
38 if (IsTdExplicitLayout(dwAttrs))
39 {
40 MD_CLASS_LAYOUT hLayout;
41 if (SUCCEEDED(pImport->GetClassLayoutInit(tk,&hLayout)))
42 {
43 ULONG ulOffset;
44 while (SUCCEEDED(pImport->GetClassLayoutNext(&hLayout,&tkField,&ulOffset)) && RidFromToken(tkField))
45 {
46 if (FAILED(pImport->GetFieldDefProps(tkField, &dwFieldAttrs)))
47 {
48 break;
49 }
50 if (!(IsFdStatic(dwFieldAttrs)||IsFdLiteral(dwFieldAttrs)))
51 {
52 uFieldSize = SizeOfField(tkField,pImport);
53 if (uFieldSize == 0xFFFFFFFF) return uFieldSize;
54 uFieldSize += ulOffset;
55 if (uFieldSize > ulInstFieldSize) ulInstFieldSize = uFieldSize;
56 }
57 }
58 }
59 }
60 else
61 {
62 HENUMInternal hEnumField;
63 unsigned cFieldsMax = 0;
64 if (SUCCEEDED(pImport->EnumInit(mdtFieldDef, tk, &hEnumField)))
65 {
66 if ((cFieldsMax = pImport->EnumGetCount(&hEnumField)) != 0)
67 {
68 while (pImport->EnumNext(&hEnumField, &tkField) && RidFromToken(tkField))
69 {
70 if (FAILED(pImport->GetFieldDefProps(tkField, &dwFieldAttrs)))
71 {
72 break;
73 }
74 if (!IsFdStatic(dwFieldAttrs) && !IsFdLiteral(dwFieldAttrs))
75 {
76 uFieldSize = SizeOfField(tkField,pImport);
77 if (uFieldSize == 0xFFFFFFFF) return uFieldSize;
78 if (ulPack > 1)
79 {
80 ULONG ulDelta = ulInstFieldSize % ulPack;
81 if (ulDelta != 0) ulInstFieldSize += ulPack - ulDelta;
82 }
83 ulInstFieldSize += uFieldSize;
84 }
85 }
86 }
87 pImport->EnumClose(&hEnumField);
88 }
89 }
90 ret = (ulInstFieldSize > ulSize) ? ulInstFieldSize : ulSize;
91 if(ret == 0) ret = 1; // zero-sized value types automatically get 1 byte
92 }
93 }
94 return ret;
95}
96
97unsigned SizeOfField(mdToken tk, IMDInternalImport* pImport)
98{
99 unsigned ret = 0xFFFFFFFF;
100 if((TypeFromToken(tk) == mdtFieldDef) && RidFromToken(tk) && pImport)
101 {
102 PCCOR_SIGNATURE pSig;
103 ULONG cSig;
104 if (FAILED(pImport->GetSigOfFieldDef(tk, &cSig, &pSig)))
105 {
106 return ret;
107 }
108 ret = SizeOfField(&pSig,cSig,pImport);
109 }
110 return ret;
111}
112
113unsigned SizeOfField(PCCOR_SIGNATURE *ppSig, ULONG cSig, IMDInternalImport* pImport)
114{
115 unsigned ret = 0xFFFFFFFF;
116 if(ppSig && *ppSig && cSig && pImport)
117 {
118 unsigned callConv = CorSigUncompressData(*ppSig);
119 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
120 {
121 mdToken tk;
122 int typ;
123 BOOL Reiterate;
124 unsigned uElementNumber = 1;
125 PCCOR_SIGNATURE pSigStart = *ppSig;
126 PCCOR_SIGNATURE pSigEnd = *ppSig+cSig;
127
128 // Size of the pointer depends on bitness of the assembly
129 unsigned nSizeOfPointer = g_pPELoader->IsPE32() ? 4 : 8;
130
131 do {
132 Reiterate = FALSE;
133 switch(typ = *(*ppSig)++) {
134 case ELEMENT_TYPE_VOID :
135 return 0;
136
137 case ELEMENT_TYPE_I1 :
138 case ELEMENT_TYPE_U1 :
139 case ELEMENT_TYPE_BOOLEAN :
140 return uElementNumber;
141
142 case ELEMENT_TYPE_CHAR :
143 case ELEMENT_TYPE_I2 :
144 case ELEMENT_TYPE_U2 :
145 return (uElementNumber << 1);
146
147 case ELEMENT_TYPE_I4 :
148 case ELEMENT_TYPE_U4 :
149 case ELEMENT_TYPE_R4 :
150 return (uElementNumber << 2);
151
152 case ELEMENT_TYPE_I8 :
153 case ELEMENT_TYPE_U8 :
154 case ELEMENT_TYPE_R8 :
155 return (uElementNumber << 3);
156
157 case ELEMENT_TYPE_OBJECT :
158 case ELEMENT_TYPE_STRING :
159 case ELEMENT_TYPE_FNPTR :
160 case ELEMENT_TYPE_CLASS :
161 case ELEMENT_TYPE_PTR :
162 case ELEMENT_TYPE_BYREF :
163 //case ELEMENT_TYPE_VAR :
164 case ELEMENT_TYPE_U :
165 case ELEMENT_TYPE_I :
166 return (uElementNumber * nSizeOfPointer);
167
168 case ELEMENT_TYPE_TYPEDBYREF : // pair of ptrs
169 return (uElementNumber * nSizeOfPointer * 2);
170
171 case ELEMENT_TYPE_VALUETYPE :
172 *ppSig += CorSigUncompressToken(*ppSig, &tk);
173 ret = SizeOfValueType(tk,pImport);
174 if(ret != 0xFFFFFFFF) ret *= uElementNumber;
175 return ret;
176
177 // Modifiers or depedant types
178
179 case ELEMENT_TYPE_ARRAY :
180 ret = SizeOfField(ppSig, cSig-(unsigned)((*ppSig)-pSigStart), pImport);
181 if(ret != 0xFFFFFFFF)
182 {
183 unsigned rank = CorSigUncompressData(*ppSig);
184 if (rank == 0) ret = 0xFFFFFFFF;
185 else
186 {
187 int* lowerBounds = new (nothrow) int[2*rank];
188 int* sizes = &lowerBounds[rank];
189 memset(lowerBounds, 0, sizeof(int)*2*rank);
190
191 unsigned numSizes = CorSigUncompressData(*ppSig);
192 _ASSERTE(numSizes <= rank);
193 unsigned i;
194 for(i =0; i < numSizes; i++)
195 sizes[i] = CorSigUncompressData(*ppSig);
196
197 unsigned numLowBounds = CorSigUncompressData(*ppSig);
198 _ASSERTE(numLowBounds <= rank);
199 for(i = 0; i < numLowBounds; i++)
200 *ppSig+=CorSigUncompressSignedInt(*ppSig,&lowerBounds[i]);
201
202 for(i = 0; i < numSizes; i++)
203 {
204 if (sizes[i]) uElementNumber *= sizes[i];
205 }
206 ret *= uElementNumber;
207 delete[] lowerBounds;
208 }
209 }
210 return ret;
211
212 case ELEMENT_TYPE_CMOD_OPT :
213 case ELEMENT_TYPE_CMOD_REQD :
214 *ppSig += CorSigUncompressToken(*ppSig, &tk);
215 case ELEMENT_TYPE_PINNED :
216 case ELEMENT_TYPE_SZARRAY : // uElementNumber doesn't change
217 if(*ppSig < pSigEnd) Reiterate = TRUE;
218 break;
219
220 default:
221 case ELEMENT_TYPE_SENTINEL :
222 case ELEMENT_TYPE_END :
223 break;
224 } // end switch
225 } while(Reiterate);
226 } // end if(CALLCONV_FIELD)
227 } // end if(signature && import)
228 return ret;
229}
230