blob: 895fb5c6c8f47b107794fe93774a1ea6a3023c06 [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
145
146size_t
147Variable::MemorySize() const
148{
149 return sizeof(Variable);
150}
151
152
153void
154Variable::CalculateSymbolContext (SymbolContext *sc)
155{
Greg Clayton4fb08152010-08-30 18:11:35 +0000156 if (m_owner_scope)
157 m_owner_scope->CalculateSymbolContext(sc);
Chris Lattner24943d22010-06-08 16:52:24 +0000158 else
159 sc->Clear();
160}
161
Greg Clayton82f07462011-05-30 00:49:24 +0000162bool
163Variable::LocationIsValidForFrame (StackFrame *frame)
164{
165 // Is the variable is described by a single location?
166 if (!m_location.IsLocationList())
167 {
168 // Yes it is, the location is valid.
169 return true;
170 }
171
172 if (frame)
173 {
174 Target *target = &frame->GetThread().GetProcess().GetTarget();
175
176 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
177 if (function)
178 {
179 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
180 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
181 return false;
182 // It is a location list. We just need to tell if the location
183 // list contains the current address when converted to a load
184 // address
185 return m_location.LocationListContainsAddress (loclist_base_load_addr,
186 frame->GetFrameCodeAddress().GetLoadAddress (target));
187 }
188 }
189 return false;
190}
Chris Lattner24943d22010-06-08 16:52:24 +0000191
192bool
193Variable::IsInScope (StackFrame *frame)
194{
195 switch (m_scope)
196 {
Greg Clayton82f07462011-05-30 00:49:24 +0000197 case eValueTypeRegister:
198 case eValueTypeRegisterSet:
199 return frame != NULL;
200
201 case eValueTypeConstResult:
Chris Lattner24943d22010-06-08 16:52:24 +0000202 return true;
203
Greg Clayton82f07462011-05-30 00:49:24 +0000204 case eValueTypeVariableGlobal:
205 case eValueTypeVariableStatic:
Chris Lattner24943d22010-06-08 16:52:24 +0000206 case eValueTypeVariableArgument:
207 case eValueTypeVariableLocal:
Greg Clayton82f07462011-05-30 00:49:24 +0000208 if (frame)
Chris Lattner24943d22010-06-08 16:52:24 +0000209 {
210 // We don't have a location list, we just need to see if the block
211 // that this variable was defined in is currently
Greg Claytona357ecf2010-09-14 03:16:58 +0000212 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
213 if (deepest_frame_block)
Chris Lattner24943d22010-06-08 16:52:24 +0000214 {
215 SymbolContext variable_sc;
216 CalculateSymbolContext (&variable_sc);
Greg Clayton82f07462011-05-30 00:49:24 +0000217 // Check for static or global variable defined at the compile unit
218 // level that wasn't defined in a block
219 if (variable_sc.block == NULL)
220 return true;
221
Greg Claytona357ecf2010-09-14 03:16:58 +0000222 if (variable_sc.block == deepest_frame_block)
Greg Clayton178710c2010-09-14 02:20:48 +0000223 return true;
Greg Claytona357ecf2010-09-14 03:16:58 +0000224 return variable_sc.block->Contains (deepest_frame_block);
Chris Lattner24943d22010-06-08 16:52:24 +0000225 }
226 }
227 break;
228
229 default:
Chris Lattner24943d22010-06-08 16:52:24 +0000230 break;
231 }
232 return false;
233}
234
Greg Clayton5d81f492011-07-08 21:46:14 +0000235Error
236Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
237 ExecutionContextScope *scope,
238 GetVariableCallback callback,
239 void *baton,
240 VariableList &variable_list,
241 ValueObjectList &valobj_list)
242{
243 Error error;
244 if (variable_expr_path && callback)
245 {
246 switch (variable_expr_path[0])
247 {
248 case '*':
249 {
250 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
251 scope,
252 callback,
253 baton,
254 variable_list,
255 valobj_list);
256 if (error.Success())
257 {
258 for (uint32_t i=0; i<valobj_list.GetSize(); )
259 {
260 Error tmp_error;
261 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
262 if (tmp_error.Fail())
263 {
264 variable_list.RemoveVariableAtIndex (i);
265 valobj_list.RemoveValueObjectAtIndex (i);
266 }
267 else
268 {
269 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
270 ++i;
271 }
272 }
273 }
274 else
275 {
276 error.SetErrorString ("unknown error");
277 }
278 return error;
279 }
280 break;
281
282 case '&':
283 {
284 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
285 scope,
286 callback,
287 baton,
288 variable_list,
289 valobj_list);
290 if (error.Success())
291 {
292 for (uint32_t i=0; i<valobj_list.GetSize(); )
293 {
294 Error tmp_error;
295 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
296 if (tmp_error.Fail())
297 {
298 variable_list.RemoveVariableAtIndex (i);
299 valobj_list.RemoveValueObjectAtIndex (i);
300 }
301 else
302 {
303 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
304 ++i;
305 }
306 }
307 }
308 else
309 {
310 error.SetErrorString ("unknown error");
311 }
312 return error;
313 }
314 break;
315
316 default:
317 {
318 RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
319 if (regex.Execute(variable_expr_path, 1))
320 {
321 std::string variable_name;
322 if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name))
323 {
324 variable_list.Clear();
325 if (callback (baton, variable_name.c_str(), variable_list))
326 {
327 uint32_t i=0;
328 while (i < variable_list.GetSize())
329 {
330 VariableSP var_sp (variable_list.GetVariableAtIndex (i));
331 ValueObjectSP valobj_sp;
332 if (var_sp)
333 {
334 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
335 if (variable_valobj_sp)
336 {
337 variable_expr_path += variable_name.size();
338 if (*variable_expr_path)
339 {
340 const char* first_unparsed = NULL;
341 ValueObject::ExpressionPathScanEndReason reason_to_stop;
342 ValueObject::ExpressionPathEndResultType final_value_type;
343 ValueObject::GetValueForExpressionPathOptions options;
344 ValueObject::ExpressionPathAftermath final_task_on_target;
345
346 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path,
347 &first_unparsed,
348 &reason_to_stop,
349 &final_value_type,
350 options,
351 &final_task_on_target);
352 if (!valobj_sp)
353 {
354 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
355 variable_expr_path,
356 var_sp->GetName().GetCString());
357 }
358 }
359 else
360 {
361 // Just the name of a variable with no extras
362 valobj_sp = variable_valobj_sp;
363 }
364 }
365 }
366
367 if (!var_sp || !valobj_sp)
368 {
369 variable_list.RemoveVariableAtIndex (i);
370 }
371 else
372 {
373 valobj_list.Append(valobj_sp);
374 ++i;
375 }
376 }
377
378 if (variable_list.GetSize() > 0)
379 {
380 error.Clear();
381 return error;
382 }
383 }
384 }
385 }
386 error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path);
387 }
388 break;
389 }
390 }
391 error.SetErrorString ("unknown error");
392 return error;
393}
394