2 // AggressiveRefletionReader.cs
5 // Jb Evain (jbevain@gmail.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
29 namespace Mono.Cecil {
33 using Mono.Cecil.Metadata;
34 using Mono.Cecil.Signatures;
36 internal sealed class AggressiveReflectionReader : ReflectionReader {
38 public AggressiveReflectionReader (ModuleDefinition module) : base (module)
42 public override void VisitTypeDefinitionCollection (TypeDefinitionCollection types)
44 base.VisitTypeDefinitionCollection (types);
46 ReadGenericParameterConstraints ();
47 ReadClassLayoutInfos ();
48 ReadFieldLayoutInfos ();
55 ReadSecurityDeclarations ();
56 ReadCustomAttributes ();
67 void ReadGenericParameterConstraints ()
69 if (!m_tHeap.HasTable (GenericParamConstraintTable.RId))
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);
77 gp.Constraints.Add (GetTypeDefOrRef (gpcRow.Constraint, new GenericContext (gp.Owner)));
81 void ReadClassLayoutInfos ()
83 if (!m_tHeap.HasTable (ClassLayoutTable.RId))
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;
95 void ReadFieldLayoutInfos ()
97 if (!m_tHeap.HasTable (FieldLayoutTable.RId))
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;
108 void ReadPInvokeInfos ()
110 if (!m_tHeap.HasTable (ImplMapTable.RId))
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]);
125 void ReadProperties ()
127 if (!m_tHeap.HasTable (PropertyTable.RId)) {
128 m_properties = new PropertyDefinition [0];
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)
140 TypeDefinition owner = GetTypeDefAt (pmapRow.Parent);
142 GenericContext context = new GenericContext (owner);
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;
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),
160 pdef.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Property, j - 1);
162 pdef.PropertyType = GetModifierType (psig.CustomMods, pdef.PropertyType);
164 if (!IsDeleted (pdef))
165 owner.Properties.Add (pdef);
167 m_properties [j - 1] = pdef;
174 if (!m_tHeap.HasTable (EventTable.RId)) {
175 m_events = new EventDefinition [0];
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)
187 TypeDefinition owner = GetTypeDefAt (emapRow.Parent);
188 GenericContext context = new GenericContext (owner);
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;
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);
206 if (!IsDeleted (edef))
207 owner.Events.Add (edef);
209 m_events [j - 1] = edef;
214 void ReadSemantics ()
216 if (!m_tHeap.HasTable (MethodSemanticsTable.RId))
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;
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;
245 void ReadInterfaces ()
247 if (!m_tHeap.HasTable (InterfaceImplTable.RId))
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)));
258 void ReadOverrides ()
260 if (!m_tHeap.HasTable (MethodImplTable.RId))
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));
273 case TokenType.MemberRef :
274 owner.Overrides.Add (
275 (MethodReference) GetMemberRefAt (
276 implRow.MethodDeclaration.RID, new GenericContext (owner)));
283 void ReadSecurityDeclarations ()
285 if (!m_tHeap.HasTable (DeclSecurityTable.RId))
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);
293 if (dsRow.Parent.RID == 0)
296 IHasSecurity owner = null;
297 switch (dsRow.Parent.TokenType) {
298 case TokenType.Assembly :
299 owner = this.Module.Assembly;
301 case TokenType.TypeDef :
302 owner = GetTypeDefAt (dsRow.Parent.RID);
304 case TokenType.Method :
305 owner = GetMethodDefAt (dsRow.Parent.RID);
309 owner.SecurityDeclarations.Add (dec);
313 void ReadCustomAttributes ()
315 if (!m_tHeap.HasTable (CustomAttributeTable.RId))
318 CustomAttributeTable caTable = m_tableReader.GetCustomAttributeTable ();
319 for (int i = 0; i < caTable.Rows.Count; i++) {
320 CustomAttributeRow caRow = caTable [i];
321 MethodReference ctor;
323 if (caRow.Type.RID == 0)
326 if (caRow.Type.TokenType == TokenType.Method)
327 ctor = GetMethodDefAt (caRow.Type.RID);
329 ctor = GetMemberRefAt (caRow.Type.RID, new GenericContext ()) as MethodReference;
331 CustomAttrib ca = m_sigReader.GetCustomAttrib (caRow.Value, ctor);
332 CustomAttribute cattr = BuildCustomAttribute (ctor, m_root.Streams.BlobHeap.Read (caRow.Value), ca);
334 if (caRow.Parent.RID == 0)
337 ICustomAttributeProvider owner = null;
338 switch (caRow.Parent.TokenType) {
339 case TokenType.Assembly :
340 owner = this.Module.Assembly;
342 case TokenType.Module :
345 case TokenType.TypeDef :
346 owner = GetTypeDefAt (caRow.Parent.RID);
348 case TokenType.TypeRef :
349 owner = GetTypeRefAt (caRow.Parent.RID);
351 case TokenType.Field :
352 owner = GetFieldDefAt (caRow.Parent.RID);
354 case TokenType.Method :
355 owner = GetMethodDefAt (caRow.Parent.RID);
357 case TokenType.Property :
358 owner = GetPropertyDefAt (caRow.Parent.RID);
360 case TokenType.Event :
361 owner = GetEventDefAt (caRow.Parent.RID);
363 case TokenType.Param :
364 owner = GetParamDefAt (caRow.Parent.RID);
366 case TokenType.GenericParam :
367 owner = GetGenericParameterAt (caRow.Parent.RID);
370 //TODO: support other ?
375 owner.CustomAttributes.Add (cattr);
379 void ReadConstants ()
381 if (!m_tHeap.HasTable (ConstantTable.RId))
384 ConstantTable csTable = m_tableReader.GetConstantTable ();
385 for (int i = 0; i < csTable.Rows.Count; i++) {
386 ConstantRow csRow = csTable [i];
388 object constant = GetConstant (csRow.Value, csRow.Type);
390 IHasConstant owner = null;
391 switch (csRow.Parent.TokenType) {
392 case TokenType.Field :
393 owner = GetFieldDefAt (csRow.Parent.RID);
395 case TokenType.Property :
396 owner = GetPropertyDefAt (csRow.Parent.RID);
398 case TokenType.Param :
399 owner = GetParamDefAt (csRow.Parent.RID);
403 owner.Constant = constant;
407 void ReadExternTypes ()
409 base.VisitExternTypeCollection (Module.ExternTypes);
412 void ReadMarshalSpecs ()
414 if (!m_tHeap.HasTable (FieldMarshalTable.RId))
417 FieldMarshalTable fmTable = m_tableReader.GetFieldMarshalTable ();
418 for (int i = 0; i < fmTable.Rows.Count; i++) {
419 FieldMarshalRow fmRow = fmTable [i];
421 if (fmRow.Parent.RID == 0)
424 IHasMarshalSpec owner = null;
425 switch (fmRow.Parent.TokenType) {
426 case TokenType.Field:
427 owner = GetFieldDefAt (fmRow.Parent.RID);
429 case TokenType.Param:
430 owner = GetParamDefAt (fmRow.Parent.RID);
434 owner.MarshalSpec = BuildMarshalDesc (
435 m_sigReader.GetMarshalSig (fmRow.NativeType), owner);
439 void ReadInitialValues ()
441 if (!m_tHeap.HasTable (FieldRVATable.RId))
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);