2 using System.Collections.Generic;
5 using Mono.Cecil.Metadata;
7 using System.Reflection;
9 namespace Mono.Debugger.Soft
11 public class MethodBodyMirror : Mirror
16 internal MethodBodyMirror (VirtualMachine vm, MethodMirror method, byte[] il) : base (vm, 0) {
21 public MethodMirror Method {
27 public byte[] GetILAsByteArray () {
31 public List<ILInstruction> Instructions {
33 return ReadCilBody (new BinaryReader (new MemoryStream (il)), il.Length);
37 static bool opcodes_inited;
39 static OpCode [] OneByteOpCode = new OpCode [0xe0 + 1];
40 static OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1];
43 List<ILInstruction> ReadCilBody (BinaryReader br, int code_size)
45 long start = br.BaseStream.Position;
46 ILInstruction last = null;
47 //GenericContext context = new GenericContext (body.Method);
48 List<ILInstruction> code = new List<ILInstruction> ();
50 var by_offset = new Dictionary<int, ILInstruction> ();
52 if (!opcodes_inited) {
53 foreach (FieldInfo fi in typeof (OpCodes).GetFields (BindingFlags.Static|BindingFlags.Public)) {
54 var val = (OpCode)fi.GetValue (null);
57 OneByteOpCode [val.Op2] = val;
59 TwoBytesOpCode [val.Op2] = val;
61 opcodes_inited = true;
64 while (br.BaseStream.Position < start + code_size) {
66 long offset = br.BaseStream.Position - start;
67 int cursor = br.ReadByte ();
72 op = TwoBytesOpCode [br.ReadByte ()];
74 op = OneByteOpCode [cursor];
76 ILInstruction instr = new ILInstruction ((int)offset, op, null);
78 by_offset [instr.Offset] = instr;
80 switch (op.OperandType) {
81 case OperandType.InlineNone :
83 case OperandType.InlineSwitch :
84 uint length = br.ReadUInt32 ();
85 int [] branches = new int [length];
86 int [] buf = new int [length];
87 for (int i = 0; i < length; i++)
88 buf [i] = br.ReadInt32 ();
89 for (int i = 0; i < length; i++)
90 branches [i] = Convert.ToInt32 (br.BaseStream.Position - start + buf [i]);
91 instr.Operand = branches;
93 case OperandType.ShortInlineBrTarget :
94 sbyte sbrtgt = br.ReadSByte ();
95 instr.Operand = Convert.ToInt32 (br.BaseStream.Position - start + sbrtgt);
97 case OperandType.InlineBrTarget :
98 int brtgt = br.ReadInt32 ();
99 instr.Operand = Convert.ToInt32 (br.BaseStream.Position - start + brtgt);
101 case OperandType.ShortInlineI :
102 if (op == OpCodes.Ldc_I4_S)
103 instr.Operand = br.ReadSByte ();
105 instr.Operand = br.ReadByte ();
107 case OperandType.ShortInlineVar :
108 instr.Operand = br.ReadByte ();
110 case OperandType.ShortInlineArg :
111 instr.Operand = br.ReadByte ();
113 case OperandType.InlineSig :
115 //instr.Operand = GetCallSiteAt (br.ReadInt32 (), context);
117 case OperandType.InlineI :
118 instr.Operand = br.ReadInt32 ();
120 case OperandType.InlineVar :
121 instr.Operand = br.ReadInt16 ();
123 case OperandType.InlineArg :
124 instr.Operand = br.ReadInt16 ();
126 case OperandType.InlineI8 :
127 instr.Operand = br.ReadInt64 ();
129 case OperandType.ShortInlineR :
130 instr.Operand = br.ReadSingle ();
132 case OperandType.InlineR :
133 instr.Operand = br.ReadDouble ();
135 case OperandType.InlineString :
136 token = br.ReadInt32 ();
137 t = vm.conn.Method_ResolveToken (Method.Id, token);
138 if (t.Type == TokenType.STRING)
139 instr.Operand = t.Str;
141 case OperandType.InlineField :
142 case OperandType.InlineMethod :
143 case OperandType.InlineType :
144 case OperandType.InlineTok :
145 token = br.ReadInt32 ();
147 t = vm.conn.Method_ResolveToken (Method.Id, token);
151 instr.Operand = vm.GetType (t.Id);
153 case TokenType.FIELD:
154 // FIXME: No vm.GetField ()
155 //instr.Operand = vm.GetField (t.Id);
157 case TokenType.METHOD:
158 instr.Operand = vm.GetMethod (t.Id);
160 case TokenType.UNKNOWN:
163 throw new NotImplementedException ("Unknown token type: " + t.Type);
170 instr.Previous = last;
179 foreach (ILInstruction i in code) {
180 switch (i.OpCode.OperandType) {
181 case OperandType.ShortInlineBrTarget:
182 case OperandType.InlineBrTarget:
183 i.Operand = by_offset [(int)i.Operand];
185 case OperandType.InlineSwitch:
186 int [] lbls = (int []) i.Operand;
187 ILInstruction [] instrs = new ILInstruction [lbls.Length];
188 for (int j = 0; j < lbls.Length; j++)
189 instrs [j] = by_offset [lbls [j]];