2 using System.Collections.Generic;
5 using Mono.Cecil.Metadata;
8 using System.Reflection;
10 namespace Mono.Debugger.Soft
12 public class MethodBodyMirror : Mirror
17 internal MethodBodyMirror (VirtualMachine vm, MethodMirror method, MethodBodyInfo info) : base (vm, 0) {
22 public MethodMirror Method {
28 public List<ILExceptionHandler> ExceptionHandlers {
30 vm.CheckProtocolVersion (2, 18);
31 return info.clauses.Select (c =>
33 var handler = new ILExceptionHandler (c.try_offset, c.try_length, (ILExceptionHandlerType) c.flags, c.handler_offset, c.handler_length);
34 if (c.flags == ExceptionClauseFlags.None)
35 handler.CatchType = vm.GetType (c.catch_type_id);
36 else if (c.flags == ExceptionClauseFlags.Filter)
37 handler.FilterOffset = c.filter_offset;
44 public byte[] GetILAsByteArray () {
48 public List<ILInstruction> Instructions {
50 return ReadCilBody (new BinaryReader (new MemoryStream (info.il)), info.il.Length);
54 static bool opcodes_inited;
56 static OpCode [] OneByteOpCode = new OpCode [0xe0 + 1];
57 static OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1];
60 List<ILInstruction> ReadCilBody (BinaryReader br, int code_size)
62 long start = br.BaseStream.Position;
63 ILInstruction last = null;
64 //GenericContext context = new GenericContext (body.Method);
65 List<ILInstruction> code = new List<ILInstruction> ();
67 var by_offset = new Dictionary<int, ILInstruction> ();
69 if (!opcodes_inited) {
70 foreach (FieldInfo fi in typeof (OpCodes).GetFields (BindingFlags.Static|BindingFlags.Public)) {
71 var val = (OpCode)fi.GetValue (null);
74 OneByteOpCode [val.Op2] = val;
76 TwoBytesOpCode [val.Op2] = val;
78 opcodes_inited = true;
81 while (br.BaseStream.Position < start + code_size) {
83 long offset = br.BaseStream.Position - start;
84 int cursor = br.ReadByte ();
89 op = TwoBytesOpCode [br.ReadByte ()];
91 op = OneByteOpCode [cursor];
93 ILInstruction instr = new ILInstruction ((int)offset, op, null);
95 by_offset [instr.Offset] = instr;
97 switch (op.OperandType) {
98 case OperandType.InlineNone :
100 case OperandType.InlineSwitch :
101 uint length = br.ReadUInt32 ();
102 int [] branches = new int [length];
103 int [] buf = new int [length];
104 for (int i = 0; i < length; i++)
105 buf [i] = br.ReadInt32 ();
106 for (int i = 0; i < length; i++)
107 branches [i] = Convert.ToInt32 (br.BaseStream.Position - start + buf [i]);
108 instr.Operand = branches;
110 case OperandType.ShortInlineBrTarget :
111 sbyte sbrtgt = br.ReadSByte ();
112 instr.Operand = Convert.ToInt32 (br.BaseStream.Position - start + sbrtgt);
114 case OperandType.InlineBrTarget :
115 int brtgt = br.ReadInt32 ();
116 instr.Operand = Convert.ToInt32 (br.BaseStream.Position - start + brtgt);
118 case OperandType.ShortInlineI :
119 if (op == OpCodes.Ldc_I4_S)
120 instr.Operand = br.ReadSByte ();
122 instr.Operand = br.ReadByte ();
124 case OperandType.ShortInlineVar :
125 instr.Operand = br.ReadByte ();
127 case OperandType.ShortInlineArg :
128 instr.Operand = br.ReadByte ();
130 case OperandType.InlineSig :
132 //instr.Operand = GetCallSiteAt (br.ReadInt32 (), context);
134 case OperandType.InlineI :
135 instr.Operand = br.ReadInt32 ();
137 case OperandType.InlineVar :
138 instr.Operand = br.ReadInt16 ();
140 case OperandType.InlineArg :
141 instr.Operand = br.ReadInt16 ();
143 case OperandType.InlineI8 :
144 instr.Operand = br.ReadInt64 ();
146 case OperandType.ShortInlineR :
147 instr.Operand = br.ReadSingle ();
149 case OperandType.InlineR :
150 instr.Operand = br.ReadDouble ();
152 case OperandType.InlineString :
153 token = br.ReadInt32 ();
154 t = vm.conn.Method_ResolveToken (Method.Id, token);
155 if (t.Type == TokenType.STRING)
156 instr.Operand = t.Str;
158 case OperandType.InlineField :
159 case OperandType.InlineMethod :
160 case OperandType.InlineType :
161 case OperandType.InlineTok :
162 token = br.ReadInt32 ();
164 t = vm.conn.Method_ResolveToken (Method.Id, token);
168 instr.Operand = vm.GetType (t.Id);
170 case TokenType.FIELD:
171 // FIXME: No vm.GetField ()
172 //instr.Operand = vm.GetField (t.Id);
174 case TokenType.METHOD:
175 instr.Operand = vm.GetMethod (t.Id);
177 case TokenType.UNKNOWN:
180 throw new NotImplementedException ("Unknown token type: " + t.Type);
187 instr.Previous = last;
196 foreach (ILInstruction i in code) {
197 switch (i.OpCode.OperandType) {
198 case OperandType.ShortInlineBrTarget:
199 case OperandType.InlineBrTarget:
200 i.Operand = by_offset [(int)i.Operand];
202 case OperandType.InlineSwitch:
203 int [] lbls = (int []) i.Operand;
204 ILInstruction [] instrs = new ILInstruction [lbls.Length];
205 for (int j = 0; j < lbls.Length; j++)
206 instrs [j] = by_offset [lbls [j]];