blob: 64018692b7cf8fdd04f787f635c3a7c19c0ac5fb [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Variable.cpp --------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Symbol/Variable.h"
11
12#include "lldb/Core/Stream.h"
Greg Clayton3bc52d02010-11-14 22:13:40 +000013#include "lldb/Core/RegularExpression.h"
Greg Clayton5d81f492011-07-08 21:46:14 +000014#include "lldb/Core/ValueObject.h"
15#include "lldb/Core/ValueObjectVariable.h"
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Symbol/Block.h"
17#include "lldb/Symbol/Function.h"
18#include "lldb/Symbol/SymbolContext.h"
19#include "lldb/Symbol/Type.h"
Greg Clayton5d81f492011-07-08 21:46:14 +000020#include "lldb/Symbol/VariableList.h"
Greg Claytoneea26402010-09-14 23:36:40 +000021#include "lldb/Target/Process.h"
Greg Claytonb04e7a82010-08-24 21:05:24 +000022#include "lldb/Target/RegisterContext.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Target/StackFrame.h"
24#include "lldb/Target/Thread.h"
Greg Claytoneea26402010-09-14 23:36:40 +000025#include "lldb/Target/Target.h"
Chris Lattner24943d22010-06-08 16:52:24 +000026
27using namespace lldb;
28using namespace lldb_private;
29
30//----------------------------------------------------------------------
31// Variable constructor
32//----------------------------------------------------------------------
Greg Clayton3bc52d02010-11-14 22:13:40 +000033Variable::Variable
34(
35 lldb::user_id_t uid,
36 const char *name,
37 const char *mangled, // The mangled variable name for variables in namespaces
38 Type *type,
39 ValueType scope,
40 SymbolContextScope *context,
41 Declaration* decl_ptr,
42 const DWARFExpression& location,
43 bool external,
44 bool artificial
45) :
Chris Lattner24943d22010-06-08 16:52:24 +000046 UserID(uid),
47 m_name(name),
Greg Clayton3bc52d02010-11-14 22:13:40 +000048 m_mangled (mangled, true),
Chris Lattner24943d22010-06-08 16:52:24 +000049 m_type(type),
50 m_scope(scope),
Greg Clayton4fb08152010-08-30 18:11:35 +000051 m_owner_scope(context),
Chris Lattner24943d22010-06-08 16:52:24 +000052 m_declaration(decl_ptr),
53 m_location(location),
54 m_external(external),
55 m_artificial(artificial)
56{
57}
58
59//----------------------------------------------------------------------
60// Destructor
61//----------------------------------------------------------------------
62Variable::~Variable()
63{
64}
65
66
Greg Clayton3bc52d02010-11-14 22:13:40 +000067const ConstString&
68Variable::GetName() const
69{
70 if (m_mangled)
71 return m_mangled.GetName();
72 return m_name;
73}
74
75bool
76Variable::NameMatches (const RegularExpression& regex) const
77{
78 if (regex.Execute (m_name.AsCString()))
79 return true;
80 return m_mangled.NameMatches (regex);
81}
82
Chris Lattner24943d22010-06-08 16:52:24 +000083void
84Variable::Dump(Stream *s, bool show_context) const
85{
86 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
87 s->Indent();
88 *s << "Variable" << (const UserID&)*this;
89
90 if (m_name)
91 *s << ", name = \"" << m_name << "\"";
92
93 if (m_type != NULL)
94 {
Greg Claytonfb7c51c2010-10-13 03:15:28 +000095 *s << ", type = {" << m_type->GetID() << "} " << (void*)m_type << " (";
Chris Lattner24943d22010-06-08 16:52:24 +000096 m_type->DumpTypeName(s);
97 s->PutChar(')');
98 }
99
100 if (m_scope != eValueTypeInvalid)
101 {
102 s->PutCString(", scope = ");
103 switch (m_scope)
104 {
105 case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break;
106 case eValueTypeVariableArgument: s->PutCString("parameter"); break;
107 case eValueTypeVariableLocal: s->PutCString("local"); break;
108 default: *s << "??? (" << m_scope << ')';
109 }
110 }
111
Greg Clayton4fb08152010-08-30 18:11:35 +0000112 if (show_context && m_owner_scope != NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000113 {
114 s->PutCString(", context = ( ");
Greg Clayton4fb08152010-08-30 18:11:35 +0000115 m_owner_scope->DumpSymbolContext(s);
Chris Lattner24943d22010-06-08 16:52:24 +0000116 s->PutCString(" )");
117 }
118
Greg Clayton1924e242010-09-15 05:51:24 +0000119 bool show_fullpaths = false;
120 m_declaration.Dump(s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +0000121
122 if (m_location.IsValid())
123 {
124 s->PutCString(", location = ");
Greg Clayton178710c2010-09-14 02:20:48 +0000125 lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
126 if (m_location.IsLocationList())
127 {
128 SymbolContext variable_sc;
129 m_owner_scope->CalculateSymbolContext(&variable_sc);
130 if (variable_sc.function)
131 loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
132 }
133 m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000134 }
135
136 if (m_external)
137 s->PutCString(", external");
138
139 if (m_artificial)
140 s->PutCString(", artificial");
141
142 s->EOL();
143}
144
Greg Claytonfb816422011-07-10 19:21:23 +0000145bool
146Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module)
147{
148 bool dumped_declaration_info = false;
149 if (m_owner_scope)
150 {
151 SymbolContext sc;
152 m_owner_scope->CalculateSymbolContext(&sc);
153 sc.block = NULL;
154 sc.line_entry.Clear();
155 bool show_inlined_frames = false;
156
157 dumped_declaration_info = sc.DumpStopContext (s,
158 NULL,
159 Address(),
160 show_fullpaths,
161 show_module,
162 show_inlined_frames);
163
164 if (sc.function)
165 s->PutChar(':');
166 }
167 if (m_declaration.DumpStopContext (s, false))
168 dumped_declaration_info = true;
169 return dumped_declaration_info;
170}
Chris Lattner24943d22010-06-08 16:52:24 +0000171
172size_t
173Variable::MemorySize() const
174{
175 return sizeof(Variable);
176}
177
178
179void
180Variable::CalculateSymbolContext (SymbolContext *sc)
181{
Greg Clayton4fb08152010-08-30 18:11:35 +0000182 if (m_owner_scope)
183 m_owner_scope->CalculateSymbolContext(sc);
Chris Lattner24943d22010-06-08 16:52:24 +0000184 else
185 sc->Clear();
186}
187
Greg Clayton82f07462011-05-30 00:49:24 +0000188bool
189Variable::LocationIsValidForFrame (StackFrame *frame)
190{
191 // Is the variable is described by a single location?
192 if (!m_location.IsLocationList())
193 {
194 // Yes it is, the location is valid.
195 return true;
196 }
197
198 if (frame)
199 {
200 Target *target = &frame->GetThread().GetProcess().GetTarget();
201
202 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
203 if (function)
204 {
205 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
206 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
207 return false;
208 // It is a location list. We just need to tell if the location
209 // list contains the current address when converted to a load
210 // address
211 return m_location.LocationListContainsAddress (loclist_base_load_addr,
212 frame->GetFrameCodeAddress().GetLoadAddress (target));
213 }
214 }
215 return false;
216}
Chris Lattner24943d22010-06-08 16:52:24 +0000217
218bool
219Variable::IsInScope (StackFrame *frame)
220{
221 switch (m_scope)
222 {
Greg Clayton82f07462011-05-30 00:49:24 +0000223 case eValueTypeRegister:
224 case eValueTypeRegisterSet:
225 return frame != NULL;
226
227 case eValueTypeConstResult:
Greg Clayton82f07462011-05-30 00:49:24 +0000228 case eValueTypeVariableGlobal:
229 case eValueTypeVariableStatic:
Greg Clayton24b03102011-07-09 20:12:33 +0000230 return true;
231
Chris Lattner24943d22010-06-08 16:52:24 +0000232 case eValueTypeVariableArgument:
233 case eValueTypeVariableLocal:
Greg Clayton82f07462011-05-30 00:49:24 +0000234 if (frame)
Chris Lattner24943d22010-06-08 16:52:24 +0000235 {
236 // We don't have a location list, we just need to see if the block
237 // that this variable was defined in is currently
Greg Claytona357ecf2010-09-14 03:16:58 +0000238 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
239 if (deepest_frame_block)
Chris Lattner24943d22010-06-08 16:52:24 +0000240 {
241 SymbolContext variable_sc;
242 CalculateSymbolContext (&variable_sc);
Greg Clayton82f07462011-05-30 00:49:24 +0000243 // Check for static or global variable defined at the compile unit
244 // level that wasn't defined in a block
245 if (variable_sc.block == NULL)
246 return true;
247
Greg Claytona357ecf2010-09-14 03:16:58 +0000248 if (variable_sc.block == deepest_frame_block)
Greg Clayton178710c2010-09-14 02:20:48 +0000249 return true;
Greg Claytona357ecf2010-09-14 03:16:58 +0000250 return variable_sc.block->Contains (deepest_frame_block);
Chris Lattner24943d22010-06-08 16:52:24 +0000251 }
252 }
253 break;
254
255 default:
Chris Lattner24943d22010-06-08 16:52:24 +0000256 break;
257 }
258 return false;
259}
260
Greg Clayton5d81f492011-07-08 21:46:14 +0000261Error
262Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
263 ExecutionContextScope *scope,
264 GetVariableCallback callback,
265 void *baton,
266 VariableList &variable_list,
267 ValueObjectList &valobj_list)
268{
269 Error error;
270 if (variable_expr_path && callback)
271 {
272 switch (variable_expr_path[0])
273 {
274 case '*':
275 {
276 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
277 scope,
278 callback,
279 baton,
280 variable_list,
281 valobj_list);
282 if (error.Success())
283 {
284 for (uint32_t i=0; i<valobj_list.GetSize(); )
285 {
286 Error tmp_error;
287 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
288 if (tmp_error.Fail())
289 {
290 variable_list.RemoveVariableAtIndex (i);
291 valobj_list.RemoveValueObjectAtIndex (i);
292 }
293 else
294 {
295 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
296 ++i;
297 }
298 }
299 }
300 else
301 {
302 error.SetErrorString ("unknown error");
303 }
304 return error;
305 }
306 break;
307
308 case '&':
309 {
310 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
311 scope,
312 callback,
313 baton,
314 variable_list,
315 valobj_list);
316 if (error.Success())
317 {
318 for (uint32_t i=0; i<valobj_list.GetSize(); )
319 {
320 Error tmp_error;
321 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
322 if (tmp_error.Fail())
323 {
324 variable_list.RemoveVariableAtIndex (i);
325 valobj_list.RemoveValueObjectAtIndex (i);
326 }
327 else
328 {
329 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
330 ++i;
331 }
332 }
333 }
334 else
335 {
336 error.SetErrorString ("unknown error");
337 }
338 return error;
339 }
340 break;
341
342 default:
343 {
344 RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
345 if (regex.Execute(variable_expr_path, 1))
346 {
347 std::string variable_name;
348 if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name))
349 {
350 variable_list.Clear();
351 if (callback (baton, variable_name.c_str(), variable_list))
352 {
353 uint32_t i=0;
354 while (i < variable_list.GetSize())
355 {
356 VariableSP var_sp (variable_list.GetVariableAtIndex (i));
357 ValueObjectSP valobj_sp;
358 if (var_sp)
359 {
360 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
361 if (variable_valobj_sp)
362 {
363 variable_expr_path += variable_name.size();
364 if (*variable_expr_path)
365 {
366 const char* first_unparsed = NULL;
367 ValueObject::ExpressionPathScanEndReason reason_to_stop;
368 ValueObject::ExpressionPathEndResultType final_value_type;
369 ValueObject::GetValueForExpressionPathOptions options;
370 ValueObject::ExpressionPathAftermath final_task_on_target;
371
372 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path,
373 &first_unparsed,
374 &reason_to_stop,
375 &final_value_type,
376 options,
377 &final_task_on_target);
378 if (!valobj_sp)
379 {
380 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
381 variable_expr_path,
382 var_sp->GetName().GetCString());
383 }
384 }
385 else
386 {
387 // Just the name of a variable with no extras
388 valobj_sp = variable_valobj_sp;
389 }
390 }
391 }
392
393 if (!var_sp || !valobj_sp)
394 {
395 variable_list.RemoveVariableAtIndex (i);
396 }
397 else
398 {
399 valobj_list.Append(valobj_sp);
400 ++i;
401 }
402 }
403
404 if (variable_list.GetSize() > 0)
405 {
406 error.Clear();
407 return error;
408 }
409 }
410 }
411 }
412 error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path);
413 }
414 break;
415 }
416 }
417 error.SetErrorString ("unknown error");
418 return error;
419}
420