5
// Jb Evain (jbevain@gmail.com)
7
// (C) 2005 - 2007 Jb Evain
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.Signatures {
32
using System.Collections;
37
using Mono.Cecil.Metadata;
39
internal sealed class SignatureReader : BaseSignatureVisitor {
42
ReflectionReader m_reflectReader;
45
IDictionary m_signatures;
47
IAssemblyResolver AssemblyResolver {
48
get { return m_reflectReader.Module.Assembly.Resolver; }
51
public SignatureReader (MetadataRoot root, ReflectionReader reflectReader)
54
m_reflectReader = reflectReader;
56
m_blobData = m_root.Streams.BlobHeap != null ? m_root.Streams.BlobHeap.Data : new byte [0];
58
m_signatures = new Hashtable ();
61
public FieldSig GetFieldSig (uint index)
63
FieldSig f = m_signatures [index] as FieldSig;
65
f = new FieldSig (index);
67
m_signatures [index] = f;
72
public PropertySig GetPropSig (uint index)
74
PropertySig p = m_signatures [index] as PropertySig;
76
p = new PropertySig (index);
78
m_signatures [index] = p;
83
public MethodDefSig GetMethodDefSig (uint index)
85
MethodDefSig m = m_signatures [index] as MethodDefSig;
87
m = new MethodDefSig (index);
89
m_signatures [index] = m;
94
public MethodRefSig GetMethodRefSig (uint index)
96
MethodRefSig m = m_signatures [index] as MethodRefSig;
98
m = new MethodRefSig (index);
100
m_signatures [index] = m;
105
public TypeSpec GetTypeSpec (uint index)
107
TypeSpec ts = m_signatures [index] as TypeSpec;
110
ts = ReadTypeSpec (m_blobData, (int) index);
111
m_signatures [index] = ts;
117
public MethodSpec GetMethodSpec (uint index)
119
MethodSpec ms = m_signatures [index] as MethodSpec;
122
ms = ReadMethodSpec (m_blobData, (int) index);
123
m_signatures [index] = ms;
129
public LocalVarSig GetLocalVarSig (uint index)
131
LocalVarSig lv = m_signatures [index] as LocalVarSig;
133
lv = new LocalVarSig (index);
135
m_signatures [index] = lv;
140
public CustomAttrib GetCustomAttrib (uint index, MethodReference ctor)
142
return GetCustomAttrib (index, ctor, false);
145
public CustomAttrib GetCustomAttrib (uint index, MethodReference ctor, bool resolve)
147
return ReadCustomAttrib ((int) index, ctor, resolve);
150
public CustomAttrib GetCustomAttrib (byte [] data, MethodReference ctor)
152
return GetCustomAttrib (data, ctor, false);
155
public CustomAttrib GetCustomAttrib (byte [] data, MethodReference ctor, bool resolve)
157
BinaryReader br = new BinaryReader (new MemoryStream (data));
158
return ReadCustomAttrib (br, data, ctor, resolve);
161
public Signature GetMemberRefSig (TokenType tt, uint index)
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);
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);
183
public MarshalSig GetMarshalSig (uint index)
185
MarshalSig ms = m_signatures [index] as MarshalSig;
187
byte [] data = m_root.Streams.BlobHeap.Read (index);
188
ms = ReadMarshalSig (data);
189
m_signatures [index] = ms;
194
public MethodSig GetStandAloneMethodSig (uint index)
196
byte [] data = m_root.Streams.BlobHeap.Read (index);
198
if ((data [0] & 0x5) > 0) {
199
MethodRefSig mrs = new MethodRefSig (index);
200
ReadMethodRefSig (mrs, data, 0, out start);
203
MethodDefSig mds = new MethodDefSig (index);
204
ReadMethodDefSig (mds, data, 0, out start);
209
public override void VisitMethodDefSig (MethodDefSig methodDef)
212
ReadMethodDefSig (methodDef, m_root.Streams.BlobHeap.Read (methodDef.BlobIndex), 0, out start);
215
public override void VisitMethodRefSig (MethodRefSig methodRef)
218
ReadMethodRefSig (methodRef, m_root.Streams.BlobHeap.Read (methodRef.BlobIndex), 0, out start);
221
public override void VisitFieldSig (FieldSig field)
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);
231
public override void VisitPropertySig (PropertySig property)
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, out start);
243
public override void VisitLocalVarSig (LocalVarSig localvar)
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);
253
void ReadMethodDefSig (MethodDefSig methodDef, byte [] data, int pos, out int start)
255
methodDef.CallingConvention = data [pos];
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);
265
methodDef.MethCallConv |= MethodCallingConvention.Default;
267
methodDef.ParamCount = Utilities.ReadCompressedInteger (data, start, out start);
268
methodDef.RetType = ReadRetType (data, start, out start);
270
methodDef.Parameters = ReadParameters (methodDef.ParamCount, data, start, out start, out sentpos);
271
methodDef.Sentinel = sentpos;
274
void ReadMethodRefSig (MethodRefSig methodRef, byte [] data, int pos, out int start)
276
methodRef.CallingConvention = data [pos];
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;
291
methodRef.MethCallConv |= MethodCallingConvention.Default;
292
methodRef.ParamCount = Utilities.ReadCompressedInteger (data, start, out start);
293
methodRef.RetType = ReadRetType (data, start, out start);
295
methodRef.Parameters = ReadParameters (methodRef.ParamCount, data, start, out start, out sentpos);
296
methodRef.Sentinel = sentpos;
299
LocalVarSig.LocalVariable [] ReadLocalVariables (int length, byte [] data, int 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);
308
LocalVarSig.LocalVariable ReadLocalVariable (byte [] data, int pos, out int start)
311
LocalVarSig.LocalVariable lv = new LocalVarSig.LocalVariable ();
315
lv.CustomMods = ReadCustomMods (data, start, out 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) {
323
if (lv.CustomMods == null || lv.CustomMods.Length == 0)
324
lv.CustomMods = ReadCustomMods (data, start, out start);
326
lv.Type = ReadType (data, cursor, out start);
333
TypeSpec ReadTypeSpec (byte [] data, int 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);
343
MethodSpec ReadMethodSpec (byte [] data, int pos)
347
Utilities.ReadCompressedInteger (data, start, out start);
348
if (Utilities.ReadCompressedInteger (data, start, out start) != 0x0a)
349
throw new ReflectionException ("Invalid MethodSpec signature");
351
return new MethodSpec (ReadGenericInstSignature (data, start, out start));
354
RetType ReadRetType (byte [] data, int pos, out int start)
356
RetType rt = new RetType ();
358
rt.CustomMods = ReadCustomMods (data, start, out start);
360
ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
362
case ElementType.Void :
363
rt.ByRef = rt.TypedByRef = false;
366
case ElementType.TypedByRef :
367
rt.ByRef = rt.Void = false;
368
rt.TypedByRef = true;
370
case ElementType.ByRef :
371
rt.TypedByRef = rt.Void = false;
373
rt.CustomMods = CombineCustomMods(rt.CustomMods, ReadCustomMods (data, start, out start));
374
rt.Type = ReadType (data, start, out start);
377
rt.TypedByRef = rt.Void = rt.ByRef = false;
378
rt.Type = ReadType (data, curs, out start);
385
static CustomMod [] CombineCustomMods (CustomMod [] original, CustomMod [] next)
387
if (next == null || next.Length == 0)
390
CustomMod [] mods = new CustomMod [original.Length + next.Length];
391
Array.Copy (original, mods, original.Length);
392
Array.Copy (next, 0, mods, original.Length, next.Length);
396
Param [] ReadParameters (int length, byte [] data, int pos, out int start)
398
Param [] ret = new Param [length];
400
for (int i = 0; i < length; i++)
401
ret [i] = ReadParameter (data, start, out start);
405
Param [] ReadParameters (int length, byte [] data, int pos, out int start, out int sentinelpos)
407
Param [] ret = new Param [length];
411
for (int i = 0; i < length; i++) {
413
int flag = Utilities.ReadCompressedInteger (data, start, out start);
415
if (flag == (int) ElementType.Sentinel) {
420
ret [i] = ReadParameter (data, curs, out start);
426
Param ReadParameter (byte [] data, int pos, out int start)
428
Param p = new Param ();
431
p.CustomMods = ReadCustomMods (data, start, out start);
433
ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
435
case ElementType.TypedByRef :
439
case ElementType.ByRef :
440
p.TypedByRef = false;
443
if (p.CustomMods == null || p.CustomMods.Length == 0)
444
p.CustomMods = ReadCustomMods (data, start, out start);
446
p.Type = ReadType (data, start, out start);
449
p.TypedByRef = false;
451
p.Type = ReadType (data, curs, out start);
457
SigType ReadType (byte [] data, int pos, out int start)
460
ElementType element = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
462
case ElementType.ValueType :
463
VALUETYPE vt = new VALUETYPE ();
464
vt.Type = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
465
(uint) Utilities.ReadCompressedInteger (data, start, out start));
467
case ElementType.Class :
468
CLASS c = new CLASS ();
469
c.Type = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
470
(uint) Utilities.ReadCompressedInteger (data, start, out start));
472
case ElementType.Ptr :
475
int flag = Utilities.ReadCompressedInteger (data, start, out start);
476
p.Void = flag == (int) ElementType.Void;
480
p.CustomMods = ReadCustomMods (data, start, out start);
481
p.PtrType = ReadType (data, start, out start);
483
case ElementType.FnPtr :
484
FNPTR fp = new FNPTR ();
485
if ((data [start] & 0x5) != 0) {
486
MethodRefSig mr = new MethodRefSig ((uint) start);
487
ReadMethodRefSig (mr, data, start, out start);
490
MethodDefSig md = new MethodDefSig ((uint) start);
491
ReadMethodDefSig (md, data, start, out start);
495
case ElementType.Array :
496
ARRAY ary = new ARRAY ();
497
ary.CustomMods = ReadCustomMods (data, start, out start);
498
ArrayShape shape = new ArrayShape ();
499
ary.Type = ReadType (data, start, out start);
500
shape.Rank = Utilities.ReadCompressedInteger (data, start, out start);
501
shape.NumSizes = Utilities.ReadCompressedInteger (data, start, out start);
502
shape.Sizes = new int [shape.NumSizes];
503
for (int i = 0; i < shape.NumSizes; i++)
504
shape.Sizes [i] = Utilities.ReadCompressedInteger (data, start, out start);
505
shape.NumLoBounds = Utilities.ReadCompressedInteger (data, start, out start);
506
shape.LoBounds = new int [shape.NumLoBounds];
507
for (int i = 0; i < shape.NumLoBounds; i++)
508
shape.LoBounds [i] = Utilities.ReadCompressedInteger (data, start, out start);
511
case ElementType.SzArray :
512
SZARRAY sa = new SZARRAY ();
513
sa.CustomMods = ReadCustomMods (data, start, out start);
514
sa.Type = ReadType (data, start, out start);
516
case ElementType.Var:
517
return new VAR (Utilities.ReadCompressedInteger (data, start, out start));
518
case ElementType.MVar:
519
return new MVAR (Utilities.ReadCompressedInteger (data, start, out start));
520
case ElementType.GenericInst:
521
GENERICINST ginst = new GENERICINST ();
523
ginst.ValueType = ((ElementType) Utilities.ReadCompressedInteger (
524
data, start, out start)) == ElementType.ValueType;
526
ginst.Type = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
527
(uint) Utilities.ReadCompressedInteger (data, start, out start));
529
ginst.Signature = ReadGenericInstSignature (data, start, out start);
533
return new SigType (element);
537
GenericInstSignature ReadGenericInstSignature (byte [] data, int pos, out int start)
540
GenericInstSignature gis = new GenericInstSignature ();
541
gis.Arity = Utilities.ReadCompressedInteger (data, start, out start);
542
gis.Types = new GenericArg [gis.Arity];
543
for (int i = 0; i < gis.Arity; i++)
544
gis.Types [i] = ReadGenericArg (data, start, out start);
549
GenericArg ReadGenericArg (byte[] data, int pos, out int start)
552
CustomMod [] mods = ReadCustomMods (data, start, out start);
553
GenericArg arg = new GenericArg (ReadType (data, start, out start));
554
arg.CustomMods = mods;
558
CustomMod [] ReadCustomMods (byte [] data, int pos, out int start)
560
ArrayList cmods = null;
564
if (buf >= data.Length - 1)
567
ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
569
if (!((flag == ElementType.CModOpt) || (flag == ElementType.CModReqD)))
573
cmods = new ArrayList (2);
575
cmods.Add (ReadCustomMod (data, start, out start));
578
return cmods == null ? CustomMod.EmptyCustomMod : cmods.ToArray (typeof (CustomMod)) as CustomMod [];
581
CustomMod ReadCustomMod (byte [] data, int pos, out int start)
583
CustomMod cm = new CustomMod ();
585
ElementType cmod = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
586
if (cmod == ElementType.CModOpt)
587
cm.CMOD = CustomMod.CMODType.OPT;
588
else if (cmod == ElementType.CModReqD)
589
cm.CMOD = CustomMod.CMODType.REQD;
591
cm.CMOD = CustomMod.CMODType.None;
592
cm.TypeDefOrRef = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
593
(uint) Utilities.ReadCompressedInteger (data, start, out start));
597
CustomAttrib ReadCustomAttrib (int pos, MethodReference ctor, bool resolve)
599
int start, length = Utilities.ReadCompressedInteger (m_blobData, pos, out start);
600
byte [] data = new byte [length];
601
Buffer.BlockCopy (m_blobData, start, data, 0, length);
603
return ReadCustomAttrib (new BinaryReader (
604
new MemoryStream (data)), data, ctor, resolve);
606
CustomAttrib ca = new CustomAttrib (ctor);
612
CustomAttrib ReadCustomAttrib (BinaryReader br, byte [] data, MethodReference ctor, bool resolve)
614
CustomAttrib ca = new CustomAttrib (ctor);
615
if (data.Length == 0) {
616
ca.FixedArgs = CustomAttrib.FixedArg.Empty;
617
ca.NamedArgs = CustomAttrib.NamedArg.Empty;
623
ca.Prolog = br.ReadUInt16 ();
624
if (ca.Prolog != CustomAttrib.StdProlog)
625
throw new MetadataFormatException ("Non standard prolog for custom attribute");
627
if (ctor.HasParameters) {
628
ca.FixedArgs = new CustomAttrib.FixedArg [ctor.Parameters.Count];
629
for (int i = 0; i < ca.FixedArgs.Length && read; i++)
630
ca.FixedArgs [i] = ReadFixedArg (data, br,
631
ctor.Parameters [i].ParameterType, ref read, resolve);
633
ca.FixedArgs = CustomAttrib.FixedArg.Empty;
636
if (br.BaseStream.Position == br.BaseStream.Length)
644
ca.NumNamed = br.ReadUInt16 ();
645
if (ca.NumNamed > 0) {
646
ca.NamedArgs = new CustomAttrib.NamedArg [ca.NumNamed];
647
for (int i = 0; i < ca.NumNamed && read; i++)
648
ca.NamedArgs [i] = ReadNamedArg (data, br, ref read, resolve);
650
ca.NamedArgs = CustomAttrib.NamedArg.Empty;
657
CustomAttrib.FixedArg ReadFixedArg (byte [] data, BinaryReader br,
658
TypeReference param, ref bool read, bool resolve)
660
CustomAttrib.FixedArg fa = new CustomAttrib.FixedArg ();
661
if (param is ArrayType) {
662
param = ((ArrayType) param).ElementType;
664
fa.NumElem = br.ReadUInt32 ();
666
if (fa.NumElem == 0 || fa.NumElem == 0xffffffff) {
667
fa.Elems = new CustomAttrib.Elem [0];
672
fa.Elems = new CustomAttrib.Elem [fa.NumElem];
673
for (int i = 0; i < fa.NumElem; i++)
674
fa.Elems [i] = ReadElem (data, br, param, ref read, resolve);
676
fa.Elems = new CustomAttrib.Elem [] { ReadElem (data, br, param, ref read, resolve) };
681
TypeReference CreateEnumTypeReference (string enumName)
683
string asmName = null;
684
int asmStart = enumName.IndexOf (',');
685
if (asmStart != -1) {
686
asmName = enumName.Substring (asmStart + 1);
687
enumName = enumName.Substring (0, asmStart);
689
// Inner class style is reflection style.
690
enumName = enumName.Replace ('+', '/');
691
AssemblyNameReference asm;
692
if (asmName == null) {
693
// If no assembly is given then the ECMA standard says the
694
// assembly is either the current one or mscorlib.
695
if (m_reflectReader.Module.Types.Contains (enumName))
696
return m_reflectReader.Module.Types [enumName];
698
asm = m_reflectReader.Corlib;
700
asm = AssemblyNameReference.Parse (asmName);
702
string [] outers = enumName.Split ('/');
703
string outerfullname = outers [0];
705
int nsIndex = outerfullname.LastIndexOf ('.');
707
ns = outerfullname.Substring (0, nsIndex);
708
string name = outerfullname.Substring (nsIndex + 1);
709
TypeReference decType = new TypeReference (name, ns, asm);
710
for (int i = 1; i < outers.Length; i++) {
711
TypeReference t = new TypeReference (outers [i], null, asm);
712
t.Module = m_reflectReader.Module;
713
t.DeclaringType = decType;
716
decType.Module = m_reflectReader.Module;
717
decType.IsValueType = true;
722
TypeReference ReadTypeReference (byte [] data, BinaryReader br, out ElementType elemType)
725
elemType = (ElementType) br.ReadByte ();
726
if (elemType == ElementType.SzArray) {
727
elemType = (ElementType) br.ReadByte ();
732
if (elemType == ElementType.Enum)
733
res = CreateEnumTypeReference (ReadUTF8String (data, br));
735
res = TypeReferenceFromElemType (elemType);
738
res = new ArrayType (res);
743
TypeReference TypeReferenceFromElemType (ElementType elemType)
746
case ElementType.Boxed :
747
case ElementType.Object:
748
return m_reflectReader.SearchCoreType (Constants.Object);
749
case ElementType.String :
750
return m_reflectReader.SearchCoreType (Constants.String);
751
case ElementType.Type :
752
return m_reflectReader.SearchCoreType (Constants.Type);
753
case ElementType.Boolean :
754
return m_reflectReader.SearchCoreType (Constants.Boolean);
755
case ElementType.Char :
756
return m_reflectReader.SearchCoreType (Constants.Char);
757
case ElementType.R4 :
758
return m_reflectReader.SearchCoreType (Constants.Single);
759
case ElementType.R8 :
760
return m_reflectReader.SearchCoreType (Constants.Double);
761
case ElementType.I1 :
762
return m_reflectReader.SearchCoreType (Constants.SByte);
763
case ElementType.I2 :
764
return m_reflectReader.SearchCoreType (Constants.Int16);
765
case ElementType.I4 :
766
return m_reflectReader.SearchCoreType (Constants.Int32);
767
case ElementType.I8 :
768
return m_reflectReader.SearchCoreType (Constants.Int64);
769
case ElementType.U1 :
770
return m_reflectReader.SearchCoreType (Constants.Byte);
771
case ElementType.U2 :
772
return m_reflectReader.SearchCoreType (Constants.UInt16);
773
case ElementType.U4 :
774
return m_reflectReader.SearchCoreType (Constants.UInt32);
775
case ElementType.U8 :
776
return m_reflectReader.SearchCoreType (Constants.UInt64);
778
throw new MetadataFormatException ("Non valid type in CustomAttrib.Elem: 0x{0}",
779
((byte) elemType).ToString("x2"));
783
internal CustomAttrib.NamedArg ReadNamedArg (byte [] data, BinaryReader br, ref bool read, bool resolve)
785
CustomAttrib.NamedArg na = new CustomAttrib.NamedArg ();
786
byte kind = br.ReadByte ();
787
if (kind == 0x53) { // field
790
} else if (kind == 0x54) { // property
794
throw new MetadataFormatException ("Wrong kind of namedarg found: 0x" + kind.ToString("x2"));
796
TypeReference elemType = ReadTypeReference (data, br, out na.FieldOrPropType);
797
na.FieldOrPropName = ReadUTF8String (data, br);
798
na.FixedArg = ReadFixedArg (data, br, elemType, ref read, resolve);
803
CustomAttrib.Elem ReadElem (byte [] data, BinaryReader br, TypeReference elemType, ref bool read, bool resolve)
805
CustomAttrib.Elem elem = new CustomAttrib.Elem ();
807
string elemName = elemType.FullName;
809
if (elemName == Constants.Object) {
810
elemType = ReadTypeReference (data, br, out elem.FieldOrPropType);
811
if (elemType is ArrayType) {
812
read = false; // Don't know how to represent arrays as an object value.
814
} else if (elemType.FullName == Constants.Object)
815
throw new MetadataFormatException ("Non valid type in CustomAttrib.Elem after boxed prefix: 0x{0}",
816
((byte) elem.FieldOrPropType).ToString ("x2"));
818
elem = ReadElem (data, br, elemType, ref read, resolve);
819
elem.String = elem.Simple = elem.Type = false;
820
elem.BoxedValueType = true;
824
elem.ElemType = elemType;
826
if (elemName == Constants.Type || elemName == Constants.String) {
827
switch (elemType.FullName) {
828
case Constants.String:
830
elem.BoxedValueType = elem.Simple = elem.Type = false;
834
elem.BoxedValueType = elem.Simple = elem.String = false;
838
if (data [br.BaseStream.Position] == 0xff) { // null
840
br.BaseStream.Position++;
842
elem.Value = ReadUTF8String (data, br);
847
elem.String = elem.Type = elem.BoxedValueType = false;
848
if (!ReadSimpleValue (br, ref elem, elem.ElemType)) {
849
if (!resolve) { // until enums writing is implemented
853
TypeReference typeRef = GetEnumUnderlyingType (elem.ElemType, resolve);
854
if (typeRef == null || !ReadSimpleValue (br, ref elem, typeRef))
861
TypeReference GetEnumUnderlyingType (TypeReference enumType, bool resolve)
863
TypeDefinition type = enumType as TypeDefinition;
864
if (type == null && resolve && AssemblyResolver != null) {
865
if (enumType.Scope is ModuleDefinition)
866
throw new NotSupportedException ();
868
AssemblyDefinition asm = AssemblyResolver.Resolve (
869
((AssemblyNameReference) enumType.Scope).FullName);
872
type = asm.MainModule.Types [enumType.FullName];
875
if (type != null && type.IsEnum)
876
return type.Fields.GetField ("value__").FieldType;
881
bool ReadSimpleValue (BinaryReader br, ref CustomAttrib.Elem elem, TypeReference type)
883
switch (type.FullName) {
884
case Constants.Boolean :
885
elem.Value = br.ReadByte () == 1;
887
case Constants.Char :
888
elem.Value = (char) br.ReadUInt16 ();
890
case Constants.Single :
891
elem.Value = br.ReadSingle ();
893
case Constants.Double :
894
elem.Value = br.ReadDouble ();
896
case Constants.Byte :
897
elem.Value = br.ReadByte ();
899
case Constants.Int16 :
900
elem.Value = br.ReadInt16 ();
902
case Constants.Int32 :
903
elem.Value = br.ReadInt32 ();
905
case Constants.Int64 :
906
elem.Value = br.ReadInt64 ();
908
case Constants.SByte :
909
elem.Value = br.ReadSByte ();
911
case Constants.UInt16 :
912
elem.Value = br.ReadUInt16 ();
914
case Constants.UInt32 :
915
elem.Value = br.ReadUInt32 ();
917
case Constants.UInt64 :
918
elem.Value = br.ReadUInt64 ();
927
MarshalSig ReadMarshalSig (byte [] data)
930
MarshalSig ms = new MarshalSig ((NativeType) Utilities.ReadCompressedInteger (data, 0, out start));
931
switch (ms.NativeInstrinsic) {
932
case NativeType.ARRAY:
933
MarshalSig.Array ar = new MarshalSig.Array ();
934
ar.ArrayElemType = (NativeType) Utilities.ReadCompressedInteger (data, start, out start);
935
if (start < data.Length)
936
ar.ParamNum = Utilities.ReadCompressedInteger (data, start, out start);
937
if (start < data.Length)
938
ar.NumElem = Utilities.ReadCompressedInteger (data, start, out start);
939
if (start < data.Length)
940
ar.ElemMult = Utilities.ReadCompressedInteger (data, start, out start);
943
case NativeType.CUSTOMMARSHALER:
944
MarshalSig.CustomMarshaler cm = new MarshalSig.CustomMarshaler ();
945
cm.Guid = ReadUTF8String (data, start, out start);
946
cm.UnmanagedType = ReadUTF8String (data, start, out start);
947
cm.ManagedType = ReadUTF8String (data, start, out start);
948
cm.Cookie = ReadUTF8String (data, start, out start);
951
case NativeType.FIXEDARRAY:
952
MarshalSig.FixedArray fa = new MarshalSig.FixedArray ();
953
fa.NumElem = Utilities.ReadCompressedInteger (data, start, out start);
954
if (start < data.Length)
955
fa.ArrayElemType = (NativeType) Utilities.ReadCompressedInteger (data, start, out start);
958
case NativeType.SAFEARRAY:
959
MarshalSig.SafeArray sa = new MarshalSig.SafeArray ();
960
if (start < data.Length)
961
sa.ArrayElemType = (VariantType) Utilities.ReadCompressedInteger (data, start, out start);
964
case NativeType.FIXEDSYSSTRING:
965
MarshalSig.FixedSysString fss = new MarshalSig.FixedSysString ();
966
if (start < data.Length)
967
fss.Size = Utilities.ReadCompressedInteger (data, start, out start);
974
static internal string ReadUTF8String (byte [] data, BinaryReader br)
976
int start = (int)br.BaseStream.Position;
977
string val = ReadUTF8String (data, start, out start);
978
br.BaseStream.Position = start;
982
static internal string ReadUTF8String (byte [] data, int pos, out int start)
984
int length = Utilities.ReadCompressedInteger (data, pos, out start);
987
// COMPACT FRAMEWORK NOTE: Encoding.GetString (byte[]) is not supported.
988
return Encoding.UTF8.GetString (data, pos, length);