using System;
using Mono.PEToolkit;
using Mono.PEToolkit.Metadata;
using System.Reflection.Emit;
using Rail.MSIL;
using System.Runtime.InteropServices;
namespace Rail.Reflect{
/// <summary>
/// This class is used to map opcodes into OpCode objects.
/// </summary>
public class OpCodesList
{
/// <summary>
///
/// </summary>
public static OpCode[] OneByteCode;
/// <summary>
///
/// </summary>
public static OpCode[] TwoByteCode;
/// <summary>
///
/// </summary>
static OpCodesList()
{
OneByteCode = new OpCode[256];
TwoByteCode = new OpCode[30];
OneByteCode[0] = OpCodes.Nop;
OneByteCode[1] = OpCodes.Break;
OneByteCode[2] = OpCodes.Ldarg_0;
OneByteCode[3] = OpCodes.Ldarg_1;
OneByteCode[4] = OpCodes.Ldarg_2;
OneByteCode[5] = OpCodes.Ldarg_3;
OneByteCode[6] = OpCodes.Ldloc_0;
OneByteCode[7] = OpCodes.Ldloc_1;
OneByteCode[8] = OpCodes.Ldloc_2;
OneByteCode[9] = OpCodes.Ldloc_3;
OneByteCode[10] = OpCodes.Stloc_0;
OneByteCode[11] = OpCodes.Stloc_1;
OneByteCode[12] = OpCodes.Stloc_2;
OneByteCode[13] = OpCodes.Stloc_3;
OneByteCode[14] = OpCodes.Ldarg_S;
OneByteCode[15] = OpCodes.Ldarga_S;
OneByteCode[16] = OpCodes.Starg_S;
OneByteCode[17] = OpCodes.Ldloc_S;
OneByteCode[18] = OpCodes.Ldloca_S;
OneByteCode[19] = OpCodes.Stloc_S;
OneByteCode[20] = OpCodes.Ldnull;
OneByteCode[21] = OpCodes.Ldc_I4_M1;
OneByteCode[22] = OpCodes.Ldc_I4_0;
OneByteCode[23] = OpCodes.Ldc_I4_1;
OneByteCode[24] = OpCodes.Ldc_I4_2;
OneByteCode[25] = OpCodes.Ldc_I4_3;
OneByteCode[26] = OpCodes.Ldc_I4_4;
OneByteCode[27] = OpCodes.Ldc_I4_5;
OneByteCode[28] = OpCodes.Ldc_I4_6;
OneByteCode[29] = OpCodes.Ldc_I4_7;
OneByteCode[30] = OpCodes.Ldc_I4_8;
OneByteCode[31] = OpCodes.Ldc_I4_S;
OneByteCode[32] = OpCodes.Ldc_I4;
OneByteCode[33] = OpCodes.Ldc_I8;
OneByteCode[34] = OpCodes.Ldc_R4;
OneByteCode[35] = OpCodes.Ldc_R8;
OneByteCode[37] = OpCodes.Dup;
OneByteCode[38] = OpCodes.Pop;
OneByteCode[39] = OpCodes.Jmp;
OneByteCode[40] = OpCodes.Call;
OneByteCode[41] = OpCodes.Calli;
OneByteCode[42] = OpCodes.Ret;
OneByteCode[43] = OpCodes.Br_S;
OneByteCode[44] = OpCodes.Brfalse_S;
OneByteCode[45] = OpCodes.Brtrue_S;
OneByteCode[46] = OpCodes.Beq_S;
OneByteCode[47] = OpCodes.Bge_S;
OneByteCode[48] = OpCodes.Bgt_S;
OneByteCode[49] = OpCodes.Ble_S;
OneByteCode[50] = OpCodes.Blt_S;
OneByteCode[51] = OpCodes.Bne_Un_S;
OneByteCode[52] = OpCodes.Bge_Un_S;
OneByteCode[53] = OpCodes.Bgt_Un_S;
OneByteCode[54] = OpCodes.Ble_Un_S;
OneByteCode[55] = OpCodes.Blt_Un_S;
OneByteCode[56] = OpCodes.Br;
OneByteCode[57] = OpCodes.Brfalse;
OneByteCode[58] = OpCodes.Brtrue;
OneByteCode[59] = OpCodes.Beq;
OneByteCode[60] = OpCodes.Bge;
OneByteCode[61] = OpCodes.Bgt;
OneByteCode[62] = OpCodes.Ble;
OneByteCode[63] = OpCodes.Blt;
OneByteCode[64] = OpCodes.Bne_Un;
OneByteCode[65] = OpCodes.Bge_Un;
OneByteCode[66] = OpCodes.Bgt_Un;
OneByteCode[67] = OpCodes.Ble_Un;
OneByteCode[68] = OpCodes.Blt_Un;
OneByteCode[69] = OpCodes.Switch;
OneByteCode[70] = OpCodes.Ldind_I1;
OneByteCode[71] = OpCodes.Ldind_U1;
OneByteCode[72] = OpCodes.Ldind_I2;
OneByteCode[73] = OpCodes.Ldind_U2;
OneByteCode[74] = OpCodes.Ldind_I4;
OneByteCode[75] = OpCodes.Ldind_U4;
OneByteCode[76] = OpCodes.Ldind_I8;
OneByteCode[77] = OpCodes.Ldind_I;
OneByteCode[78] = OpCodes.Ldind_R4;
OneByteCode[79] = OpCodes.Ldind_R8;
OneByteCode[80] = OpCodes.Ldind_Ref;
OneByteCode[81] = OpCodes.Stind_Ref;
OneByteCode[82] = OpCodes.Stind_I1;
OneByteCode[83] = OpCodes.Stind_I2;
OneByteCode[84] = OpCodes.Stind_I4;
OneByteCode[85] = OpCodes.Stind_I8;
OneByteCode[86] = OpCodes.Stind_R4;
OneByteCode[87] = OpCodes.Stind_R8;
OneByteCode[88] = OpCodes.Add;
OneByteCode[89] = OpCodes.Sub;
OneByteCode[90] = OpCodes.Mul;
OneByteCode[91] = OpCodes.Div;
OneByteCode[92] = OpCodes.Div_Un;
OneByteCode[93] = OpCodes.Rem;
OneByteCode[94] = OpCodes.Rem_Un;
OneByteCode[95] = OpCodes.And;
OneByteCode[96] = OpCodes.Or;
OneByteCode[97] = OpCodes.Xor;
OneByteCode[98] = OpCodes.Shl;
OneByteCode[99] = OpCodes.Shr;
OneByteCode[100] = OpCodes.Shr_Un;
OneByteCode[101] = OpCodes.Neg;
OneByteCode[102] = OpCodes.Not;
OneByteCode[103] = OpCodes.Conv_I1;
OneByteCode[104] = OpCodes.Conv_I2;
OneByteCode[105] = OpCodes.Conv_I4;
OneByteCode[106] = OpCodes.Conv_I8;
OneByteCode[107] = OpCodes.Conv_R4;
OneByteCode[108] = OpCodes.Conv_R8;
OneByteCode[109] = OpCodes.Conv_U4;
OneByteCode[110] = OpCodes.Conv_U8;
OneByteCode[111] = OpCodes.Callvirt;
OneByteCode[112] = OpCodes.Cpobj;
OneByteCode[113] = OpCodes.Ldobj;
OneByteCode[114] = OpCodes.Ldstr;
OneByteCode[115] = OpCodes.Newobj;
OneByteCode[116] = OpCodes.Castclass;
OneByteCode[117] = OpCodes.Isinst;
OneByteCode[118] = OpCodes.Conv_R_Un;
OneByteCode[121] = OpCodes.Unbox;
OneByteCode[122] = OpCodes.Throw;
OneByteCode[123] = OpCodes.Ldfld;
OneByteCode[124] = OpCodes.Ldflda;
OneByteCode[125] = OpCodes.Stfld;
OneByteCode[126] = OpCodes.Ldsfld;
OneByteCode[127] = OpCodes.Ldsflda;
OneByteCode[128] = OpCodes.Stsfld;
OneByteCode[129] = OpCodes.Stobj;
OneByteCode[130] = OpCodes.Conv_Ovf_I1_Un;
OneByteCode[131] = OpCodes.Conv_Ovf_I2_Un;
OneByteCode[132] = OpCodes.Conv_Ovf_I4_Un;
OneByteCode[133] = OpCodes.Conv_Ovf_I8_Un;
OneByteCode[134] = OpCodes.Conv_Ovf_U1_Un;
OneByteCode[135] = OpCodes.Conv_Ovf_U2_Un;
OneByteCode[136] = OpCodes.Conv_Ovf_U4_Un;
OneByteCode[137] = OpCodes.Conv_Ovf_U8_Un;
OneByteCode[138] = OpCodes.Conv_Ovf_I_Un;
OneByteCode[139] = OpCodes.Conv_Ovf_U_Un;
OneByteCode[140] = OpCodes.Box;
OneByteCode[141] = OpCodes.Newarr;
OneByteCode[142] = OpCodes.Ldlen;
OneByteCode[143] = OpCodes.Ldelema;
OneByteCode[144] = OpCodes.Ldelem_I1;
OneByteCode[145] = OpCodes.Ldelem_U1;
OneByteCode[146] = OpCodes.Ldelem_I2;
OneByteCode[147] = OpCodes.Ldelem_U2;
OneByteCode[148] = OpCodes.Ldelem_I4;
OneByteCode[149] = OpCodes.Ldelem_U4;
OneByteCode[150] = OpCodes.Ldelem_I8;
OneByteCode[151] = OpCodes.Ldelem_I;
OneByteCode[152] = OpCodes.Ldelem_R4;
OneByteCode[153] = OpCodes.Ldelem_R8;
OneByteCode[154] = OpCodes.Ldelem_Ref;
OneByteCode[155] = OpCodes.Stelem_I;
OneByteCode[156] = OpCodes.Stelem_I1;
OneByteCode[157] = OpCodes.Stelem_I2;
OneByteCode[158] = OpCodes.Stelem_I4;
OneByteCode[159] = OpCodes.Stelem_I8;
OneByteCode[160] = OpCodes.Stelem_R4;
OneByteCode[161] = OpCodes.Stelem_R8;
OneByteCode[162] = OpCodes.Stelem_Ref;
OneByteCode[179] = OpCodes.Conv_Ovf_I1;
OneByteCode[180] = OpCodes.Conv_Ovf_U1;
OneByteCode[181] = OpCodes.Conv_Ovf_I2;
OneByteCode[182] = OpCodes.Conv_Ovf_U2;
OneByteCode[183] = OpCodes.Conv_Ovf_I4;
OneByteCode[184] = OpCodes.Conv_Ovf_U4;
OneByteCode[185] = OpCodes.Conv_Ovf_I8;
OneByteCode[186] = OpCodes.Conv_Ovf_U8;
OneByteCode[194] = OpCodes.Refanyval;
OneByteCode[195] = OpCodes.Ckfinite;
OneByteCode[198] = OpCodes.Mkrefany;
OneByteCode[208] = OpCodes.Ldtoken;
OneByteCode[209] = OpCodes.Conv_U2;
OneByteCode[210] = OpCodes.Conv_U1;
OneByteCode[211] = OpCodes.Conv_I;
OneByteCode[212] = OpCodes.Conv_Ovf_I;
OneByteCode[213] = OpCodes.Conv_Ovf_U;
OneByteCode[214] = OpCodes.Add_Ovf;
OneByteCode[215] = OpCodes.Add_Ovf_Un;
OneByteCode[216] = OpCodes.Mul_Ovf;
OneByteCode[217] = OpCodes.Mul_Ovf_Un;
OneByteCode[218] = OpCodes.Sub_Ovf;
OneByteCode[219] = OpCodes.Sub_Ovf_Un;
OneByteCode[220] = OpCodes.Endfinally;
OneByteCode[221] = OpCodes.Leave;
OneByteCode[222] = OpCodes.Leave_S;
OneByteCode[223] = OpCodes.Stind_I;
OneByteCode[224] = OpCodes.Conv_U;
OneByteCode[248] = OpCodes.Prefix7;
OneByteCode[249] = OpCodes.Prefix6;
OneByteCode[250] = OpCodes.Prefix5;
OneByteCode[251] = OpCodes.Prefix4;
OneByteCode[252] = OpCodes.Prefix3;
OneByteCode[253] = OpCodes.Prefix2;
OneByteCode[254] = OpCodes.Prefix1;
OneByteCode[255] = OpCodes.Prefixref;
TwoByteCode[0] = OpCodes.Arglist;
TwoByteCode[1] = OpCodes.Ceq;
TwoByteCode[2] = OpCodes.Cgt;
TwoByteCode[3] = OpCodes.Cgt_Un;
TwoByteCode[4] = OpCodes.Clt;
TwoByteCode[5] = OpCodes.Clt_Un;
TwoByteCode[6] = OpCodes.Ldftn;
TwoByteCode[7] = OpCodes.Ldvirtftn;
TwoByteCode[9] = OpCodes.Ldarg;
TwoByteCode[10] = OpCodes.Ldarga;
TwoByteCode[11] = OpCodes.Starg;
TwoByteCode[12] = OpCodes.Ldloc;
TwoByteCode[13] = OpCodes.Ldloca;
TwoByteCode[14] = OpCodes.Stloc;
TwoByteCode[15] = OpCodes.Localloc;
TwoByteCode[17] = OpCodes.Endfilter;
TwoByteCode[18] = OpCodes.Unaligned;
TwoByteCode[19] = OpCodes.Volatile;
TwoByteCode[20] = OpCodes.Tailcall;
TwoByteCode[21] = OpCodes.Initobj;
TwoByteCode[23] = OpCodes.Cpblk;
TwoByteCode[24] = OpCodes.Initblk;
TwoByteCode[26] = OpCodes.Rethrow;
TwoByteCode[28] = OpCodes.Sizeof;
TwoByteCode[29] = OpCodes.Refanytype;
}
}
/// <summary>
///
/// </summary>
public class MetadataSignatures
{
/// <summary>
/// The enum that holds the value for diferent signature types
/// </summary>
public enum SigTypeEnum
{
MethodDefSig,
MethodRefSig,
StandaloneSig,
TypeSpecSig
}
/// <summary>
/// Signature CallingConvention
/// </summary>
public int CallingConvention;
/// <summary>
/// Read and decompress the int value at Cursor position and
/// increments the Cursor position by the number of bytes read
/// </summary>
/// <param name="stream">The stream of bytes</param>
/// <param name="pos">The position int the stream where to read from</param>
/// <returns>The decompressed int</returns>
public static int ReadCompressedInt(byte [] stream,out int pos, int posValue)
{
pos = posValue;
int returnVal = -1;
if (stream[pos] == 0xFF)
{
pos += 1;
}
else if ((stream[pos] & 0x80) == 0)
{
returnVal = stream[pos];
pos += 1;
}
else if ((stream[pos] & 0x40) == 0)
{
returnVal = (stream[pos] & ~0x80) << 8 | stream[pos + 1];
pos += 2;
}
else
{
returnVal = (stream[pos] & ~0xC0) << 24 | stream[pos + 1] << 16 | stream[pos + 2] << 8 | stream[pos + 3];
pos += 4;
}
return returnVal;
}
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
/// <param name="posValue"></param>
/// <returns></returns>
public static SigType GetSigType(byte [] stream,out int pos, int posValue)
{
pos = posValue;
ElementType CurrentType = (ElementType)ReadCompressedInt(stream,out pos, pos);
switch (CurrentType)
{
case ElementType.ValueType: return new ValueType(stream,out pos, pos);
case ElementType.Class: return new CLASS(stream,out pos, pos);
case ElementType.Ptr: return new PTR(stream,out pos, pos);
case ElementType.FnPtr: return new FNPTR(stream,out pos, pos);
case ElementType.Array: return new ARRAY(stream,out pos, pos);
case ElementType.SzArray: return new SZARRAY(stream,out pos, pos);
default: return new SigType(CurrentType);
}
}
}
/// <summary>
/// The Custom Mod in signature, RetType and Param
/// </summary>
public class CustomMod
{
/// <summary>
///
/// </summary>
public bool CMOD_OPT = false; //compressed
/// <summary>
///
/// </summary>
public bool CMOD_REQD = false; //compressed
/// <summary>
///
/// </summary>
public int TypeDefOrRefIndex;
/// <summary>
///
/// </summary>
public TokenType TypeTable; //the last two are de uncompressed and unencoded form of TypeRefOrDefEnconded
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
/// <param name="posValue"></param>
public CustomMod(byte [] stream,out int pos, int posValue)
{
pos = posValue;
int compressedInt = MetadataSignatures.ReadCompressedInt(stream,out pos, pos);
if (ElementType.CModOpt==(ElementType)compressedInt) CMOD_OPT=true;
else if (ElementType.CModReqd==(ElementType)compressedInt) CMOD_REQD=true;
MDToken mdt = TabsDecoder.DecodeToken(CodedTokenId.TypeDefOrRef,
MetadataSignatures.ReadCompressedInt(stream,out pos, pos));
TypeTable = mdt.Type;
TypeDefOrRefIndex = mdt.RID;
}
}
/// <summary>
/// The RetType of a Signature
/// </summary>
public class RetType
{
/// <summary>
///
/// </summary>
public CustomMod [] CustomMods;
/// <summary>
///
/// </summary>
public bool ByRef = false;
/// <summary>
///
/// </summary>
public bool TypeByRef = false;
/// <summary>
///
/// </summary>
public bool VOID = false;
/// <summary>
///
/// </summary>
public SigType Type;
/// <summary>
/// Read the RetType of a Signature
/// </summary>
/// <param name="cursor">The cursor to the RetType</param>
/// <param name="assmbl">The Assmbl that holds the metadata</param>
public RetType(byte [] stream, out int pos, int posValue)
{
pos = posValue;
int size = pos;
int i = 0;
CustomMods = new CustomMod[1];
int compressedInt = MetadataSignatures.ReadCompressedInt(stream, out size, pos);
size = pos;
while ((ElementType)compressedInt==ElementType.CModOpt ||
(ElementType)compressedInt==ElementType.CModReqd)
{
if (i>=CustomMods.Length)
{
CustomMod [] temp = new CustomMod[CustomMods.Length*2];
CustomMods.CopyTo(temp,0);
CustomMods = temp;
}
CustomMods[i] = new CustomMod(stream, out pos, pos);
i++;
compressedInt = MetadataSignatures.ReadCompressedInt(stream, out size, pos);
}
if (CustomMods.Length>i)
{
CustomMod [] copy = new CustomMod[i];
for (int j = 0;j < i; j++)
{
copy[j] = CustomMods[j];
}
CustomMods = copy;
}
compressedInt = MetadataSignatures.ReadCompressedInt(stream, out size, pos);
if ((ElementType)compressedInt==ElementType.ByRef)
{
ByRef = true;
pos = size;
Type = MetadataSignatures.GetSigType(stream, out pos, pos);
}
else if ((ElementType)compressedInt==ElementType.TypedByRef)
{
TypeByRef = true;
Type = null;
pos = size;
}
else if ((ElementType)compressedInt==ElementType.Void)
{
VOID = true;
Type = new SigType(ElementType.Void);
pos = size;
}
else //The last possile case, but I'm not sure this is right because I can't find this case in the spec
{
Type = MetadataSignatures.GetSigType(stream, out pos, pos);
}
}
}
/// <summary>
/// The Param item for the list of Params in the signature
/// </summary>
public class Param
{
/// <summary>
///
/// </summary>
public CustomMod [] CustomMods;
/// <summary>
///
/// </summary>
public bool ByRef = false;
/// <summary>
///
/// </summary>
public bool TypeByRef = false;
/// <summary>
///
/// </summary>
public SigType Type;
/// <summary>
///
/// </summary>
public bool Sentinel = false;
/// <summary>
/// Read the Param of the signature
/// </summary>
/// <param name="cursor">The cursor to the Param</param>
/// <param name="assmbl">Tha Assmbl that holds th metadata</param>
/// <param name="LookForSentinel">True if it has the sentinel byte ON</param>
public Param(byte [] stream, out int pos, int posValue, bool LookForSentinel)
{
pos = posValue;
int size = pos;
int i = 0;
CustomMods = new CustomMod[1];
int compressedInt = MetadataSignatures.ReadCompressedInt(stream,out size, size);
if (!LookForSentinel && compressedInt==0x41)
{
Sentinel = true;
return;
}
else if (LookForSentinel && compressedInt==0x41)
{
Sentinel = true;
pos += 1;
}
size = pos;
compressedInt = MetadataSignatures.ReadCompressedInt(stream,out size, size);
while ((ElementType)compressedInt==ElementType.CModOpt ||
(ElementType)compressedInt==ElementType.CModReqd)
{
if (i>=CustomMods.Length)
{
CustomMod [] temp = new CustomMod[CustomMods.Length*2];
CustomMods.CopyTo(temp,0);
CustomMods = temp;
}
CustomMods[i] = new CustomMod(stream, out pos, pos);
i++;
size = pos;
compressedInt = MetadataSignatures.ReadCompressedInt(stream,out size, size);
}
if (CustomMods.Length>i)
{
CustomMod [] copy = new CustomMod[i];
for (int j = 0;j < i; j++)
{
copy[j] = CustomMods[j];
}
CustomMods = copy;
}
size = pos;
compressedInt = MetadataSignatures.ReadCompressedInt(stream,out size, size);
if ((ElementType)compressedInt==ElementType.ByRef)
{
ByRef = true;
pos = size;
Type = MetadataSignatures.GetSigType(stream, out pos, pos);
}
else if ((ElementType)compressedInt==ElementType.TypedByRef)
{
TypeByRef = true;
Type = null;
pos = size;
}
else //The last possible case, could not found it in the metadata
{
Type = MetadataSignatures.GetSigType(stream, out pos, pos);
}
}
}
/// <summary>
///
/// </summary>
public class SigType
{
/// <summary>
///
/// </summary>
public ElementType ElementType;
/// <summary>
///
/// </summary>
/// <param name="element"></param>
public SigType(ElementType element)
{
this.ElementType = element;
}
}
/// <summary>
///
/// </summary>
public class ValueType : SigType
{
/// <summary>
///
/// </summary>
public TokenType TypeTable;
/// <summary>
///
/// </summary>
public int Index;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
/// <param name="posValue"></param>
public ValueType(byte [] stream,out int pos, int posValue) : base (ElementType.ValueType)
{
pos = posValue;
MDToken mdt = TabsDecoder.DecodeToken(CodedTokenId.TypeDefOrRef,
MetadataSignatures.ReadCompressedInt(stream,out pos,pos));
TypeTable = mdt.Type;
Index = mdt.RID;
}
}
/// <summary>
///
/// </summary>
public class CLASS : SigType
{
/// <summary>
///
/// </summary>
public TokenType TypeTable;
/// <summary>
///
/// </summary>
public int Index;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
/// <param name="posValue"></param>
public CLASS(byte [] stream,out int pos, int posValue) : base (ElementType.Class)
{
pos = posValue;
MDToken mdt = TabsDecoder.DecodeToken(CodedTokenId.TypeDefOrRef,
MetadataSignatures.ReadCompressedInt(stream,out pos,pos));
TypeTable = mdt.Type;
Index = mdt.RID;
}
}
/// <summary>
///
/// </summary>
public class PTR : SigType
{
/// <summary>
/// TODO: CustomMod* not suported
/// </summary>
public SigType ptrType;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
/// <param name="posValue"></param>
public PTR(byte [] stream,out int pos, int posValue) : base (ElementType.Ptr)
{
pos = posValue;
ptrType = MetadataSignatures.GetSigType(stream,out pos, pos);
}
}
/// <summary>
///
/// </summary>
public class FNPTR : SigType
{
/// <summary>
///
/// </summary>
public MethodDefSig methodDefSig;
/// <summary>
///
/// </summary>
public MethodRefSig methodRefSig;
/// <summary>
///
/// </summary>
public bool IsMethodDef
{
get
{
if (this.methodDefSig==null) return false;
return true;
}
}
/// <summary>
///
/// </summary>
public bool IsMethodRef
{
get
{
if (this.methodRefSig==null) return false;
return true;
}
}
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
public FNPTR(byte [] stream,out int pos, int posValue) : base (ElementType.FnPtr)
{
pos = posValue;
if ((stream[pos] & 0x05) !=0)
{
this.methodDefSig = null;
this.methodRefSig = new MethodRefSig(stream,out pos, posValue);
}
else
{
this.methodRefSig = null;
this.methodDefSig = new MethodDefSig(stream,out pos, posValue);
}
}
}
/// <summary>
///
/// </summary>
public class ARRAY : SigType
{
/// <summary>
///
/// </summary>
public SigType Type;
/// <summary>
///
/// </summary>
public ARRAY.ArrayShape arrayShape;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
public ARRAY(byte [] stream,out int pos, int posValue) : base (ElementType.Array)
{
pos = posValue;
this.Type = MetadataSignatures.GetSigType(stream,out pos, pos);
this.arrayShape = new ArrayShape(stream,out pos, pos);
}
/// <summary>
///
/// </summary>
public class ArrayShape
{
/// <summary>
///
/// </summary>
public int Rank;
/// <summary>
///
/// </summary>
public int NumSizes;
/// <summary>
///
/// </summary>
public int [] Sizes;
/// <summary>
///
/// </summary>
public int NumLoBounds;
/// <summary>
///
/// </summary>
public int [] LoBounds;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
public ArrayShape(byte [] stream,out int pos, int posValue)
{
pos = posValue;
Rank = MetadataSignatures.ReadCompressedInt(stream,out pos,pos);
NumSizes = MetadataSignatures.ReadCompressedInt(stream,out pos,pos);
if (NumSizes!=0)
{
Sizes = new int[NumSizes];
for (int i=0; i<NumSizes;i++)
Sizes[i] = MetadataSignatures.ReadCompressedInt(stream,out pos,pos);
}
NumLoBounds = MetadataSignatures.ReadCompressedInt(stream,out pos,pos);
if (NumLoBounds!=0)
{
LoBounds = new int[NumLoBounds];
for (int i=0;i<NumLoBounds;i++)
LoBounds[i] = MetadataSignatures.ReadCompressedInt(stream,out pos,pos);
}
}
/// <summary>
///
/// </summary>
public ArrayShape()
{
Rank = 1;
NumSizes = 0;
Sizes = null;
NumLoBounds = 0;
LoBounds = null;
}
}
}
/// <summary>
///
/// </summary>
public class SZARRAY : SigType
{
/// <summary>
/// TODO: CustomMod* not suported
/// </summary>
public SigType Type;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
public SZARRAY(byte [] stream,out int pos, int posValue) : base (ElementType.SzArray)
{
pos = posValue;
this.Type = MetadataSignatures.GetSigType(stream,out pos, pos);
}
}
/// <summary>
/// FieldSig
/// </summary>
public class FieldSig : MetadataSignatures
{
/// <summary>
///
/// </summary>
public bool Field = false;
/// <summary>
///
/// </summary>
public CustomMod [] CustomMods;
/// <summary>
///
/// </summary>
public SigType Type;
/// <summary>
/// Constructor
/// </summary>
/// <param name="assmbl">The Assmbl that holds the metadata</param>
/// <param name="index">Index into the Blob stream</param>
public FieldSig(byte [] stream,int index)
{
MetadataResolver.SetBlobReadPosition(stream, out index, index);
if ((stream[index] & 0x06) !=0 || (stream[index] & 0x60) !=0) this.Field = true;
CallingConvention = stream[index];
index += 1;
int size = index;
int i = 0;
CustomMods = new CustomMod[1];
int compressedInt = MetadataSignatures.ReadCompressedInt(stream,out size, size);
while ((ElementType)compressedInt==ElementType.CModOpt ||
(ElementType)compressedInt==ElementType.CModReqd)
{
if (i>=CustomMods.Length)
{
CustomMod [] temp = new CustomMod[CustomMods.Length*2];
CustomMods.CopyTo(temp,0);
CustomMods = temp;
}
CustomMods[i] = new CustomMod(stream,out size, size);
i++;
compressedInt = MetadataSignatures.ReadCompressedInt(stream,out size,size);
}
if (CustomMods.Length>i)
{
CustomMod [] copy = new CustomMod[i];
for (int j = 0;j < i; j++)
{
copy[j] = CustomMods[j];
}
CustomMods = copy;
}
Type = MetadataSignatures.GetSigType(stream, out index,index);
}
}
/// <summary>
/// Type to hold a MethodDefSig
/// </summary>
public class MethodDefSig : MetadataSignatures
{
/// <summary>
///
/// </summary>
public bool HasThis = false;
/// <summary>
///
/// </summary>
public bool ExplicitThis = false;
/// <summary>
///
/// </summary>
public bool Default = false;
/// <summary>
///
/// </summary>
public bool Vararg = false;
/// <summary>
///
/// </summary>
public int ParamCount;
/// <summary>
///
/// </summary>
public RetType retType;
/// <summary>
///
/// </summary>
public Param [] Params;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
/// <param name="posValue"></param>
public MethodDefSig(byte [] stream,out int pos, int posValue)
{
pos = posValue;
if ((stream[pos] & 0x80) == 0)
pos += 1;
else if ((stream[pos] & 0x40) == 0)
pos += 2;
else
pos += 4;
if ((stream[pos] & 0x20) !=0) this.HasThis = true;
if ((stream[pos] & 0x40) !=0) this.ExplicitThis = true;
if (stream[pos] ==0) this.Default = true;
if ((stream[pos] & 0x05) !=0) this.Vararg = true;
CallingConvention = stream[pos];
pos += 1;
this.ParamCount = MetadataSignatures.ReadCompressedInt(stream, out pos,pos);
this.retType = new RetType(stream, out pos,pos);
this.Params = new Param[this.ParamCount];
for (int i = 0;i<this.ParamCount;i++)
{
this.Params[i] = new Param(stream, out pos,pos,false);
}
}
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
public MethodDefSig(byte [] stream,int pos)
{
if ((stream[pos] & 0x80) == 0)
pos += 1;
else if ((stream[pos] & 0x40) == 0)
pos += 2;
else
pos += 4;
if ((stream[pos] & 0x20) !=0) this.HasThis = true;
if ((stream[pos] & 0x40) !=0) this.ExplicitThis = true;
if (stream[pos] ==0) this.Default = true;
if ((stream[pos] & 0x05) !=0) this.Vararg = true;
CallingConvention = stream[pos];
pos += 1;
this.ParamCount = MetadataSignatures.ReadCompressedInt(stream, out pos,pos);
this.retType = new RetType(stream, out pos,pos);
this.Params = new Param[this.ParamCount];
for (int i = 0;i<this.ParamCount;i++)
{
this.Params[i] = new Param(stream, out pos,pos,false);
}
}
}
/// <summary>
/// MethodRefSig
/// </summary>
public class MethodRefSig : MetadataSignatures
{
/// <summary>
///
/// </summary>
public bool HasThis = false;
/// <summary>
///
/// </summary>
public bool ExplicitThis = false;
/// <summary>
///
/// </summary>
public bool Default = false;
/// <summary>
///
/// </summary>
public bool Vararg = false;
/// <summary>
///
/// </summary>
public int ParamCount;
/// <summary>
///
/// </summary>
public RetType retType;
/// <summary>
///
/// </summary>
public Param [] Params;
/// <summary>
///
/// </summary>
public bool Sentinel = false;
/// <summary>
///
/// </summary>
public Param [] ParamsAfterSentinel;
/// <summary>
/// Constructor
/// </summary>
/// <param name="stream">The blob byte stream</param>
/// <param name="index">Index into the Blob stream</param>
public MethodRefSig(byte [] stream, out int pos, int posValue)
{
pos = posValue;
if ((stream[pos] & 0x80) == 0)
pos += 1;
else if ((stream[pos] & 0x40) == 0)
pos += 2;
else
pos += 4;
if ((stream[pos] & 0x20) !=0) this.HasThis = true;
if ((stream[pos] & 0x40) !=0) this.ExplicitThis = true;
if (stream[pos] ==0) this.Default = true;
if ((stream[pos] & 0x05) !=0) this.Vararg = true;
CallingConvention = stream[pos];
pos += 1;
this.ParamCount = MetadataSignatures.ReadCompressedInt(stream, out pos, pos);
this.retType = new RetType(stream, out pos, pos);
this.Params = new Param[this.ParamCount];
int SentinelPos = 0;
for (int i = 0;i<this.ParamCount;i++)
{
if (!this.Sentinel)
{
Param TempParam = new Param(stream, out pos,pos,true);
if (TempParam.Sentinel)
{
this.Sentinel = true;
Param [] TempParamsArray = new Param[i];
for (int j=0;j<i;j++)
{
TempParamsArray[j] = this.Params[j];
}
this.Params = TempParamsArray;
TempParamsArray = null;
this.ParamsAfterSentinel = new Param[this.ParamCount-i];
SentinelPos = i;
this.ParamsAfterSentinel[i-SentinelPos] = TempParam;
continue;
}
this.Params[i] = TempParam;
}
else
{
this.ParamsAfterSentinel[i-SentinelPos] = new Param(stream, out pos,pos, false);
}
}
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="stream">The blob byte stream</param>
/// <param name="pos">Index into the Blob stream</param>
public MethodRefSig(byte [] stream, int pos)
{
if ((stream[pos] & 0x80) == 0)
pos += 1;
else if ((stream[pos] & 0x40) == 0)
pos += 2;
else
pos += 4;
if ((stream[pos] & 0x20) !=0) this.HasThis = true;
if ((stream[pos] & 0x40) !=0) this.ExplicitThis = true;
if (stream[pos] ==0) this.Default = true;
if ((stream[pos] & 0x05) !=0) this.Vararg = true;
CallingConvention = stream[pos];
pos += 1;
this.ParamCount = MetadataSignatures.ReadCompressedInt(stream, out pos, pos);
this.retType = new RetType(stream, out pos, pos);
this.Params = new Param[this.ParamCount];
int SentinelPos = 0;
for (int i = 0;i<this.ParamCount;i++)
{
if (!this.Sentinel)
{
Param TempParam = new Param(stream, out pos,pos,true);
if (TempParam.Sentinel)
{
this.Sentinel = true;
Param [] TempParamsArray = new Param[i];
for (int j=0;j<i;j++)
{
TempParamsArray[j] = this.Params[j];
}
this.Params = TempParamsArray;
TempParamsArray = null;
this.ParamsAfterSentinel = new Param[this.ParamCount-i];
SentinelPos = i;
this.ParamsAfterSentinel[i-SentinelPos] = TempParam;
continue;
}
this.Params[i] = TempParam;
}
else
{
this.ParamsAfterSentinel[i-SentinelPos] = new Param(stream, out pos,pos, false);
}
}
}
}
/// <summary>
/// PropertySig
/// </summary>
public class PropertySig : MetadataSignatures
{
/// <summary>
///
/// </summary>
public bool Property = false;
/// <summary>
///
/// </summary>
public int ParamCount;
/// <summary>
///
/// </summary>
public SigType Type;
/// <summary>
///
/// </summary>
public Param [] Params;
/// <summary>
/// Cobstructor
/// </summary>
/// <param name="stream">The blob heap byte sttream</param>
/// <param name="pos">Index into the blob heap</param>
public PropertySig(byte [] stream,int pos)
{
MetadataResolver.SetBlobReadPosition(stream,out pos,pos);
if ((stream[pos] & 0x80) !=0) this.Property = true;
CallingConvention = stream[pos];
pos += 1;
this.ParamCount = MetadataSignatures.ReadCompressedInt(stream, out pos, pos);
this.Type = MetadataSignatures.GetSigType(stream, out pos, pos);
this.Params = new Param[this.ParamCount];
for (int i = 0;i<this.ParamCount;i++)
{
this.Params[i] = new Param(stream, out pos, pos, false);
}
}
}
/// <summary>
///
/// </summary>
public class TypeSpecSig : MetadataSignatures
{
/// <summary>
///
/// </summary>
public SigType Type;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="index"></param>
public TypeSpecSig(byte [] stream,int index)
{
// KIRK: Added this line to read the count from the Blob stream
int count = ReadCompressedInt(stream,out index, index);
Type = MetadataSignatures.GetSigType(stream, out index, index);
}
}
/// <summary>
/// Local variables signatures
/// </summary>
public class LocalVarSig
{
/// <summary>
/// Check if the initial value of the signature is 0x7
/// </summary>
public bool IsLocalSig = true;
/// <summary>
/// Number of local variables in the signature
/// </summary>
public int Count;
/// <summary>
/// array of types in the signature
/// </summary>
public LocalVarSig.LocalSigType [] types;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="blobIndex"></param>
public LocalVarSig(byte [] stream, int blobIndex)
{
// TODO: Verify why this sometimes doens't have the 0x07 value
if (stream[blobIndex]!=0x07) this.IsLocalSig = false;
blobIndex += 1;
// TODO: check if the Count value is correctly obtained
this.Count = MetadataSignatures.ReadCompressedInt(stream, out blobIndex, blobIndex);
if (this.Count>0)
{
this.types = new LocalSigType[this.Count];
for (int i = 0; i< this.Count; i++)
{
this.types[i] = new LocalSigType(stream, out blobIndex, blobIndex);
}
}
else
{
this.types = null;
}
}
/// <summary>
///
/// </summary>
public class LocalSigType
{
/// <summary>
///
/// </summary>
public SigType type;
/// <summary>
/// The only value currently used is ELEMENT_TYPE_PINNED
/// </summary>
public bool Constraint = false;
/// <summary>
///
/// </summary>
public bool ByRef = false;
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="pos"></param>
/// <param name="posValue"></param>
public LocalSigType(byte [] stream, out int pos, int posValue)
{
pos = posValue;
int SizeRead = pos;
//The only value currently used is ELEMENT_TYPE_PINNED
while (MetadataSignatures.ReadCompressedInt(stream, out SizeRead, SizeRead)
== (int)ElementType.Pinned)
{
this.Constraint = true;
pos = SizeRead;
}
SizeRead = pos;
if (MetadataSignatures.ReadCompressedInt(stream, out SizeRead, SizeRead)
== (int)ElementType.ByRef)
{
ByRef = true;
pos = SizeRead;
}
this.type = MetadataSignatures.GetSigType(stream, out pos, pos);
}
}
}
/// <summary>
/// The type for the marshaling signature
/// </summary>
public class MarshalSpec
{
/// <summary>
/// The native type
/// </summary>
private UnmanagedType NativeIntrinsec;
public UnmanagedType ArrayElementType;
public int ParamNum;
public int ElemMult;
public int NumElem;
/// <summary>
/// Get the NativeType
/// </summary>
/// <returns>The NativeType of the element</returns>
public UnmanagedType GetNativeType()
{
return this.NativeIntrinsec;
}
/// <summary>
/// Create a new MarshalSpec
/// </summary>
/// <param name="stream">The byte stream to read from</param>
/// <param name="posValue">The starting read postion</param>
public MarshalSpec(byte [] stream, int pos)
{
MetadataResolver.SetBlobReadPosition(stream,out pos,pos);
this.NativeIntrinsec = (UnmanagedType)MetadataSignatures.ReadCompressedInt(
stream, out pos, pos);
if ((this.NativeIntrinsec & UnmanagedType.ByValArray) != 0)
{
this.NumElem = MetadataSignatures.ReadCompressedInt(
stream, out pos, pos);
}
else if ((this.NativeIntrinsec & UnmanagedType.SafeArray) != 0)
{
this.ArrayElementType = (UnmanagedType)MetadataSignatures.ReadCompressedInt(
stream, out pos, pos);
}
else if ((this.NativeIntrinsec & UnmanagedType.ByValTStr) != 0)
{
this.NumElem = MetadataSignatures.ReadCompressedInt(
stream, out pos, pos);
}
else if ((this.NativeIntrinsec & UnmanagedType.LPArray) != 0)
{
this.ArrayElementType = (UnmanagedType)MetadataSignatures.ReadCompressedInt(
stream, out pos, pos);
}
}
/// <summary>
/// Create a MarshalSpec
/// </summary>
/// <param name="type"></param>
internal MarshalSpec(UnmanagedType type)
{
this.NativeIntrinsec = type;
}
}
}
|