2 using System.Collections.Generic;
5 namespace Mono.Debugger.Soft
7 public class StackFrame : Mirror
10 AppDomainMirror domain;
14 StackFrameFlags flags;
17 * FIXME: Decide on the way to request/handle debugging information:
18 * - request the info in bulk for all frames/on demand for individual frames
19 * - request the info from the runtime/request only the il offset, and compute
20 * everything else based on this info using the method debug info.
23 internal StackFrame (VirtualMachine vm, long id, ThreadMirror thread, MethodMirror method, int il_offset, StackFrameFlags flags) : base (vm, id) {
26 this.il_offset = il_offset;
30 public ThreadMirror Thread {
36 public AppDomainMirror Domain {
39 if (vm.Version.AtLeast (2, 38)) {
41 domain = vm.GetDomain (vm.conn.StackFrame_GetDomain (thread.Id, Id));
42 } catch (AbsentInformationException) {
43 domain = Thread.Domain;
46 domain = Thread.Domain;
54 public MethodMirror Method {
60 public Location Location {
62 if (location == null) {
64 string src_file = null;
66 int column_number = 0;
67 int end_line_number = -1;
68 int end_column_number = -1;
73 line_number = method.il_offset_to_line_number (il_offset, out src_file, out hash, out column_number, out end_line_number, out end_column_number);
75 location = new Location (vm, Method, 0, il_offset, src_file != null ? src_file : method.SourceFile, line_number, column_number, end_line_number, end_column_number, hash);
81 public string FileName {
83 return Location.SourceFile;
89 return Location.ILOffset;
93 public int LineNumber {
95 return Location.LineNumber;
99 public int ColumnNumber {
101 return Location.ColumnNumber;
105 public bool IsDebuggerInvoke {
107 return (flags & StackFrameFlags.DEBUGGER_INVOKE) != 0;
112 * Whenever this frame transitions to native code. The method associated
113 * with the frame is either an InternalCall or a pinvoke method.
115 public bool IsNativeTransition {
117 return (flags & StackFrameFlags.NATIVE_TRANSITION) != 0;
121 public Value GetValue (ParameterInfoMirror param) {
123 throw new ArgumentNullException ("param");
124 if (param.Method != Method)
125 throw new ArgumentException ("Parameter doesn't belong to this frame's method.");
127 throw new ArgumentException ("Parameter represents the method return value.");
130 // FIXME: Allow returning the frame return value if possible
131 return vm.DecodeValue (vm.conn.StackFrame_GetValues (thread.Id, Id, new int [] { (- param.Position) - 1 })[0]);
134 public Value GetValue (LocalVariable var) {
136 throw new ArgumentNullException ("var");
137 if (var.Method != Method)
138 throw new ArgumentException ("Local variable doesn't belong to this frame's method.");
141 // FIXME: Check for return value
142 // FIXME: Allow returning the frame return value if possible
143 return vm.DecodeValue (vm.conn.StackFrame_GetValues (thread.Id, Id, new int [] { var.GetValueIndex } )[0]);
146 public Value[] GetValues (LocalVariable[] vars) {
148 throw new ArgumentNullException ("vars");
149 for (int i = 0; i < vars.Length; ++i) {
150 if (vars [i] == null)
151 throw new ArgumentNullException ("vars");
152 if (vars [i].Method != Method)
153 throw new ArgumentException ("Local variable doesn't belong to this frame's method.");
155 int[] pos = new int [vars.Length];
156 for (int i = 0; i < vars.Length; ++i)
157 pos [i] = vars [i].GetValueIndex;
158 return vm.DecodeValues (vm.conn.StackFrame_GetValues (thread.Id, Id, pos));
161 public Value GetArgument (int pos) {
162 return GetValue (Method.GetParameters () [pos]);
165 public Value GetThis () {
166 return vm.DecodeValue (vm.conn.StackFrame_GetThis (thread.Id, Id));
169 // Since protocol version 2.44
170 public void SetThis (Value value) {
172 throw new ArgumentNullException ("value");
173 if (Method.IsStatic || !Method.DeclaringType.IsValueType)
174 throw new InvalidOperationException ("The frame's method needs to be a valuetype instance method.");
175 vm.conn.StackFrame_SetThis (thread.Id, Id, vm.EncodeValue (value));
178 public void SetValue (LocalVariable var, Value value) {
180 throw new ArgumentNullException ("var");
181 if (var.Method != Method)
182 throw new ArgumentException ("Local variable doesn't belong to this frame's method.");
184 throw new ArgumentNullException ("value");
187 // FIXME: Check for return value
189 vm.conn.StackFrame_SetValues (thread.Id, Id, new int [] { var.GetValueIndex }, new ValueImpl [] { vm.EncodeValue (value) });
190 } catch (CommandException ex) {
191 if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
192 throw new ArgumentException ("Value does not match the type of the local variable.");
198 public void SetValue (ParameterInfoMirror param, Value value) {
200 throw new ArgumentNullException ("param");
201 if (param.Method != Method)
202 throw new ArgumentException ("Parameter doesn't belong to this frame's method.");
204 throw new ArgumentException ("Parameter represents the method return value.");
206 throw new ArgumentNullException ("value");
210 // FIXME: Allow setting the frame return value if possible
212 vm.conn.StackFrame_SetValues (thread.Id, Id, new int [] { (- param.Position) - 1 }, new ValueImpl [] { vm.EncodeValue (value) });
213 } catch (CommandException ex) {
214 if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
215 throw new ArgumentException ("Value does not match the type of the variable.");
221 public IList<LocalVariable> GetVisibleVariables () {
222 if (Location.ILOffset == -1)
223 throw new AbsentInformationException ();
225 return Method.GetLocals ().Where (l => l.LiveRangeStart <= location.ILOffset && l.LiveRangeEnd >= location.ILOffset).ToList ();
228 public LocalVariable GetVisibleVariableByName (string name) {
230 throw new ArgumentNullException ("name");
232 if (Location.ILOffset == -1)
233 throw new AbsentInformationException ();
235 return Method.GetLocals ().Where (l => l.LiveRangeStart <= location.ILOffset && l.LiveRangeEnd >= location.ILOffset && l.Name == name).FirstOrDefault ();