~do-win/do/test-paths

« back to all changes in this revision

Viewing changes to Mono.Addins.CecilReflector/Mono.Cecil/Mono.Cecil.Signatures/SignatureReader.cs

  • Committer: Chris S.
  • Date: 2009-06-21 03:37:34 UTC
  • Revision ID: chris@szikszoy.com-20090621033734-ud2jdcd5pq9r3ue9
initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// SignatureReader.cs
 
3
//
 
4
// Author:
 
5
//   Jb Evain (jbevain@gmail.com)
 
6
//
 
7
// (C) 2005 - 2007 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.Signatures {
 
30
 
 
31
        using System;
 
32
        using System.Collections;
 
33
        using System.IO;
 
34
        using System.Text;
 
35
 
 
36
        using Mono.Cecil;
 
37
        using Mono.Cecil.Metadata;
 
38
 
 
39
        internal sealed class SignatureReader : BaseSignatureVisitor {
 
40
 
 
41
                MetadataRoot m_root;
 
42
                ReflectionReader m_reflectReader;
 
43
                byte [] m_blobData;
 
44
 
 
45
                IDictionary m_signatures;
 
46
 
 
47
                IAssemblyResolver AssemblyResolver {
 
48
                        get { return m_reflectReader.Module.Assembly.Resolver; }
 
49
                }
 
50
 
 
51
                public SignatureReader (MetadataRoot root, ReflectionReader reflectReader)
 
52
                {
 
53
                        m_root = root;
 
54
                        m_reflectReader = reflectReader;
 
55
 
 
56
                        m_blobData = m_root.Streams.BlobHeap != null ? m_root.Streams.BlobHeap.Data : new byte [0];
 
57
 
 
58
                        m_signatures = new Hashtable ();
 
59
                }
 
60
 
 
61
                public FieldSig GetFieldSig (uint index)
 
62
                {
 
63
                        FieldSig f = m_signatures [index] as FieldSig;
 
64
                        if (f == null) {
 
65
                                f = new FieldSig (index);
 
66
                                f.Accept (this);
 
67
                                m_signatures [index] = f;
 
68
                        }
 
69
                        return f;
 
70
                }
 
71
 
 
72
                public PropertySig GetPropSig (uint index)
 
73
                {
 
74
                        PropertySig p = m_signatures [index] as PropertySig;
 
75
                        if (p == null) {
 
76
                                p = new PropertySig (index);
 
77
                                p.Accept (this);
 
78
                                m_signatures [index] = p;
 
79
                        }
 
80
                        return p;
 
81
                }
 
82
 
 
83
                public MethodDefSig GetMethodDefSig (uint index)
 
84
                {
 
85
                        MethodDefSig m = m_signatures [index] as MethodDefSig;
 
86
                        if (m == null) {
 
87
                                m = new MethodDefSig (index);
 
88
                                m.Accept (this);
 
89
                                m_signatures [index] = m;
 
90
                        }
 
91
                        return m;
 
92
                }
 
93
 
 
94
                public MethodRefSig GetMethodRefSig (uint index)
 
95
                {
 
96
                        MethodRefSig m = m_signatures [index] as MethodRefSig;
 
97
                        if (m == null) {
 
98
                                m = new MethodRefSig (index);
 
99
                                m.Accept (this);
 
100
                                m_signatures [index] = m;
 
101
                        }
 
102
                        return m;
 
103
                }
 
104
 
 
105
                public TypeSpec GetTypeSpec (uint index)
 
106
                {
 
107
                        TypeSpec ts = m_signatures [index] as TypeSpec;
 
108
 
 
109
                        if (ts == null) {
 
110
                                ts = ReadTypeSpec (m_blobData, (int) index);
 
111
                                m_signatures [index] = ts;
 
112
                        }
 
113
 
 
114
                        return ts;
 
115
                }
 
116
 
 
117
                public MethodSpec GetMethodSpec (uint index)
 
118
                {
 
119
                        MethodSpec ms = m_signatures [index] as MethodSpec;
 
120
 
 
121
                        if (ms == null) {
 
122
                                ms = ReadMethodSpec (m_blobData, (int) index);
 
123
                                m_signatures [index] = ms;
 
124
                        }
 
125
 
 
126
                        return ms;
 
127
                }
 
128
 
 
129
                public LocalVarSig GetLocalVarSig (uint index)
 
130
                {
 
131
                        LocalVarSig lv = m_signatures [index] as LocalVarSig;
 
132
                        if (lv == null) {
 
133
                                lv = new LocalVarSig (index);
 
134
                                lv.Accept (this);
 
135
                                m_signatures [index] = lv;
 
136
                        }
 
137
                        return lv;
 
138
                }
 
139
 
 
140
                public CustomAttrib GetCustomAttrib (uint index, MethodReference ctor)
 
141
                {
 
142
                        return GetCustomAttrib (index, ctor, false);
 
143
                }
 
144
 
 
145
                public CustomAttrib GetCustomAttrib (uint index, MethodReference ctor, bool resolve)
 
146
                {
 
147
                        return ReadCustomAttrib ((int) index, ctor, resolve);
 
148
                }
 
149
 
 
150
                public CustomAttrib GetCustomAttrib (byte [] data, MethodReference ctor)
 
151
                {
 
152
                        return GetCustomAttrib (data, ctor, false);
 
153
                }
 
154
 
 
155
                public CustomAttrib GetCustomAttrib (byte [] data, MethodReference ctor, bool resolve)
 
156
                {
 
157
                        BinaryReader br = new BinaryReader (new MemoryStream (data));
 
158
                        return ReadCustomAttrib (br, data, ctor, resolve);
 
159
                }
 
160
 
 
161
                public Signature GetMemberRefSig (TokenType tt, uint index)
 
162
                {
 
163
                        int start, callconv;
 
164
                        Utilities.ReadCompressedInteger (m_blobData, (int) index, out start);
 
165
                        callconv = m_blobData [start];
 
166
                        if ((callconv & 0x5) == 0x5 || (callconv & 0x10) == 0x10) // vararg || generic?
 
167
                                return GetMethodDefSig (index);
 
168
                        if ((callconv & 0x6) != 0) // field ?
 
169
                                return GetFieldSig (index);
 
170
 
 
171
                        switch (tt) {
 
172
                        case TokenType.TypeDef :
 
173
                        case TokenType.TypeRef :
 
174
                        case TokenType.TypeSpec :
 
175
                                return GetMethodRefSig (index);
 
176
                        case TokenType.ModuleRef :
 
177
                        case TokenType.Method :
 
178
                                return GetMethodDefSig (index);
 
179
                        }
 
180
                        return null;
 
181
                }
 
182
 
 
183
                public MarshalSig GetMarshalSig (uint index)
 
184
                {
 
185
                        MarshalSig ms = m_signatures [index] as MarshalSig;
 
186
                        if (ms == null) {
 
187
                                byte [] data = m_root.Streams.BlobHeap.Read (index);
 
188
                                ms = ReadMarshalSig (data);
 
189
                                m_signatures [index] = ms;
 
190
                        }
 
191
                        return ms;
 
192
                }
 
193
 
 
194
                public MethodSig GetStandAloneMethodSig (uint index)
 
195
                {
 
196
                        byte [] data = m_root.Streams.BlobHeap.Read (index);
 
197
                        int start;
 
198
                        if ((data [0] & 0x5) > 0) {
 
199
                                MethodRefSig mrs = new MethodRefSig (index);
 
200
                                ReadMethodRefSig (mrs, data, 0, out start);
 
201
                                return mrs;
 
202
                        } else {
 
203
                                MethodDefSig mds = new MethodDefSig (index);
 
204
                                ReadMethodDefSig (mds, data, 0, out start);
 
205
                                return mds;
 
206
                        }
 
207
                }
 
208
 
 
209
                public override void VisitMethodDefSig (MethodDefSig methodDef)
 
210
                {
 
211
                        int start;
 
212
                        ReadMethodDefSig (methodDef, m_root.Streams.BlobHeap.Read (methodDef.BlobIndex), 0, out start);
 
213
                }
 
214
 
 
215
                public override void VisitMethodRefSig (MethodRefSig methodRef)
 
216
                {
 
217
                        int start;
 
218
                        ReadMethodRefSig (methodRef, m_root.Streams.BlobHeap.Read (methodRef.BlobIndex), 0, out start);
 
219
                }
 
220
 
 
221
                public override void VisitFieldSig (FieldSig field)
 
222
                {
 
223
                        int start;
 
224
                        Utilities.ReadCompressedInteger (m_blobData, (int) field.BlobIndex, out start);
 
225
                        field.CallingConvention = m_blobData [start];
 
226
                        field.Field = (field.CallingConvention & 0x6) != 0;
 
227
                        field.CustomMods = ReadCustomMods (m_blobData, start + 1, out start);
 
228
                        field.Type = ReadType (m_blobData, start, out start);
 
229
                }
 
230
 
 
231
                public override void VisitPropertySig (PropertySig property)
 
232
                {
 
233
                        int start;
 
234
                        Utilities.ReadCompressedInteger (m_blobData, (int) property.BlobIndex, out start);
 
235
                        property.CallingConvention = m_blobData [start];
 
236
                        property.Property = (property.CallingConvention & 0x8) != 0;
 
237
                        property.ParamCount = Utilities.ReadCompressedInteger (m_blobData, start + 1, out start);
 
238
                        property.CustomMods = ReadCustomMods (m_blobData, start, out start);
 
239
                        property.Type = ReadType (m_blobData, start, out start);
 
240
                        property.Parameters = ReadParameters (property.ParamCount, m_blobData, start);
 
241
                }
 
242
 
 
243
                public override void VisitLocalVarSig (LocalVarSig localvar)
 
244
                {
 
245
                        int start;
 
246
                        Utilities.ReadCompressedInteger (m_blobData, (int) localvar.BlobIndex, out start);
 
247
                        localvar.CallingConvention = m_blobData [start];
 
248
                        localvar.Local = (localvar.CallingConvention & 0x7) != 0;
 
249
                        localvar.Count = Utilities.ReadCompressedInteger (m_blobData, start + 1, out start);
 
250
                        localvar.LocalVariables = ReadLocalVariables (localvar.Count, m_blobData, start);
 
251
                }
 
252
 
 
253
                void ReadMethodDefSig (MethodDefSig methodDef, byte [] data, int pos, out int start)
 
254
                {
 
255
                        methodDef.CallingConvention = data [pos];
 
256
                        start = pos + 1;
 
257
                        methodDef.HasThis = (methodDef.CallingConvention & 0x20) != 0;
 
258
                        methodDef.ExplicitThis = (methodDef.CallingConvention & 0x40) != 0;
 
259
                        if ((methodDef.CallingConvention & 0x5) != 0)
 
260
                                methodDef.MethCallConv |= MethodCallingConvention.VarArg;
 
261
                        else if ((methodDef.CallingConvention & 0x10) != 0) {
 
262
                                methodDef.MethCallConv |= MethodCallingConvention.Generic;
 
263
                                methodDef.GenericParameterCount = Utilities.ReadCompressedInteger (data, start, out start);
 
264
                        } else
 
265
                                methodDef.MethCallConv |= MethodCallingConvention.Default;
 
266
 
 
267
                        methodDef.ParamCount = Utilities.ReadCompressedInteger (data, start, out start);
 
268
                        methodDef.RetType = ReadRetType (data, start, out start);
 
269
                        int sentpos;
 
270
                        methodDef.Parameters = ReadParameters (methodDef.ParamCount, data, start, out sentpos);
 
271
                        methodDef.Sentinel = sentpos;
 
272
                }
 
273
 
 
274
                void ReadMethodRefSig (MethodRefSig methodRef, byte [] data, int pos, out int start)
 
275
                {
 
276
                        methodRef.CallingConvention = data [pos];
 
277
                        start = pos + 1;
 
278
                        methodRef.HasThis = (methodRef.CallingConvention & 0x20) != 0;
 
279
                        methodRef.ExplicitThis = (methodRef.CallingConvention & 0x40) != 0;
 
280
                        if ((methodRef.CallingConvention & 0x1) != 0)
 
281
                                methodRef.MethCallConv |= MethodCallingConvention.C;
 
282
                        else if ((methodRef.CallingConvention & 0x2) != 0)
 
283
                                methodRef.MethCallConv |= MethodCallingConvention.StdCall;
 
284
                        else if ((methodRef.CallingConvention & 0x3) != 0)
 
285
                                methodRef.MethCallConv |= MethodCallingConvention.ThisCall;
 
286
                        else if ((methodRef.CallingConvention & 0x4) != 0)
 
287
                                methodRef.MethCallConv |= MethodCallingConvention.FastCall;
 
288
                        else if ((methodRef.CallingConvention & 0x5) != 0)
 
289
                                methodRef.MethCallConv |= MethodCallingConvention.VarArg;
 
290
                        else
 
291
                                methodRef.MethCallConv |= MethodCallingConvention.Default;
 
292
                        methodRef.ParamCount = Utilities.ReadCompressedInteger (data, start, out start);
 
293
                        methodRef.RetType = ReadRetType (data, start, out start);
 
294
                        int sentpos;
 
295
                        methodRef.Parameters = ReadParameters (methodRef.ParamCount, data, start, out sentpos);
 
296
                        methodRef.Sentinel = sentpos;
 
297
                }
 
298
 
 
299
                LocalVarSig.LocalVariable [] ReadLocalVariables (int length, byte [] data, int pos)
 
300
                {
 
301
                        int start = pos;
 
302
                        LocalVarSig.LocalVariable [] types = new LocalVarSig.LocalVariable [length];
 
303
                        for (int i = 0; i < length; i++)
 
304
                                types [i] = ReadLocalVariable (data, start, out start);
 
305
                        return types;
 
306
                }
 
307
 
 
308
                LocalVarSig.LocalVariable ReadLocalVariable (byte [] data, int pos, out int start)
 
309
                {
 
310
                        start = pos;
 
311
                        LocalVarSig.LocalVariable lv = new LocalVarSig.LocalVariable ();
 
312
                        lv.ByRef = false;
 
313
                        int cursor;
 
314
                        while (true) {
 
315
                                lv.CustomMods = ReadCustomMods (data, start, out start);
 
316
                                cursor = start;
 
317
                                int current = Utilities.ReadCompressedInteger (data, start, out start);
 
318
                                if (current == (int) ElementType.Pinned) // the only possible constraint
 
319
                                        lv.Constraint |= Constraint.Pinned;
 
320
                                else if (current == (int) ElementType.ByRef) {
 
321
                                        lv.ByRef = true;
 
322
 
 
323
                                        if (lv.CustomMods == null || lv.CustomMods.Length == 0)
 
324
                                                lv.CustomMods = ReadCustomMods (data, start, out start);
 
325
                                } else {
 
326
                                        lv.Type = ReadType (data, cursor, out start);
 
327
                                        break;
 
328
                                }
 
329
                        }
 
330
                        return lv;
 
331
                }
 
332
 
 
333
                TypeSpec ReadTypeSpec (byte [] data, int pos)
 
334
                {
 
335
                        int start = pos;
 
336
                        Utilities.ReadCompressedInteger (data, start, out start);
 
337
                        TypeSpec ts = new TypeSpec ();
 
338
                        ts.CustomMods = ReadCustomMods (data, start, out start);
 
339
                        ts.Type = ReadType (data, start, out start);
 
340
                        return ts;
 
341
                }
 
342
 
 
343
                MethodSpec ReadMethodSpec (byte [] data, int pos)
 
344
                {
 
345
                        int start = pos;
 
346
 
 
347
                        Utilities.ReadCompressedInteger (data, start, out start);
 
348
                        if (Utilities.ReadCompressedInteger (data, start, out start) != 0x0a)
 
349
                                throw new ReflectionException ("Invalid MethodSpec signature");
 
350
 
 
351
                        return new MethodSpec (ReadGenericInstSignature (data, start, out start));
 
352
                }
 
353
 
 
354
                RetType ReadRetType (byte [] data, int pos, out int start)
 
355
                {
 
356
                        RetType rt = new RetType ();
 
357
                        start = pos;
 
358
                        rt.CustomMods = ReadCustomMods (data, start, out start);
 
359
                        int curs = start;
 
360
                        ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
 
361
                        switch (flag) {
 
362
                        case ElementType.Void :
 
363
                                rt.ByRef = rt.TypedByRef = false;
 
364
                                rt.Void = true;
 
365
                                break;
 
366
                        case ElementType.TypedByRef :
 
367
                                rt.ByRef = rt.Void = false;
 
368
                                rt.TypedByRef = true;
 
369
                                break;
 
370
                        case ElementType.ByRef :
 
371
                                rt.TypedByRef = rt.Void = false;
 
372
                                rt.ByRef = true;
 
373
 
 
374
                                if (rt.CustomMods == null || rt.CustomMods.Length == 0)
 
375
                                        rt.CustomMods = ReadCustomMods (data, start, out start);
 
376
 
 
377
                                rt.Type = ReadType (data, start, out start);
 
378
                                break;
 
379
                        default :
 
380
                                rt.TypedByRef = rt.Void = rt.ByRef = false;
 
381
                                rt.Type = ReadType (data, curs, out start);
 
382
                                break;
 
383
                        }
 
384
                        return rt;
 
385
                }
 
386
 
 
387
                Param [] ReadParameters (int length, byte [] data, int pos)
 
388
                {
 
389
                        Param [] ret = new Param [length];
 
390
                        int start = pos;
 
391
                        for (int i = 0; i < length; i++)
 
392
                                ret [i] = ReadParameter (data, start, out start);
 
393
                        return ret;
 
394
                }
 
395
 
 
396
                Param [] ReadParameters (int length, byte [] data, int pos, out int sentinelpos)
 
397
                {
 
398
                        Param [] ret = new Param [length];
 
399
                        int start = pos;
 
400
                        sentinelpos = -1;
 
401
 
 
402
                        for (int i = 0; i < length; i++) {
 
403
                                int curs = start;
 
404
                                int flag = Utilities.ReadCompressedInteger (data, start, out start);
 
405
 
 
406
                                if (flag == (int) ElementType.Sentinel) {
 
407
                                        sentinelpos = i;
 
408
                                        curs = start;
 
409
                                }
 
410
 
 
411
                                ret [i] = ReadParameter (data, curs, out start);
 
412
                        }
 
413
 
 
414
                        return ret;
 
415
                }
 
416
 
 
417
                Param ReadParameter (byte [] data, int pos, out int start)
 
418
                {
 
419
                        Param p = new Param ();
 
420
                        start = pos;
 
421
 
 
422
                        p.CustomMods = ReadCustomMods (data, start, out start);
 
423
                        int curs = start;
 
424
                        ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
 
425
                        switch (flag) {
 
426
                        case ElementType.TypedByRef :
 
427
                                p.TypedByRef = true;
 
428
                                p.ByRef = false;
 
429
                                break;
 
430
                        case ElementType.ByRef :
 
431
                                p.TypedByRef = false;
 
432
                                p.ByRef = true;
 
433
 
 
434
                                if (p.CustomMods == null || p.CustomMods.Length == 0)
 
435
                                        p.CustomMods = ReadCustomMods (data, start, out start);
 
436
 
 
437
                                p.Type = ReadType (data, start, out start);
 
438
                                break;
 
439
                        default :
 
440
                                p.TypedByRef = false;
 
441
                                p.ByRef = false;
 
442
                                p.Type = ReadType (data, curs, out start);
 
443
                                break;
 
444
                        }
 
445
                        return p;
 
446
                }
 
447
 
 
448
                SigType ReadType (byte [] data, int pos, out int start)
 
449
                {
 
450
                        start = pos;
 
451
                        ElementType element = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
 
452
                        switch (element) {
 
453
                        case ElementType.ValueType :
 
454
                                VALUETYPE vt = new VALUETYPE ();
 
455
                                vt.Type = Utilities.GetMetadataToken(CodedIndex.TypeDefOrRef,
 
456
                                        (uint) Utilities.ReadCompressedInteger (data, start, out start));
 
457
                                return vt;
 
458
                        case ElementType.Class :
 
459
                                CLASS c = new CLASS ();
 
460
                                c.Type = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
 
461
                                        (uint) Utilities.ReadCompressedInteger (data, start, out start));
 
462
                                return c;
 
463
                        case ElementType.Ptr :
 
464
                                PTR p = new PTR ();
 
465
                                int buf = start;
 
466
                                int flag = Utilities.ReadCompressedInteger (data, start, out start);
 
467
                                p.Void = flag == (int) ElementType.Void;
 
468
                                if (p.Void)
 
469
                                        return p;
 
470
                                start = buf;
 
471
                                p.CustomMods = ReadCustomMods (data, start, out start);
 
472
                                p.PtrType = ReadType (data, start, out start);
 
473
                                return p;
 
474
                        case ElementType.FnPtr :
 
475
                                FNPTR fp = new FNPTR ();
 
476
                                if ((data [start] & 0x5) != 0) {
 
477
                                        MethodRefSig mr = new MethodRefSig ((uint) start);
 
478
                                        ReadMethodRefSig (mr, data, start, out start);
 
479
                                        fp.Method = mr;
 
480
                                } else {
 
481
                                        MethodDefSig md = new MethodDefSig ((uint) start);
 
482
                                        ReadMethodDefSig (md, data, start, out start);
 
483
                                        fp.Method = md;
 
484
                                }
 
485
                                return fp;
 
486
                        case ElementType.Array :
 
487
                                ARRAY ary = new ARRAY ();
 
488
                                ary.CustomMods = ReadCustomMods (data, start, out start);
 
489
                                ArrayShape shape = new ArrayShape ();
 
490
                                ary.Type = ReadType (data, start, out start);
 
491
                                shape.Rank = Utilities.ReadCompressedInteger (data, start, out start);
 
492
                                shape.NumSizes = Utilities.ReadCompressedInteger (data, start, out start);
 
493
                                shape.Sizes = new int [shape.NumSizes];
 
494
                                for (int i = 0; i < shape.NumSizes; i++)
 
495
                                        shape.Sizes [i] = Utilities.ReadCompressedInteger (data, start, out start);
 
496
                                shape.NumLoBounds = Utilities.ReadCompressedInteger (data, start, out start);
 
497
                                shape.LoBounds = new int [shape.NumLoBounds];
 
498
                                for (int i = 0; i < shape.NumLoBounds; i++)
 
499
                                        shape.LoBounds [i] = Utilities.ReadCompressedInteger (data, start, out start);
 
500
                                ary.Shape = shape;
 
501
                                return ary;
 
502
                        case ElementType.SzArray :
 
503
                                SZARRAY sa = new SZARRAY ();
 
504
                                sa.CustomMods = ReadCustomMods (data, start, out start);
 
505
                                sa.Type = ReadType (data, start, out start);
 
506
                                return sa;
 
507
                        case ElementType.Var:
 
508
                                return new VAR (Utilities.ReadCompressedInteger (data, start, out start));
 
509
                        case ElementType.MVar:
 
510
                                return new MVAR (Utilities.ReadCompressedInteger (data, start, out start));
 
511
                        case ElementType.GenericInst:
 
512
                                GENERICINST ginst = new GENERICINST ();
 
513
 
 
514
                                ginst.ValueType = ((ElementType) Utilities.ReadCompressedInteger (
 
515
                                        data, start, out start)) == ElementType.ValueType;
 
516
 
 
517
                                ginst.Type = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
 
518
                                        (uint) Utilities.ReadCompressedInteger (data, start, out start));
 
519
 
 
520
                                ginst.Signature = ReadGenericInstSignature (data, start, out start);
 
521
 
 
522
                                return ginst;
 
523
                        default :
 
524
                                return new SigType (element);
 
525
                        }
 
526
                }
 
527
 
 
528
                GenericInstSignature ReadGenericInstSignature (byte [] data, int pos, out int start)
 
529
                {
 
530
                        start = pos;
 
531
                        GenericInstSignature gis = new GenericInstSignature ();
 
532
                        gis.Arity = Utilities.ReadCompressedInteger (data, start, out start);
 
533
                        gis.Types = new GenericArg [gis.Arity];
 
534
                        for (int i = 0; i < gis.Arity; i++)
 
535
                                gis.Types [i] = ReadGenericArg (data, start, out start);
 
536
 
 
537
                        return gis;
 
538
                }
 
539
 
 
540
                GenericArg ReadGenericArg (byte[] data, int pos, out int start)
 
541
                {
 
542
                        start = pos;
 
543
                        CustomMod [] mods = ReadCustomMods (data, start, out start);
 
544
                        GenericArg arg = new GenericArg (ReadType (data, start, out start));
 
545
                        arg.CustomMods = mods;
 
546
                        return arg;
 
547
                }
 
548
 
 
549
                CustomMod [] ReadCustomMods (byte [] data, int pos, out int start)
 
550
                {
 
551
                        ArrayList cmods = new ArrayList ();
 
552
                        start = pos;
 
553
                        while (true) {
 
554
                                int buf = start;
 
555
                                ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
 
556
                                start = buf;
 
557
                                if (!((flag == ElementType.CModOpt) || (flag == ElementType.CModReqD)))
 
558
                                        break;
 
559
                                cmods.Add (ReadCustomMod (data, start, out start));
 
560
                        }
 
561
                        return cmods.ToArray (typeof (CustomMod)) as CustomMod [];
 
562
                }
 
563
 
 
564
                CustomMod ReadCustomMod (byte [] data, int pos, out int start)
 
565
                {
 
566
                        CustomMod cm = new CustomMod ();
 
567
                        start = pos;
 
568
                        ElementType cmod = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
 
569
                        if (cmod == ElementType.CModOpt)
 
570
                                cm.CMOD = CustomMod.CMODType.OPT;
 
571
                        else if (cmod == ElementType.CModReqD)
 
572
                                cm.CMOD = CustomMod.CMODType.REQD;
 
573
                        else
 
574
                                cm.CMOD = CustomMod.CMODType.None;
 
575
                        cm.TypeDefOrRef = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
 
576
                                (uint) Utilities.ReadCompressedInteger (data, start, out start));
 
577
                        return cm;
 
578
                }
 
579
 
 
580
                CustomAttrib ReadCustomAttrib (int pos, MethodReference ctor, bool resolve)
 
581
                {
 
582
                        int start, length = Utilities.ReadCompressedInteger (m_blobData, pos, out start);
 
583
                        byte [] data = new byte [length];
 
584
                        Buffer.BlockCopy (m_blobData, start, data, 0, length);
 
585
                        try {
 
586
                                return ReadCustomAttrib (new BinaryReader (
 
587
                                        new MemoryStream (data)), data, ctor, resolve);
 
588
                        } catch {
 
589
                                CustomAttrib ca = new CustomAttrib (ctor);
 
590
                                ca.Read = false;
 
591
                                return ca;
 
592
                        }
 
593
                }
 
594
 
 
595
                CustomAttrib ReadCustomAttrib (BinaryReader br, byte [] data, MethodReference ctor, bool resolve)
 
596
                {
 
597
                        CustomAttrib ca = new CustomAttrib (ctor);
 
598
                        if (data.Length == 0) {
 
599
                                ca.FixedArgs = new CustomAttrib.FixedArg [0];
 
600
                                ca.NamedArgs = new CustomAttrib.NamedArg [0];
 
601
                                return ca;
 
602
                        }
 
603
 
 
604
                        bool read = true;
 
605
 
 
606
                        ca.Prolog = br.ReadUInt16 ();
 
607
                        if (ca.Prolog != CustomAttrib.StdProlog)
 
608
                                throw new MetadataFormatException ("Non standard prolog for custom attribute");
 
609
 
 
610
                        ca.FixedArgs = new CustomAttrib.FixedArg [ctor.Parameters.Count];
 
611
                        for (int i = 0; i < ca.FixedArgs.Length && read; i++)
 
612
                                ca.FixedArgs [i] = ReadFixedArg (data, br,
 
613
                                        ctor.Parameters [i].ParameterType, ref read, resolve);
 
614
 
 
615
                        if (br.BaseStream.Position == br.BaseStream.Length)
 
616
                                read = false;
 
617
 
 
618
                        if (!read) {
 
619
                                ca.Read = read;
 
620
                                return ca;
 
621
                        }
 
622
 
 
623
                        ca.NumNamed = br.ReadUInt16 ();
 
624
                        ca.NamedArgs = new CustomAttrib.NamedArg [ca.NumNamed];
 
625
                        for (int i = 0; i < ca.NumNamed && read; i++)
 
626
                                ca.NamedArgs [i] = ReadNamedArg (data, br, ref read, resolve);
 
627
 
 
628
                        ca.Read = read;
 
629
                        return ca;
 
630
                }
 
631
 
 
632
                CustomAttrib.FixedArg ReadFixedArg (byte [] data, BinaryReader br,
 
633
                        TypeReference param, ref bool read, bool resolve)
 
634
                {
 
635
                        CustomAttrib.FixedArg fa = new CustomAttrib.FixedArg ();
 
636
                        if (param is ArrayType) {
 
637
                                param = ((ArrayType) param).ElementType;
 
638
                                fa.SzArray = true;
 
639
                                fa.NumElem = br.ReadUInt32 ();
 
640
 
 
641
                                if (fa.NumElem == 0 || fa.NumElem == 0xffffffff) {
 
642
                                        fa.Elems = new CustomAttrib.Elem [0];
 
643
                                        fa.NumElem = 0;
 
644
                                        return fa;
 
645
                                }
 
646
 
 
647
                                fa.Elems = new CustomAttrib.Elem [fa.NumElem];
 
648
                                for (int i = 0; i < fa.NumElem; i++)
 
649
                                        fa.Elems [i] = ReadElem (data, br, param, ref read, resolve);
 
650
                        } else
 
651
                                fa.Elems = new CustomAttrib.Elem [] { ReadElem (data, br, param, ref read, resolve) };
 
652
 
 
653
                        return fa;
 
654
                }
 
655
 
 
656
                TypeReference CreateEnumTypeReference (string enumName)
 
657
                {
 
658
                        string asmName = null;
 
659
                        int asmStart = enumName.IndexOf (',');
 
660
                        if (asmStart != -1) {
 
661
                                asmName = enumName.Substring (asmStart + 1);
 
662
                                enumName = enumName.Substring (0, asmStart);
 
663
                        }
 
664
                        // Inner class style is reflection style.
 
665
                        enumName = enumName.Replace ('+', '/');
 
666
                        AssemblyNameReference asm;
 
667
                        if (asmName == null) {
 
668
                                // If no assembly is given then the ECMA standard says the
 
669
                                // assembly is either the current one or mscorlib.
 
670
                                if (m_reflectReader.Module.Types.Contains (enumName))
 
671
                                        return m_reflectReader.Module.Types [enumName];
 
672
 
 
673
                                asm = m_reflectReader.Corlib;
 
674
                        } else
 
675
                                asm = AssemblyNameReference.Parse (asmName);
 
676
 
 
677
                        string [] outers = enumName.Split ('/');
 
678
                        string outerfullname = outers [0];
 
679
                        string ns = null;
 
680
                        int nsIndex = outerfullname.LastIndexOf ('.');
 
681
                        if (nsIndex != -1)
 
682
                                ns = outerfullname.Substring (0, nsIndex);
 
683
                        string name = outerfullname.Substring (nsIndex + 1);
 
684
                        TypeReference decType = new TypeReference (name, ns, asm);
 
685
                        for (int i = 1; i < outers.Length; i++) {
 
686
                                TypeReference t = new TypeReference (outers [i], null, asm);
 
687
                                t.DeclaringType = decType;
 
688
                                decType = t;
 
689
                        }
 
690
                        decType.IsValueType = true;
 
691
 
 
692
                        return decType;
 
693
                }
 
694
 
 
695
                TypeReference ReadTypeReference (byte [] data, BinaryReader br, out ElementType elemType)
 
696
                {
 
697
                        bool array = false;
 
698
                        elemType = (ElementType) br.ReadByte ();
 
699
                        if (elemType == ElementType.SzArray) {
 
700
                                elemType = (ElementType) br.ReadByte ();
 
701
                                array = true;
 
702
                        }
 
703
 
 
704
                        TypeReference res;
 
705
                        if (elemType == ElementType.Enum)
 
706
                                res = CreateEnumTypeReference (ReadUTF8String (data, br));
 
707
                        else
 
708
                                res = TypeReferenceFromElemType (elemType);
 
709
 
 
710
                        if (array)
 
711
                                res = new ArrayType (res);
 
712
 
 
713
                        return res;
 
714
                }
 
715
 
 
716
                TypeReference TypeReferenceFromElemType (ElementType elemType)
 
717
                {
 
718
                        switch (elemType) {
 
719
                        case ElementType.Boxed :
 
720
                                return m_reflectReader.SearchCoreType (Constants.Object);
 
721
                        case ElementType.String :
 
722
                                return m_reflectReader.SearchCoreType (Constants.String);
 
723
                        case ElementType.Type :
 
724
                                return m_reflectReader.SearchCoreType (Constants.Type);
 
725
                        case ElementType.Boolean :
 
726
                                return m_reflectReader.SearchCoreType (Constants.Boolean);
 
727
                        case ElementType.Char :
 
728
                                return m_reflectReader.SearchCoreType (Constants.Char);
 
729
                        case ElementType.R4 :
 
730
                                return m_reflectReader.SearchCoreType (Constants.Single);
 
731
                        case ElementType.R8 :
 
732
                                return m_reflectReader.SearchCoreType (Constants.Double);
 
733
                        case ElementType.I1 :
 
734
                                return m_reflectReader.SearchCoreType (Constants.SByte);
 
735
                        case ElementType.I2 :
 
736
                                return m_reflectReader.SearchCoreType (Constants.Int16);
 
737
                        case ElementType.I4 :
 
738
                                return m_reflectReader.SearchCoreType (Constants.Int32);
 
739
                        case ElementType.I8 :
 
740
                                return m_reflectReader.SearchCoreType (Constants.Int64);
 
741
                        case ElementType.U1 :
 
742
                                return m_reflectReader.SearchCoreType (Constants.Byte);
 
743
                        case ElementType.U2 :
 
744
                                return m_reflectReader.SearchCoreType (Constants.UInt16);
 
745
                        case ElementType.U4 :
 
746
                                return m_reflectReader.SearchCoreType (Constants.UInt32);
 
747
                        case ElementType.U8 :
 
748
                                return m_reflectReader.SearchCoreType (Constants.UInt64);
 
749
                        default :
 
750
                                throw new MetadataFormatException ("Non valid type in CustomAttrib.Elem: 0x{0}",
 
751
                                        ((byte) elemType).ToString("x2"));
 
752
                        }
 
753
                }
 
754
 
 
755
                internal CustomAttrib.NamedArg ReadNamedArg (byte [] data, BinaryReader br, ref bool read, bool resolve)
 
756
                {
 
757
                        CustomAttrib.NamedArg na = new CustomAttrib.NamedArg ();
 
758
                        byte kind = br.ReadByte ();
 
759
                        if (kind == 0x53) { // field
 
760
                                na.Field = true;
 
761
                                na.Property = false;
 
762
                        } else if (kind == 0x54) { // property
 
763
                                na.Field = false;
 
764
                                na.Property = true;
 
765
                        } else
 
766
                                throw new MetadataFormatException ("Wrong kind of namedarg found: 0x" + kind.ToString("x2"));
 
767
 
 
768
                        TypeReference elemType = ReadTypeReference (data, br, out na.FieldOrPropType);
 
769
                        na.FieldOrPropName = ReadUTF8String (data, br);
 
770
                        na.FixedArg = ReadFixedArg (data, br, elemType, ref read, resolve);
 
771
 
 
772
                        return na;
 
773
                }
 
774
 
 
775
                CustomAttrib.Elem ReadElem (byte [] data, BinaryReader br, TypeReference elemType, ref bool read, bool resolve)
 
776
                {
 
777
                        CustomAttrib.Elem elem = new CustomAttrib.Elem ();
 
778
 
 
779
                        string elemName = elemType.FullName;
 
780
 
 
781
                        if (elemName == Constants.Object) {
 
782
                                elemType = ReadTypeReference (data, br, out elem.FieldOrPropType);
 
783
                                if (elemType is ArrayType) {
 
784
                                        read = false; // Don't know how to represent arrays as an object value.
 
785
                                        return elem;
 
786
                                } else if (elemType.FullName == Constants.Object)
 
787
                                        throw new MetadataFormatException ("Non valid type in CustomAttrib.Elem after boxed prefix: 0x{0}",
 
788
                                                ((byte) elem.FieldOrPropType).ToString("x2"));
 
789
 
 
790
                                elem = ReadElem (data, br, elemType, ref read, resolve);
 
791
                                elem.String = elem.Simple = elem.Type = false;
 
792
                                elem.BoxedValueType = true;
 
793
                                return elem;
 
794
                        }
 
795
 
 
796
                        elem.ElemType = elemType;
 
797
 
 
798
                        if (elemName == Constants.Type || elemName == Constants.String) {
 
799
                                switch (elemType.FullName) {
 
800
                                case Constants.String:
 
801
                                        elem.String = true;
 
802
                                        elem.BoxedValueType = elem.Simple = elem.Type = false;
 
803
                                        break;
 
804
                                case Constants.Type:
 
805
                                        elem.Type = true;
 
806
                                        elem.BoxedValueType = elem.Simple = elem.String = false;
 
807
                                        break;
 
808
                                }
 
809
 
 
810
                                if (data [br.BaseStream.Position] == 0xff) { // null
 
811
                                        elem.Value = null;
 
812
                                        br.BaseStream.Position++;
 
813
                                } else {
 
814
                                        elem.Value = ReadUTF8String (data, br);
 
815
                                }
 
816
                                return elem;
 
817
                        }
 
818
 
 
819
                        elem.String = elem.Type = elem.BoxedValueType = false;
 
820
                        if (!ReadSimpleValue (br, ref elem, elem.ElemType)) {
 
821
                                if (!resolve) { // until enums writing is implemented
 
822
                                        read = false;
 
823
                                        return elem;
 
824
                                }
 
825
                                TypeReference typeRef = GetEnumUnderlyingType (elem.ElemType, resolve);
 
826
                                if (typeRef == null || !ReadSimpleValue (br, ref elem, typeRef))
 
827
                                        read = false;
 
828
                        }
 
829
 
 
830
                        return elem;
 
831
                }
 
832
 
 
833
                TypeReference GetEnumUnderlyingType (TypeReference enumType, bool resolve)
 
834
                {
 
835
                        TypeDefinition type = enumType as TypeDefinition;
 
836
                        if (type == null && resolve && AssemblyResolver != null) {
 
837
                                if (enumType.Scope is ModuleDefinition)
 
838
                                        throw new NotSupportedException ();
 
839
 
 
840
                                AssemblyDefinition asm = AssemblyResolver.Resolve (
 
841
                                        ((AssemblyNameReference) enumType.Scope).FullName);
 
842
                                type = asm.MainModule.Types [enumType.FullName];
 
843
                        }
 
844
 
 
845
                        if (type != null && type.IsEnum)
 
846
                                return type.Fields.GetField ("value__").FieldType;
 
847
 
 
848
                        return null;
 
849
                }
 
850
 
 
851
                bool ReadSimpleValue (BinaryReader br, ref CustomAttrib.Elem elem, TypeReference type)
 
852
                {
 
853
                        switch (type.FullName) {
 
854
                        case Constants.Boolean :
 
855
                                elem.Value = br.ReadByte () == 1;
 
856
                                break;
 
857
                        case Constants.Char :
 
858
                                elem.Value = (char) br.ReadUInt16 ();
 
859
                                break;
 
860
                        case Constants.Single :
 
861
                                elem.Value = br.ReadSingle ();
 
862
                                break;
 
863
                        case Constants.Double :
 
864
                                elem.Value = br.ReadDouble ();
 
865
                                break;
 
866
                        case Constants.Byte :
 
867
                                elem.Value = br.ReadByte ();
 
868
                                break;
 
869
                        case Constants.Int16 :
 
870
                                elem.Value = br.ReadInt16 ();
 
871
                                break;
 
872
                        case Constants.Int32 :
 
873
                                elem.Value = br.ReadInt32 ();
 
874
                                break;
 
875
                        case Constants.Int64 :
 
876
                                elem.Value = br.ReadInt64 ();
 
877
                                break;
 
878
                        case Constants.SByte :
 
879
                                elem.Value = br.ReadSByte ();
 
880
                                break;
 
881
                        case Constants.UInt16 :
 
882
                                elem.Value = br.ReadUInt16 ();
 
883
                                break;
 
884
                        case Constants.UInt32 :
 
885
                                elem.Value = br.ReadUInt32 ();
 
886
                                break;
 
887
                        case Constants.UInt64 :
 
888
                                elem.Value = br.ReadUInt64 ();
 
889
                                break;
 
890
                        default : // enum
 
891
                                return false;
 
892
                        }
 
893
                        elem.Simple = true;
 
894
                        return true;
 
895
                }
 
896
 
 
897
                MarshalSig ReadMarshalSig (byte [] data)
 
898
                {
 
899
                        int start;
 
900
                        MarshalSig ms = new MarshalSig ((NativeType) Utilities.ReadCompressedInteger (data, 0, out start));
 
901
                        switch (ms.NativeInstrinsic) {
 
902
                        case NativeType.ARRAY:
 
903
                                MarshalSig.Array ar = new MarshalSig.Array ();
 
904
                                ar.ArrayElemType = (NativeType) Utilities.ReadCompressedInteger (data, start, out start);
 
905
                                if (start < data.Length)
 
906
                                        ar.ParamNum = Utilities.ReadCompressedInteger (data, start, out start);
 
907
                                if (start < data.Length)
 
908
                                        ar.NumElem = Utilities.ReadCompressedInteger (data, start, out start);
 
909
                                if (start < data.Length)
 
910
                                        ar.ElemMult = Utilities.ReadCompressedInteger (data, start, out start);
 
911
                                ms.Spec = ar;
 
912
                                break;
 
913
                        case NativeType.CUSTOMMARSHALER:
 
914
                                MarshalSig.CustomMarshaler cm = new MarshalSig.CustomMarshaler ();
 
915
                                cm.Guid = ReadUTF8String (data, start, out start);
 
916
                                cm.UnmanagedType = ReadUTF8String (data, start, out start);
 
917
                                cm.ManagedType = ReadUTF8String (data, start, out start);
 
918
                                cm.Cookie = ReadUTF8String (data, start, out start);
 
919
                                ms.Spec = cm;
 
920
                                break;
 
921
                        case NativeType.FIXEDARRAY:
 
922
                                MarshalSig.FixedArray fa = new MarshalSig.FixedArray ();
 
923
                                fa.NumElem = Utilities.ReadCompressedInteger (data, start, out start);
 
924
                                if (start < data.Length)
 
925
                                        fa.ArrayElemType = (NativeType) Utilities.ReadCompressedInteger (data, start, out start);
 
926
                                ms.Spec = fa;
 
927
                                break;
 
928
                        case NativeType.SAFEARRAY:
 
929
                                MarshalSig.SafeArray sa = new MarshalSig.SafeArray ();
 
930
                                if (start < data.Length)
 
931
                                        sa.ArrayElemType = (VariantType) Utilities.ReadCompressedInteger (data, start, out start);
 
932
                                ms.Spec = sa;
 
933
                                break;
 
934
                        case NativeType.FIXEDSYSSTRING:
 
935
                                MarshalSig.FixedSysString fss = new MarshalSig.FixedSysString ();
 
936
                                if (start < data.Length)
 
937
                                        fss.Size = Utilities.ReadCompressedInteger (data, start, out start);
 
938
                                ms.Spec = fss;
 
939
                                break;
 
940
                        }
 
941
                        return ms;
 
942
                }
 
943
 
 
944
                static internal string ReadUTF8String (byte [] data, BinaryReader br)
 
945
                {
 
946
                        int start = (int)br.BaseStream.Position;
 
947
                        string val = ReadUTF8String (data, start, out start);
 
948
                        br.BaseStream.Position = start;
 
949
                        return val;
 
950
                }
 
951
 
 
952
                static internal string ReadUTF8String (byte [] data, int pos, out int start)
 
953
                {
 
954
                        int length = Utilities.ReadCompressedInteger (data, pos, out start);
 
955
                        pos = start;
 
956
                        start += length;
 
957
                        // COMPACT FRAMEWORK NOTE: Encoding.GetString (byte[]) is not supported.
 
958
                        return Encoding.UTF8.GetString (data, pos, length);
 
959
                }
 
960
        }
 
961
}