Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2010-01-25 08:29:31 +0300
committerjfrijters <jfrijters>2010-01-25 08:29:31 +0300
commit198c9d70eac5d6d88718bfedee19314edf77661b (patch)
treecf6e13cb042f93d214c145fd405fefc19cb21b59 /reflect/MethodBody.cs
parent2966abd1dcb1eaa8fe692094f657943a9f2d21be (diff)
New IKVM.Reflection implementation.
Diffstat (limited to 'reflect/MethodBody.cs')
-rw-r--r--reflect/MethodBody.cs153
1 files changed, 153 insertions, 0 deletions
diff --git a/reflect/MethodBody.cs b/reflect/MethodBody.cs
new file mode 100644
index 00000000..0aca1db4
--- /dev/null
+++ b/reflect/MethodBody.cs
@@ -0,0 +1,153 @@
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using IKVM.Reflection.Reader;
+using System.IO;
+
+namespace IKVM.Reflection
+{
+ public sealed class MethodBody
+ {
+ private readonly IList<ExceptionHandlingClause> exceptionClauses;
+ private readonly IList<LocalVariableInfo> locals;
+ private readonly bool initLocals;
+ private readonly int maxStack;
+ private readonly int localVarSigTok;
+ private byte[] body;
+
+ internal MethodBody(ModuleReader module, int rva, IGenericContext context)
+ {
+ const byte CorILMethod_TinyFormat = 0x02;
+ const byte CorILMethod_FatFormat = 0x03;
+ const byte CorILMethod_MoreSects = 0x08;
+ const byte CorILMethod_InitLocals = 0x10;
+ const byte CorILMethod_Sect_EHTable = 0x01;
+ const byte CorILMethod_Sect_FatFormat = 0x40;
+ const byte CorILMethod_Sect_MoreSects = 0x80;
+
+ List<ExceptionHandlingClause> exceptionClauses = new List<ExceptionHandlingClause>();
+ List<LocalVariableInfo> locals = new List<LocalVariableInfo>();
+ module.SeekRVA(rva);
+ BinaryReader br = new BinaryReader(module.stream);
+ byte b = br.ReadByte();
+ if ((b & 3) == CorILMethod_TinyFormat)
+ {
+ initLocals = true;
+ body = br.ReadBytes(b >> 2);
+ }
+ else if ((b & 3) == CorILMethod_FatFormat)
+ {
+ initLocals = (b & CorILMethod_InitLocals) != 0;
+ short flagsAndSize = (short)(b | (br.ReadByte() << 8));
+ if ((flagsAndSize >> 12) != 3)
+ {
+ throw new BadImageFormatException("Fat format method header size should be 3");
+ }
+ maxStack = br.ReadUInt16();
+ int codeLength = br.ReadInt32();
+ localVarSigTok = br.ReadInt32();
+ body = br.ReadBytes(codeLength);
+ if ((b & CorILMethod_MoreSects) != 0)
+ {
+ module.stream.Position = (module.stream.Position + 3) & ~3;
+ int hdr = br.ReadInt32();
+ if ((hdr & CorILMethod_Sect_MoreSects) != 0 || (hdr & CorILMethod_Sect_EHTable) == 0)
+ {
+ throw new NotImplementedException();
+ }
+ else if ((hdr & CorILMethod_Sect_FatFormat) != 0)
+ {
+ int count = (((hdr >> 8) & 0xFFFFFF) - 4) / 24;
+ for (int i = 0; i < count; i++)
+ {
+ int flags = br.ReadInt32();
+ int tryOffset = br.ReadInt32();
+ int tryLength = br.ReadInt32();
+ int handlerOffset = br.ReadInt32();
+ int handlerLength = br.ReadInt32();
+ int classTokenOrFilterOffset = br.ReadInt32();
+ exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context));
+ }
+ }
+ else
+ {
+ int count = (((hdr >> 8) & 0xFF) - 4) / 12;
+ for (int i = 0; i < count; i++)
+ {
+ int flags = br.ReadUInt16();
+ int tryOffset = br.ReadUInt16();
+ int tryLength = br.ReadByte();
+ int handlerOffset = br.ReadUInt16();
+ int handlerLength = br.ReadByte();
+ int classTokenOrFilterOffset = br.ReadInt32();
+ exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context));
+ }
+ }
+ }
+ if (localVarSigTok != 0)
+ {
+ ByteReader sig = module.ResolveSignature(localVarSigTok);
+ Signature.ReadLocalVarSig(module, sig, context, locals);
+ }
+ }
+ else
+ {
+ throw new BadImageFormatException();
+ }
+ this.exceptionClauses = exceptionClauses.AsReadOnly();
+ this.locals = locals.AsReadOnly();
+ }
+
+ public IList<ExceptionHandlingClause> ExceptionHandlingClauses
+ {
+ get { return exceptionClauses; }
+ }
+
+ public bool InitLocals
+ {
+ get { return initLocals; }
+ }
+
+ public IList<LocalVariableInfo> LocalVariables
+ {
+ get { return locals; }
+ }
+
+ public byte[] GetILAsByteArray()
+ {
+ return body;
+ }
+
+ public int LocalSignatureMetadataToken
+ {
+ get { return localVarSigTok; }
+ }
+
+ public int MaxStackSize
+ {
+ get { return maxStack; }
+ }
+ }
+}