internal static MethodSignatureInfoV2 ParseMethodSignature(uint signature, DotNetFile file, string FunctionName) { MethodSignatureInfoV2 ret = new MethodSignatureInfoV2(); string sig = ""; var blobStreamReader = new BinaryReader(new MemoryStream(file.Backend.BlobStream)); blobStreamReader.BaseStream.Seek(signature, SeekOrigin.Begin); var length = IlDecompiler.ParseNumber(blobStreamReader); var type = IlDecompiler.ParseNumber(blobStreamReader); var parmaters = IlDecompiler.ParseNumber(blobStreamReader); //This field becomes "generic parameters" if type & 10 != 0 if ((type & 0x10) != 0) { ret.AmountOfGenericParams = (int)parmaters; //The "real" generic param amount parmaters = IlDecompiler.ParseNumber(blobStreamReader); } var returnVal = ReadParam(blobStreamReader, file); //read return value ret.ReturnVal = returnVal; if (type == 0) { //Static method sig += "static "; ret.IsStatic = true; } if ((type & 0x20) != 0) { ret.HasThis = true; } sig += returnVal.TypeInString; sig += " " + FunctionName; sig += "("; for (ulong i = 0; i < parmaters; i++) { var parm = ReadParam(blobStreamReader, file); ret.Params.Add(parm); sig += parm.TypeInString + ", "; ret.AmountOfParms++; } if (parmaters > 0) { sig = sig.Substring(0, sig.Length - 2); //Remove the last , } sig += ");"; ret.Signature = sig; return(ret); }
internal static MethodSignatureParam ReadParam(BinaryReader r, DotNetFile file) { string sig; var parm = r.ReadByte(); MethodSignatureParam ret = new MethodSignatureParam(); switch (parm) { case 0x00: { //end of list sig = "End of list"; ret.type = StackItemType.Array; //array maybe? break; } case 0x01: { sig = "void"; ret.type = StackItemType.None; break; } case 0x02: { sig = "bool"; ret.type = StackItemType.Boolean; break; } case 0x03: { sig = "char"; ret.type = StackItemType.Char; break; } case 0x04: { sig = "sbyte"; ret.type = StackItemType.SByte; break; } case 0x05: { sig = "byte"; ret.type = StackItemType.Byte; break; } case 0x06: { sig = "short"; ret.type = StackItemType.Int16; break; } case 0x07: { sig = "ushort"; ret.type = StackItemType.UInt16; break; } case 0x08: { sig = "int"; ret.type = StackItemType.Int32; break; } case 0x09: { sig = "uint"; ret.type = StackItemType.UInt32; break; } case 0x0A: { sig = "long"; ret.type = StackItemType.Int64; break; } case 0x0B: { sig = "ulong"; ret.type = StackItemType.UInt64; break; } case 0x0C: { sig = "float"; ret.type = StackItemType.Float32; break; } case 0x0D: { sig = "double"; ret.type = StackItemType.Float64; break; } case 0x0E: { sig = "string"; ret.type = StackItemType.String; break; } case 0xF: //Pointer* (followed by type) { sig = ReadParam(r, file).TypeInString + "*"; ret.type = StackItemType.Int32; break; } case 0x10: //byref* //followed by type { sig = "ref " + ReadParam(r, file).TypeInString; ret.type = StackItemType.Int32; break; } case 0x11: //valve type (followed by typedef or typeref token) { var t = IlDecompiler.ParseNumber(r); //type of the type IlDecompiler.DecodeTypeDefOrRef(t, out uint rowType, out uint index); string name; string Namespace; ret.type = StackItemType.Object; ret.IsClass = true; if (rowType == 0) { //typedef var tt = file.Backend.Tabels.TypeDefTabel[(int)(index - 1)]; name = file.Backend.ClrStringsStream.GetByOffset(tt.Name); Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.Namespace); //resolve it foreach (var item in file.Types) { if (item.NameSpace == Namespace && item.Name == name) { ret.ClassType = item; } } } else if (rowType == 1) { //typeref var tt = file.Backend.Tabels.TypeRefTabel[(int)(index - 1)]; name = file.Backend.ClrStringsStream.GetByOffset(tt.TypeName); Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.TypeNamespace); } else { throw new NotImplementedException(); } if (!string.IsNullOrEmpty(Namespace)) { sig = $"{Namespace}.{name}"; } else { sig = $"{name}"; } break; } case 0x12: //class followed by typedef or typeref token { var t = IlDecompiler.ParseNumber(r); //type of the type IlDecompiler.DecodeTypeDefOrRef(t, out uint rowType, out uint index); string name; string Namespace; ret.type = StackItemType.Object; ret.IsClass = true; if (rowType == 0) { //typedef var tt = file.Backend.Tabels.TypeDefTabel[(int)(index - 1)]; name = file.Backend.ClrStringsStream.GetByOffset(tt.Name); Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.Namespace); //resolve it foreach (var item in file.Types) { if (item.NameSpace == Namespace && item.Name == name) { ret.ClassType = item; } } } else if (rowType == 1) { //typeref var tt = file.Backend.Tabels.TypeRefTabel[(int)(index - 1)]; name = file.Backend.ClrStringsStream.GetByOffset(tt.TypeName); Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.TypeNamespace); } else { throw new NotImplementedException(); } if (!string.IsNullOrEmpty(Namespace)) { sig = $"{Namespace}.{name}"; } else { sig = $"{name}"; } break; } case 0x13: //GENERIC_PARM { var b = IlDecompiler.ParseNumber(r); sig = "T"; ret.type = StackItemType.Any; break; } case 0x14: { sig = "[][]"; ret.type = StackItemType.Array; break; } case 0x15: { //ELEMENT_TYPE_GENERICINST var t = IlDecompiler.ParseNumber(r); //type of the generic type var c = IlDecompiler.ParseNumber(r); //generic type (TypeDefOrRefEncoded) var d = IlDecompiler.ParseNumber(r); //Count of generic args IlDecompiler.DecodeTypeDefOrRef((uint)c, out uint rowType, out uint index); ret.IsGeneric = true; ret.type = StackItemType.Object; List <MethodSignatureParam> @params = new List <MethodSignatureParam>(); for (ulong i = 0; i < d; i++) { @params.Add(ReadParam(r, file)); } if (rowType == 0) { //typedef var tt = file.Backend.Tabels.TypeDefTabel[(int)(index - 1)]; var name = file.Backend.ClrStringsStream.GetByOffset(tt.Name); var Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.Namespace); if (!string.IsNullOrEmpty(Namespace)) { sig = $"{Namespace}.{name}<"; } else { sig = $"{name}<"; } ret.GenericClassNamespace = Namespace; ret.GenericClassName = name; } else if (rowType == 1) { //typeref var tt = file.Backend.Tabels.TypeRefTabel[(int)(index - 1)]; var name = file.Backend.ClrStringsStream.GetByOffset(tt.TypeName); var Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.TypeNamespace); if (!string.IsNullOrEmpty(Namespace)) { sig = $"{Namespace}.{name}<"; } else { sig = $"{name}<"; } ret.GenericClassNamespace = Namespace; ret.GenericClassName = name; } else { throw new NotImplementedException(); } foreach (var item in @params) { sig += item.TypeInString + ", "; } sig = sig.Substring(0, sig.Length - 2); sig += ">"; break; } case 0x16: { //TypedRefrerence structure sig = "TypedReference"; ret.type = StackItemType.Object; break; } case 0x18: { //IntPtr sig = "IntPtr"; ret.type = StackItemType.IntPtr; break; } case 0x19: { //UIntPtr sig = "UIntPtr"; ret.type = StackItemType.UIntPtr; break; } case 0x1B: { sig = "func ptr"; ret.type = StackItemType.MethodPtr; break; } case 0x1C: { sig = "object"; ret.type = StackItemType.Object; break; } case 0x1D: { ret.ArrayType = ReadParam(r, file); sig = ret.ArrayType.TypeInString + "[]"; ret.type = StackItemType.Array; ret.IsArray = true; break; } case 0x1E: //MVar var num = IlDecompiler.ParseNumber(r); sig = "T" + num; break; case 0x20: var num2 = IlDecompiler.ParseNumber(r); IlDecompiler.DecodeTypeDefOrRef((uint)num2, out uint rowType2, out uint index2); sig = "TODO: 0x20"; break; default: throw new System.NotImplementedException("Unknown byte: 0x" + parm.ToString("X")); } ret.TypeInString = sig; return(ret); }