[cil-strip] Upgrade to latest Mono.Cecil API
[mono.git] / mcs / tools / cil-strip / Mono.Cecil / AggressiveReflectionReader.cs
1 //
2 // AggressiveRefletionReader.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2005 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 namespace Mono.Cecil {
30
31         using System;
32
33         using Mono.Cecil.Metadata;
34         using Mono.Cecil.Signatures;
35
36         internal sealed class AggressiveReflectionReader : ReflectionReader {
37
38                 public AggressiveReflectionReader (ModuleDefinition module) : base (module)
39                 {
40                 }
41
42                 public override void VisitTypeDefinitionCollection (TypeDefinitionCollection types)
43                 {
44                         base.VisitTypeDefinitionCollection (types);
45
46                         ReadGenericParameterConstraints ();
47                         ReadClassLayoutInfos ();
48                         ReadFieldLayoutInfos ();
49                         ReadPInvokeInfos ();
50                         ReadProperties ();
51                         ReadEvents ();
52                         ReadSemantics ();
53                         ReadInterfaces ();
54                         ReadOverrides ();
55                         ReadSecurityDeclarations ();
56                         ReadCustomAttributes ();
57                         ReadConstants ();
58                         ReadExternTypes ();
59                         ReadMarshalSpecs ();
60                         ReadInitialValues ();
61
62                         m_events = null;
63                         m_properties = null;
64                         m_parameters = null;
65                 }
66
67                 void ReadGenericParameterConstraints ()
68                 {
69                         if (!m_tHeap.HasTable (GenericParamConstraintTable.RId))
70                                 return;
71
72                         GenericParamConstraintTable gpcTable = m_tableReader.GetGenericParamConstraintTable ();
73                         for (int i = 0; i < gpcTable.Rows.Count; i++) {
74                                 GenericParamConstraintRow gpcRow = gpcTable [i];
75                                 GenericParameter gp = GetGenericParameterAt (gpcRow.Owner);
76
77                                 gp.Constraints.Add (GetTypeDefOrRef (gpcRow.Constraint, new GenericContext (gp.Owner)));
78                         }
79                 }
80
81                 void ReadClassLayoutInfos ()
82                 {
83                         if (!m_tHeap.HasTable (ClassLayoutTable.RId))
84                                 return;
85
86                         ClassLayoutTable clTable = m_tableReader.GetClassLayoutTable ();
87                         for (int i = 0; i < clTable.Rows.Count; i++) {
88                                 ClassLayoutRow clRow = clTable [i];
89                                 TypeDefinition type = GetTypeDefAt (clRow.Parent);
90                                 type.PackingSize = clRow.PackingSize;
91                                 type.ClassSize = clRow.ClassSize;
92                         }
93                 }
94
95                 void ReadFieldLayoutInfos ()
96                 {
97                         if (!m_tHeap.HasTable (FieldLayoutTable.RId))
98                                 return;
99
100                         FieldLayoutTable flTable = m_tableReader.GetFieldLayoutTable ();
101                         for (int i = 0; i < flTable.Rows.Count; i++) {
102                                 FieldLayoutRow flRow = flTable [i];
103                                 FieldDefinition field = GetFieldDefAt (flRow.Field);
104                                 field.Offset = flRow.Offset;
105                         }
106                 }
107
108                 void ReadPInvokeInfos ()
109                 {
110                         if (!m_tHeap.HasTable (ImplMapTable.RId))
111                                 return;
112
113                         ImplMapTable imTable = m_tableReader.GetImplMapTable ();
114                         for (int i = 0; i < imTable.Rows.Count; i++) {
115                                 ImplMapRow imRow = imTable [i];
116                                 if (imRow.MemberForwarded.TokenType == TokenType.Method) { // should always be true
117                                         MethodDefinition meth = GetMethodDefAt (imRow.MemberForwarded.RID);
118                                         meth.PInvokeInfo = new PInvokeInfo (
119                                                 meth, imRow.MappingFlags, MetadataRoot.Streams.StringsHeap [imRow.ImportName],
120                                                 Module.ModuleReferences [(int) imRow.ImportScope - 1]);
121                                 }
122                         }
123                 }
124
125                 void ReadProperties ()
126                 {
127                         if (!m_tHeap.HasTable (PropertyTable.RId)) {
128                                 m_properties = new PropertyDefinition [0];
129                                 return;
130                         }
131
132                         PropertyTable propsTable = m_tableReader.GetPropertyTable ();
133                         PropertyMapTable pmapTable = m_tableReader.GetPropertyMapTable ();
134                         m_properties = new PropertyDefinition [propsTable.Rows.Count];
135                         for (int i = 0; i < pmapTable.Rows.Count; i++) {
136                                 PropertyMapRow pmapRow = pmapTable [i];
137                                 if (pmapRow.Parent == 0)
138                                         continue;
139
140                                 TypeDefinition owner = GetTypeDefAt (pmapRow.Parent);
141
142                                 GenericContext context = new GenericContext (owner);
143
144                                 int start = (int) pmapRow.PropertyList, last = propsTable.Rows.Count + 1, end;
145                                 if (i < pmapTable.Rows.Count - 1)
146                                         end = (int) pmapTable [i + 1].PropertyList;
147                                 else
148                                         end = last;
149
150                                 if (end > last)
151                                         end = last;
152
153                                 for (int j = start; j < end; j++) {
154                                         PropertyRow prow = propsTable [j - 1];
155                                         PropertySig psig = m_sigReader.GetPropSig (prow.Type);
156                                         PropertyDefinition pdef = new PropertyDefinition (
157                                                 m_root.Streams.StringsHeap [prow.Name],
158                                                 GetTypeRefFromSig (psig.Type, context),
159                                         prow.Flags);
160                                         pdef.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Property, j - 1);
161
162                                         pdef.PropertyType = GetModifierType (psig.CustomMods, pdef.PropertyType);
163
164                                         if (!IsDeleted (pdef))
165                                                 owner.Properties.Add (pdef);
166
167                                         m_properties [j - 1] = pdef;
168                                 }
169                         }
170                 }
171
172                 void ReadEvents ()
173                 {
174                         if (!m_tHeap.HasTable (EventTable.RId)) {
175                                 m_events = new EventDefinition [0];
176                                 return;
177                         }
178
179                         EventTable evtTable = m_tableReader.GetEventTable ();
180                         EventMapTable emapTable = m_tableReader.GetEventMapTable ();
181                         m_events = new EventDefinition [evtTable.Rows.Count];
182                         for (int i = 0; i < emapTable.Rows.Count; i++) {
183                                 EventMapRow emapRow = emapTable [i];
184                                 if (emapRow.Parent == 0)
185                                         continue;
186
187                                 TypeDefinition owner = GetTypeDefAt (emapRow.Parent);
188                                 GenericContext context = new GenericContext (owner);
189
190                                 int start = (int) emapRow.EventList, last = evtTable.Rows.Count + 1, end;
191                                 if (i < (emapTable.Rows.Count - 1))
192                                         end = (int) emapTable [i + 1].EventList;
193                                 else
194                                         end = last;
195
196                                 if (end > last)
197                                         end = last;
198
199                                 for (int j = start; j < end; j++) {
200                                         EventRow erow = evtTable [j - 1];
201                                         EventDefinition edef = new EventDefinition (
202                                                 m_root.Streams.StringsHeap [erow.Name],
203                                                 GetTypeDefOrRef (erow.EventType, context), erow.EventFlags);
204                                         edef.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Event, j - 1);
205
206                                         if (!IsDeleted (edef))
207                                                 owner.Events.Add (edef);
208
209                                         m_events [j - 1] = edef;
210                                 }
211                         }
212                 }
213
214                 void ReadSemantics ()
215                 {
216                         if (!m_tHeap.HasTable (MethodSemanticsTable.RId))
217                                 return;
218
219                         MethodSemanticsTable semTable = m_tableReader.GetMethodSemanticsTable ();
220                         for (int i = 0; i < semTable.Rows.Count; i++) {
221                                 MethodSemanticsRow semRow = semTable [i];
222                                 MethodDefinition semMeth = GetMethodDefAt (semRow.Method);
223                                 semMeth.SemanticsAttributes = semRow.Semantics;
224                                 switch (semRow.Association.TokenType) {
225                                 case TokenType.Event :
226                                         EventDefinition evt = GetEventDefAt (semRow.Association.RID);
227                                         if ((semRow.Semantics & MethodSemanticsAttributes.AddOn) != 0)
228                                                 evt.AddMethod = semMeth;
229                                         else if ((semRow.Semantics & MethodSemanticsAttributes.Fire) != 0)
230                                                 evt.InvokeMethod = semMeth;
231                                         else if ((semRow.Semantics & MethodSemanticsAttributes.RemoveOn) != 0)
232                                                 evt.RemoveMethod = semMeth;
233                                         break;
234                                 case TokenType.Property :
235                                         PropertyDefinition prop = GetPropertyDefAt (semRow.Association.RID);
236                                         if ((semRow.Semantics & MethodSemanticsAttributes.Getter) != 0)
237                                                 prop.GetMethod = semMeth;
238                                         else if ((semRow.Semantics & MethodSemanticsAttributes.Setter) != 0)
239                                                 prop.SetMethod = semMeth;
240                                         break;
241                                 }
242                         }
243                 }
244
245                 void ReadInterfaces ()
246                 {
247                         if (!m_tHeap.HasTable (InterfaceImplTable.RId))
248                                 return;
249
250                         InterfaceImplTable intfsTable = m_tableReader.GetInterfaceImplTable ();
251                         for (int i = 0; i < intfsTable.Rows.Count; i++) {
252                                 InterfaceImplRow intfsRow = intfsTable [i];
253                                 TypeDefinition owner = GetTypeDefAt (intfsRow.Class);
254                                 owner.Interfaces.Add (GetTypeDefOrRef (intfsRow.Interface, new GenericContext (owner)));
255                         }
256                 }
257
258                 void ReadOverrides ()
259                 {
260                         if (!m_tHeap.HasTable (MethodImplTable.RId))
261                                 return;
262
263                         MethodImplTable implTable = m_tableReader.GetMethodImplTable ();
264                         for (int i = 0; i < implTable.Rows.Count; i++) {
265                                 MethodImplRow implRow = implTable [i];
266                                 if (implRow.MethodBody.TokenType == TokenType.Method) {
267                                         MethodDefinition owner = GetMethodDefAt (implRow.MethodBody.RID);
268                                         switch (implRow.MethodDeclaration.TokenType) {
269                                         case TokenType.Method :
270                                                 owner.Overrides.Add (
271                                                         GetMethodDefAt (implRow.MethodDeclaration.RID));
272                                                 break;
273                                         case TokenType.MemberRef :
274                                                 owner.Overrides.Add (
275                                                         (MethodReference) GetMemberRefAt (
276                                                                 implRow.MethodDeclaration.RID, new GenericContext (owner)));
277                                                 break;
278                                         }
279                                 }
280                         }
281                 }
282
283                 void ReadSecurityDeclarations ()
284                 {
285                         if (!m_tHeap.HasTable (DeclSecurityTable.RId))
286                                 return;
287
288                         DeclSecurityTable dsTable = m_tableReader.GetDeclSecurityTable ();
289                         for (int i = 0; i < dsTable.Rows.Count; i++) {
290                                 DeclSecurityRow dsRow = dsTable [i];
291                                 SecurityDeclaration dec = BuildSecurityDeclaration (dsRow);
292
293                                 if (dsRow.Parent.RID == 0)
294                                         continue;
295
296                                 IHasSecurity owner = null;
297                                 switch (dsRow.Parent.TokenType) {
298                                 case TokenType.Assembly :
299                                         owner = this.Module.Assembly;
300                                         break;
301                                 case TokenType.TypeDef :
302                                         owner = GetTypeDefAt (dsRow.Parent.RID);
303                                         break;
304                                 case TokenType.Method :
305                                         owner = GetMethodDefAt (dsRow.Parent.RID);
306                                         break;
307                                 }
308
309                                 owner.SecurityDeclarations.Add (dec);
310                         }
311                 }
312
313                 void ReadCustomAttributes ()
314                 {
315                         if (!m_tHeap.HasTable (CustomAttributeTable.RId))
316                                 return;
317
318                         CustomAttributeTable caTable = m_tableReader.GetCustomAttributeTable ();
319                         for (int i = 0; i < caTable.Rows.Count; i++) {
320                                 CustomAttributeRow caRow = caTable [i];
321                                 MethodReference ctor;
322
323                                 if (caRow.Type.RID == 0)
324                                         continue;
325
326                                 if (caRow.Type.TokenType == TokenType.Method)
327                                         ctor = GetMethodDefAt (caRow.Type.RID);
328                                 else
329                                         ctor = GetMemberRefAt (caRow.Type.RID, new GenericContext ()) as MethodReference;
330
331                                 CustomAttrib ca = m_sigReader.GetCustomAttrib (caRow.Value, ctor);
332                                 CustomAttribute cattr = BuildCustomAttribute (ctor, m_root.Streams.BlobHeap.Read (caRow.Value), ca);
333
334                                 if (caRow.Parent.RID == 0)
335                                         continue;
336
337                                 ICustomAttributeProvider owner = null;
338                                 switch (caRow.Parent.TokenType) {
339                                 case TokenType.Assembly :
340                                         owner = this.Module.Assembly;
341                                         break;
342                                 case TokenType.Module :
343                                         owner = this.Module;
344                                         break;
345                                 case TokenType.TypeDef :
346                                         owner = GetTypeDefAt (caRow.Parent.RID);
347                                         break;
348                                 case TokenType.TypeRef :
349                                         owner = GetTypeRefAt (caRow.Parent.RID);
350                                         break;
351                                 case TokenType.Field :
352                                         owner = GetFieldDefAt (caRow.Parent.RID);
353                                         break;
354                                 case TokenType.Method :
355                                         owner = GetMethodDefAt (caRow.Parent.RID);
356                                         break;
357                                 case TokenType.Property :
358                                         owner = GetPropertyDefAt (caRow.Parent.RID);
359                                         break;
360                                 case TokenType.Event :
361                                         owner = GetEventDefAt (caRow.Parent.RID);
362                                         break;
363                                 case TokenType.Param :
364                                         owner = GetParamDefAt (caRow.Parent.RID);
365                                         break;
366                                 case TokenType.GenericParam :
367                                         owner = GetGenericParameterAt (caRow.Parent.RID);
368                                         break;
369                                 default :
370                                         //TODO: support other ?
371                                         break;
372                                 }
373
374                                 if (owner != null)
375                                         owner.CustomAttributes.Add (cattr);
376                         }
377                 }
378
379                 void ReadConstants ()
380                 {
381                         if (!m_tHeap.HasTable (ConstantTable.RId))
382                                 return;
383
384                         ConstantTable csTable = m_tableReader.GetConstantTable ();
385                         for (int i = 0; i < csTable.Rows.Count; i++) {
386                                 ConstantRow csRow = csTable [i];
387
388                                 object constant = GetConstant (csRow.Value, csRow.Type);
389
390                                 IHasConstant owner = null;
391                                 switch (csRow.Parent.TokenType) {
392                                 case TokenType.Field :
393                                         owner = GetFieldDefAt (csRow.Parent.RID);
394                                         break;
395                                 case TokenType.Property :
396                                         owner = GetPropertyDefAt (csRow.Parent.RID);
397                                         break;
398                                 case TokenType.Param :
399                                         owner = GetParamDefAt (csRow.Parent.RID);
400                                         break;
401                                 }
402
403                                 owner.Constant = constant;
404                         }
405                 }
406
407                 void ReadExternTypes ()
408                 {
409                         base.VisitExternTypeCollection (Module.ExternTypes);
410                 }
411
412                 void ReadMarshalSpecs ()
413                 {
414                         if (!m_tHeap.HasTable (FieldMarshalTable.RId))
415                                 return;
416
417                         FieldMarshalTable fmTable = m_tableReader.GetFieldMarshalTable ();
418                         for (int i = 0; i < fmTable.Rows.Count; i++) {
419                                 FieldMarshalRow fmRow = fmTable [i];
420
421                                 if (fmRow.Parent.RID == 0)
422                                         continue;
423
424                                 IHasMarshalSpec owner = null;
425                                 switch (fmRow.Parent.TokenType) {
426                                 case TokenType.Field:
427                                         owner = GetFieldDefAt (fmRow.Parent.RID);
428                                         break;
429                                 case TokenType.Param:
430                                         owner = GetParamDefAt (fmRow.Parent.RID);
431                                         break;
432                                 }
433
434                                 owner.MarshalSpec = BuildMarshalDesc (
435                                         m_sigReader.GetMarshalSig (fmRow.NativeType), owner);
436                         }
437                 }
438
439                 void ReadInitialValues ()
440                 {
441                         if (!m_tHeap.HasTable (FieldRVATable.RId))
442                                 return;
443
444                         FieldRVATable frTable = m_tableReader.GetFieldRVATable ();
445                         for (int i = 0; i < frTable.Rows.Count; i++) {
446                                 FieldRVARow frRow = frTable [i];
447                                 FieldDefinition field = GetFieldDefAt (frRow.Field);
448                                 field.RVA = frRow.RVA;
449                                 SetInitialValue (field);
450                         }
451                 }
452         }
453 }