3 using System
.Collections
.Generic
;
5 using MD
= Mono
.Debugger
;
6 using DL
= Mono
.Debugging
.Client
;
8 using Mono
.Debugging
.Client
;
9 using Mono
.Debugging
.Backend
;
10 using Mono
.Debugger
.Languages
;
12 namespace DebuggerServer
14 class BacktraceWrapper
: RemoteFrameObject
, IBacktrace
, IDisposable
16 MD
.StackFrame
[] frames
;
17 DissassemblyBuffer
[] disBuffers
;
20 public BacktraceWrapper (MD
.StackFrame
[] frames
)
26 public void Dispose ()
31 public int FrameCount
{
32 get { return frames.Length; }
35 public DL
.StackFrame
[] GetStackFrames (int firstIndex
, int lastIndex
)
39 //FIXME: validate indices
41 List
<DL
.StackFrame
> list
= new List
<DL
.StackFrame
> ();
42 for (int i
= firstIndex
; i
<= lastIndex
&& i
< frames
.Length
; i
++) {
43 MD
.StackFrame frame
= frames
[i
];
45 string filename
= null;
48 if (frame
.Method
!= null) {
49 method
= frame
.Method
.Name
;
50 if (!method
.StartsWith ("<")) {
51 int p
= method
.IndexOf ('(');
53 method
= method
.Substring (0, p
).Trim ();
55 } else if (frame
.Name
!= null) {
56 method
= frame
.Name
.Name
;
61 if (frame
.SourceAddress
!= null) {
62 if (frame
.SourceAddress
.SourceFile
!= null)
63 filename
= frame
.SourceAddress
.SourceFile
.FileName
;
64 line
= frame
.SourceAddress
.Row
;
67 string lang
= frame
.Language
!= null ? frame
.Language
.Name
: string.Empty
;
68 list
.Add (new DL
.StackFrame (frame
.TargetAddress
.Address
, new DL
.SourceLocation (method
, filename
, line
), lang
));
71 return list
.ToArray ();
74 EvaluationContext
GetEvaluationContext (int frameIndex
, int timeout
)
78 timeout
= DebuggerServer
.DefaultEvaluationTimeout
;
79 MD
.StackFrame frame
= frames
[frameIndex
];
80 return new EvaluationContext (frame
.Thread
, frame
, timeout
);
83 public ObjectValue
[] GetLocalVariables (int frameIndex
, int timeout
)
85 EvaluationContext ctx
= GetEvaluationContext (frameIndex
, timeout
);
86 List
<ObjectValue
> vars
= new List
<ObjectValue
> ();
87 foreach (VariableReference vref
in Util
.GetLocalVariables (ctx
))
88 vars
.Add (vref
.CreateObjectValue (true));
89 return vars
.ToArray ();
92 public ObjectValue
[] GetParameters (int frameIndex
, int timeout
)
95 EvaluationContext ctx
= GetEvaluationContext (frameIndex
, timeout
);
96 List
<ObjectValue
> vars
= new List
<ObjectValue
> ();
97 foreach (VariableReference vref
in Util
.GetParameters (ctx
)) {
98 vars
.Add (vref
.CreateObjectValue (true));
100 return vars
.ToArray ();
102 return new ObjectValue
[0];
106 public ObjectValue
GetThisReference (int frameIndex
, int timeout
)
108 EvaluationContext ctx
= GetEvaluationContext (frameIndex
, timeout
);
109 if (ctx
.Frame
.Method
!= null && ctx
.Frame
.Method
.HasThis
) {
110 ObjectValueFlags flags
= ObjectValueFlags
.Field
| ObjectValueFlags
.ReadOnly
;
111 TargetVariable
var = ctx
.Frame
.Method
.GetThis (ctx
.Thread
);
112 VariableReference vref
= new VariableReference (ctx
, var, flags
);
113 return vref
.CreateObjectValue ();
119 public ObjectValue
[] GetAllLocals (int frameIndex
, int timeout
)
121 EvaluationContext ctx
= GetEvaluationContext (frameIndex
, timeout
);
123 List
<ObjectValue
> locals
= new List
<ObjectValue
> ();
125 // 'This' reference, or a reference to the type if the method is static
127 ObjectValue val
= GetThisReference (frameIndex
, timeout
);
130 else if (ctx
.Frame
.Method
!= null) {
131 TargetType t
= ctx
.Frame
.Method
.GetDeclaringType (ctx
.Thread
);
133 ValueReference vr
= new TypeValueReference (ctx
, t
);
134 locals
.Add (vr
.CreateObjectValue (true));
139 locals
.AddRange (GetParameters (frameIndex
, timeout
));
142 locals
.AddRange (GetLocalVariables (frameIndex
, timeout
));
144 return locals
.ToArray ();
147 public ObjectValue
[] GetExpressionValues (int frameIndex
, string[] expressions
, bool evaluateMethods
, int timeout
)
149 EvaluationContext ctx
= GetEvaluationContext (frameIndex
, timeout
);
150 ObjectValue
[] values
= new ObjectValue
[expressions
.Length
];
151 for (int n
=0; n
<values
.Length
; n
++) {
152 string exp
= expressions
[n
];
153 values
[n
] = Server
.Instance
.AsyncEvaluationTracker
.Run (exp
, ObjectValueFlags
.Literal
, delegate {
154 return GetExpressionValue (ctx
, exp
, evaluateMethods
);
160 ObjectValue
GetExpressionValue (EvaluationContext ctx
, string exp
, bool evaluateMethods
)
163 EvaluationOptions ops
= new EvaluationOptions ();
164 ops
.CanEvaluateMethods
= evaluateMethods
;
165 ValueReference
var = (ValueReference
) Server
.Instance
.Evaluator
.Evaluate (ctx
, exp
, ops
);
167 return var.CreateObjectValue ();
169 return ObjectValue
.CreateUnknown (exp
);
170 } catch (NotSupportedExpressionException ex
) {
171 return ObjectValue
.CreateNotSupported (exp
, ex
.Message
, ObjectValueFlags
.None
);
172 } catch (EvaluatorException ex
) {
173 return ObjectValue
.CreateError (exp
, ex
.Message
, ObjectValueFlags
.None
);
174 } catch (Exception ex
) {
175 Server
.Instance
.WriteDebuggerError (ex
);
176 return ObjectValue
.CreateUnknown (exp
);
180 public CompletionData
GetExpressionCompletionData (int frameIndex
, string exp
)
182 EvaluationContext ctx
= GetEvaluationContext (frameIndex
, -1);
185 if (exp
[exp
.Length
- 1] == '.') {
186 exp
= exp
.Substring (0, exp
.Length
- 1);
188 while (i
< exp
.Length
) {
189 ValueReference vr
= null;
191 vr
= Server
.Instance
.Evaluator
.Evaluate (ctx
, exp
.Substring (i
), null);
193 DL
.CompletionData data
= new DL
.CompletionData ();
194 foreach (ValueReference cv
in vr
.GetChildReferences ())
195 data
.Items
.Add (new CompletionItem (cv
.Name
, cv
.Flags
));
196 data
.ExpressionLenght
= 0;
199 } catch (Exception ex
) {
200 Console
.WriteLine (ex
);
208 bool lastWastLetter
= false;
211 if (!char.IsLetterOrDigit (c
) && c
!= '_')
213 lastWastLetter
= !char.IsDigit (c
);
215 if (lastWastLetter
) {
216 string partialWord
= exp
.Substring (i
+1);
218 DL
.CompletionData data
= new DL
.CompletionData ();
219 data
.ExpressionLenght
= partialWord
.Length
;
223 foreach (ValueReference vc
in Util
.GetLocalVariables (ctx
))
224 if (vc
.Name
.StartsWith (partialWord
))
225 data
.Items
.Add (new CompletionItem (vc
.Name
, vc
.Flags
));
229 foreach (ValueReference vc
in Util
.GetParameters (ctx
))
230 if (vc
.Name
.StartsWith (partialWord
))
231 data
.Items
.Add (new CompletionItem (vc
.Name
, vc
.Flags
));
235 TargetStructObject thisobj
= null;
237 if (ctx
.Frame
.Method
.HasThis
) {
238 TargetObject ob
= ctx
.Frame
.Method
.GetThis (ctx
.Thread
).GetObject (ctx
.Frame
);
239 thisobj
= ObjectUtil
.GetRealObject (ctx
, ob
) as TargetStructObject
;
240 data
.Items
.Add (new CompletionItem ("this", DL
.ObjectValueFlags
.Field
| DL
.ObjectValueFlags
.ReadOnly
));
243 TargetStructType type
= ctx
.Frame
.Method
.GetDeclaringType (ctx
.Thread
);
245 foreach (ValueReference vc
in Util
.GetMembers (ctx
, type
, thisobj
))
246 if (vc
.Name
.StartsWith (partialWord
))
247 data
.Items
.Add (new CompletionItem (vc
.Name
, vc
.Flags
));
249 if (data
.Items
.Count
> 0)
255 public AssemblyLine
[] Disassemble (int frameIndex
, int firstLine
, int count
)
258 if (disBuffers
== null)
259 disBuffers
= new MdbDissassemblyBuffer
[frames
.Length
];
261 MD
.StackFrame frame
= frames
[frameIndex
];
262 DissassemblyBuffer buffer
= disBuffers
[frameIndex
];
263 if (buffer
== null) {
264 buffer
= new MdbDissassemblyBuffer (frame
.Thread
, frame
.TargetAddress
);
265 disBuffers
[frameIndex
] = buffer
;
268 return buffer
.GetLines (firstLine
, firstLine
+ count
- 1);
271 void CheckDisposed ()
274 throw new InvalidOperationException ("Invalid stack frame");
278 class MdbDissassemblyBuffer
: DissassemblyBuffer
281 MD
.TargetAddress baseAddr
;
283 public MdbDissassemblyBuffer (MD
.Thread thread
, MD
.TargetAddress addr
): base (addr
.Address
)
285 this.thread
= thread
;
286 this.baseAddr
= addr
;
289 public override AssemblyLine
[] GetLines (long startAddr
, long endAddr
)
291 List
<AssemblyLine
> lines
= new List
<AssemblyLine
> ();
293 MD
.TargetAddress addr
= baseAddr
+ (startAddr
- baseAddr
.Address
);
294 while (addr
.Address
<= endAddr
) {
296 MD
.AssemblerLine line
= thread
.DisassembleInstruction (null, addr
);
297 lines
.Add (new AssemblyLine (addr
.Address
, line
.Text
));
298 addr
+= line
.InstructionSize
;
300 Console
.WriteLine ("failed " + addr
.Address
);
301 lines
.Add (new AssemblyLine (addr
.Address
, "??"));
305 return lines
.ToArray ();