OLD | NEW |
| (Empty) |
1 // Copyright 2009 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can | |
3 // be found in the LICENSE file. | |
4 using System; | |
5 using System.Collections.Generic; | |
6 using System.Diagnostics; | |
7 using Google.MsAd7.BaseImpl.Ad7Enumerators; | |
8 using Google.MsAd7.BaseImpl.DebugProperties; | |
9 using Google.MsAd7.BaseImpl.Interfaces; | |
10 using Google.MsAd7.BaseImpl.Interfaces.SimpleSymbolTypes; | |
11 using Microsoft.VisualStudio; | |
12 using Microsoft.VisualStudio.Debugger.Interop; | |
13 | |
14 namespace Google.MsAd7.BaseImpl { | |
15 /// <summary> | |
16 /// StackFrame represents a frame on the stack. It also implements | |
17 /// IDebugExpressionContext2, because the current stack frame determines | |
18 /// how expressions should be evaluated. | |
19 /// A stackframe consist of: | |
20 /// Code Context: The location of the first line of the compilation unit | |
21 /// that describes the scope in this stack frame. Generally the location | |
22 /// of an opening parenthesis. | |
23 /// Thread ID: The thread id. | |
24 /// Module: The name of a nexe, its code address, and it's fully qualified | |
25 /// location. | |
26 /// Function: A function's name and DWARF Id. | |
27 /// </summary> | |
28 public class StackFrame : IDebugStackFrame2, IDebugExpressionContext2 { | |
29 public StackFrame(RegisterSet rset, | |
30 IDebugThread2 thread, | |
31 Module module, | |
32 ISimpleDebugger dbg) { | |
33 programCounter_ = rset["RIP"]; | |
34 DocumentContext dc = DocumentContext.FromAddress(programCounter_, dbg); | |
35 if (dc == null){ | |
36 return; | |
37 } | |
38 CodeContext cc = dc.CodeContexts[0]; | |
39 Function fn = dbg.Symbols.FunctionFromAddress(programCounter_); | |
40 | |
41 codeContext_ = cc; | |
42 thread_ = thread; | |
43 module_ = module; | |
44 func_ = fn; | |
45 dbg_ = dbg; | |
46 | |
47 rootProperty_ = new DebugPropertyBase( | |
48 null, | |
49 fn.Name, | |
50 "[ROOT PROPERTY TYPE]", | |
51 fn.Id, | |
52 0, | |
53 enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_METHOD, | |
54 dbg_); | |
55 | |
56 registers_ = new DebugPropertyBase( | |
57 rootProperty_, | |
58 "Registers", "", "", 0, enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_NONE, dbg_); | |
59 rset.Parent = registers_; | |
60 } | |
61 | |
62 public Function Func { | |
63 get { return func_; } | |
64 } | |
65 | |
66 public CodeContext CodeContext { | |
67 get { return codeContext_; } | |
68 } | |
69 | |
70 public Module Module { | |
71 get { return module_; } | |
72 } | |
73 | |
74 public ulong ReturnAddress { get { return programCounter_; } } | |
75 | |
76 | |
77 #region IDebugExpressionContext2 Members | |
78 | |
79 public int ParseText(string pszCode, | |
80 enum_PARSEFLAGS dwFlags, | |
81 uint nRadix, | |
82 out IDebugExpression2 ppExpr, | |
83 out string pbstrError, | |
84 out uint pichError) { | |
85 Debug.WriteLine("StackFrame.ParseText"); | |
86 | |
87 ppExpr = null; | |
88 pbstrError = "<unknown>"; | |
89 pichError = (uint)pbstrError.Length; | |
90 | |
91 if (properties_.ContainsKey(pszCode)) | |
92 { | |
93 ppExpr = new SimpleExpression(properties_[pszCode]); | |
94 pbstrError = null; | |
95 pichError = 0; | |
96 return VSConstants.S_OK; | |
97 } else if (Char.IsNumber(pszCode,0)) { | |
98 // If it's a number, we interpret it as an address | |
99 string trimmed = pszCode.Trim(); | |
100 int radix = 16; // VS assumes hex for addresses | |
101 if (trimmed[0] == '0') { | |
102 if (trimmed.Length >= 2 && trimmed[1] == 'x') { | |
103 radix = 16; | |
104 trimmed = trimmed.Substring(2); | |
105 } else { | |
106 radix = 8; | |
107 } | |
108 } | |
109 ulong address = Convert.ToUInt64(trimmed, radix); | |
110 | |
111 if (address != 0) { | |
112 var memProp = new DebugPropertyBase( | |
113 null, | |
114 pszCode, | |
115 "void*", | |
116 0, | |
117 address, | |
118 enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_DATA, | |
119 dbg_); | |
120 ppExpr = new SimpleExpression(memProp); | |
121 pbstrError = null; | |
122 pichError = 0; | |
123 } | |
124 return VSConstants.S_OK; | |
125 } | |
126 | |
127 return (ppExpr != null) ? VSConstants.S_OK : VSConstants.E_FAIL; | |
128 } | |
129 | |
130 #endregion | |
131 | |
132 #region IDebugStackFrame2 Members | |
133 | |
134 public int GetCodeContext(out IDebugCodeContext2 ppCodeCxt) { | |
135 Debug.WriteLine("StackFrame.GetCodeContext"); | |
136 ppCodeCxt = codeContext_; | |
137 return VSConstants.S_OK; | |
138 } | |
139 | |
140 public int GetDocumentContext(out IDebugDocumentContext2 ppCxt) { | |
141 Debug.WriteLine("StackFrame.GetDocumentContext"); | |
142 codeContext_.GetDocumentContext(out ppCxt); | |
143 return VSConstants.S_OK; | |
144 } | |
145 | |
146 public int GetName(out string pbstrName) { | |
147 Debug.WriteLine("StackFrame.GetName"); | |
148 pbstrName = func_.Name; | |
149 return VSConstants.S_OK; | |
150 } | |
151 | |
152 public int GetInfo(enum_FRAMEINFO_FLAGS dwFieldSpec, | |
153 uint nRadix, | |
154 FRAMEINFO[] pFrameInfo) { | |
155 Debug.WriteLine("StackFrame.GetInfo"); | |
156 string fmt = (nRadix == 16) ? "X" : "D"; | |
157 | |
158 /* | |
159 * Experimental value of dwFieldSpec: | |
160 enum_FRAMEINFO_FLAGS.FIF_FUNCNAME | |
161 | enum_FRAMEINFO_FLAGS.FIF_LANGUAGE | |
162 | enum_FRAMEINFO_FLAGS.FIF_STACKRANGE | |
163 | enum_FRAMEINFO_FLAGS.FIF_FRAME | |
164 | enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO | |
165 | enum_FRAMEINFO_FLAGS.FIF_STALECODE | |
166 | enum_FRAMEINFO_FLAGS.FIF_FLAGS | |
167 | enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP | |
168 | enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_FORMAT | |
169 | enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS | |
170 | enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE | |
171 | enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES | |
172 | enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_OFFSET | |
173 | enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES | |
174 | enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES | |
175 | enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES | |
176 | enum_FRAMEINFO_FLAGS.FIF_FILTER_NON_USER_CODE; | |
177 */ | |
178 | |
179 pFrameInfo[0].m_addrMin = codeContext_.Address; | |
180 pFrameInfo[0].m_addrMax = codeContext_.Address + codeContext_.Count; | |
181 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STACKRANGE; | |
182 | |
183 pFrameInfo[0].m_bstrArgs = ""; | |
184 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_ARGS; | |
185 | |
186 pFrameInfo[0].m_bstrFuncName = func_.Name; | |
187 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME; | |
188 | |
189 pFrameInfo[0].m_bstrLanguage = "C++"; | |
190 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_LANGUAGE; | |
191 | |
192 pFrameInfo[0].m_bstrReturnType = "void"; | |
193 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_RETURNTYPE; | |
194 | |
195 pFrameInfo[0].m_bstrModule = module_.Name; | |
196 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_MODULE; | |
197 | |
198 pFrameInfo[0].m_pFrame = this; | |
199 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FRAME; | |
200 | |
201 pFrameInfo[0].m_pModule = module_; | |
202 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP; | |
203 | |
204 pFrameInfo[0].m_fHasDebugInfo = 1; | |
205 pFrameInfo[0].m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO; | |
206 | |
207 return VSConstants.S_OK; | |
208 } | |
209 | |
210 public int GetPhysicalStackRange(out ulong paddrMin, out ulong paddrMax) { | |
211 Debug.WriteLine("StackFrame.GetPhysicalStackRange"); | |
212 paddrMin = codeContext_.Address; | |
213 paddrMax = paddrMin + codeContext_.Count; | |
214 return VSConstants.S_OK; | |
215 } | |
216 | |
217 public int GetExpressionContext(out IDebugExpressionContext2 ppExprCxt) { | |
218 Debug.WriteLine("StackFrame.GetExpressionContext"); | |
219 ppExprCxt = this; | |
220 return VSConstants.S_OK; | |
221 } | |
222 | |
223 public int GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage)
{ | |
224 Debug.WriteLine("StackFrame.GetLanguageInfo"); | |
225 | |
226 codeContext_.GetLanguageInfo(ref pbstrLanguage, ref pguidLanguage); | |
227 | |
228 return VSConstants.S_OK; | |
229 } | |
230 | |
231 public int GetDebugProperty(out IDebugProperty2 ppProperty) { | |
232 Debug.WriteLine("StackFrame.GetDebugProperty"); | |
233 | |
234 ppProperty = rootProperty_; | |
235 return VSConstants.S_OK; | |
236 } | |
237 | |
238 /// <summary> | |
239 /// EnumProperties is called by the Visual Studio Debugger to get | |
240 /// information about each stack frame that applies to the thread being | |
241 /// debugged. Detailed infromation about the parameters can be found on | |
242 /// msdn. | |
243 /// </summary> | |
244 public int EnumProperties(enum_DEBUGPROP_INFO_FLAGS dwFields, | |
245 uint nRadix, | |
246 ref Guid guidFilter, | |
247 uint dwTimeout, | |
248 out uint pcelt, | |
249 out IEnumDebugPropertyInfo2 ppEnum) { | |
250 ppEnum = null; | |
251 pcelt = 0; | |
252 | |
253 Debug.WriteLine("StackFrame.EnumProperties"); | |
254 if (properties_.Count < 1) { | |
255 RefreshProperties(); | |
256 } | |
257 | |
258 DebugPropertyBase root = rootProperty_; | |
259 if (guidFilter == Guids.guidFilterRegisters) { | |
260 root = registers_; | |
261 } | |
262 | |
263 root.EnumChildren( | |
264 dwFields, | |
265 nRadix, | |
266 ref guidFilter, | |
267 enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ALL, | |
268 "", | |
269 uint.MaxValue, | |
270 out ppEnum); | |
271 | |
272 | |
273 if (ppEnum != null) { | |
274 ppEnum.GetCount(out pcelt); | |
275 } | |
276 return VSConstants.S_OK; | |
277 } | |
278 | |
279 /// <summary> | |
280 /// Gets the symbols that are defined in the current scope and adds them | |
281 /// to this frame's property information. The information being gathered | |
282 /// here will help the debugger retrieve the values of specific variables | |
283 /// later. | |
284 /// </summary> | |
285 private void RefreshProperties() { | |
286 properties_.Clear(); | |
287 | |
288 var symbols = dbg_.Symbols.GetSymbolsInScope(codeContext_.Address); | |
289 | |
290 foreach (var symbol in symbols) { | |
291 var prop = new Variable( | |
292 rootProperty_, | |
293 symbol, | |
294 enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_DATA, | |
295 dbg_); | |
296 properties_.Add(prop.Name, prop); | |
297 } | |
298 } | |
299 | |
300 public int GetThread(out IDebugThread2 ppThread) { | |
301 Debug.WriteLine("StackFrame.GetThread"); | |
302 ppThread = thread_; | |
303 return VSConstants.S_OK; | |
304 } | |
305 | |
306 #endregion | |
307 | |
308 #region Private Implementation | |
309 | |
310 private readonly ulong programCounter_; | |
311 private readonly CodeContext codeContext_; | |
312 private readonly Module module_; | |
313 private readonly IDebugThread2 thread_; | |
314 private Function func_; | |
315 private ISimpleDebugger dbg_; | |
316 private DebugPropertyBase rootProperty_; | |
317 private DebugPropertyBase registers_; | |
318 private readonly Dictionary<string, DebugPropertyBase> properties_ = new Dic
tionary<string, DebugPropertyBase>(); | |
319 | |
320 #endregion | |
321 } | |
322 } | |
OLD | NEW |