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 | |
13 | extern PELoader *g_pPELoader; |
14 | |
15 | unsigned 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 | |
97 | unsigned 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 | |
113 | unsigned 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 | |