blob: afe6476a6dc0b3a5010505390be974b25c5476b7 [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
Greg Clayton9b82f862011-07-11 05:12:02 +0000219Variable::LocationIsValidForAddress (const Address &address)
220{
221 // Be sure to resolve the address to section offset prior to
222 // calling this function.
223 if (address.IsSectionOffset())
224 {
225 SymbolContext sc;
226 CalculateSymbolContext(&sc);
227 if (sc.module_sp.get() == address.GetModule())
228 {
229 // Is the variable is described by a single location?
230 if (!m_location.IsLocationList())
231 {
232 // Yes it is, the location is valid.
233 return true;
234 }
235
236 if (sc.function)
237 {
238 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
239 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
240 return false;
241 // It is a location list. We just need to tell if the location
242 // list contains the current address when converted to a load
243 // address
244 return m_location.LocationListContainsAddress (loclist_base_file_addr,
245 address.GetFileAddress());
246 }
247 }
248 }
249 return false;
250}
251
252bool
Chris Lattner24943d22010-06-08 16:52:24 +0000253Variable::IsInScope (StackFrame *frame)
254{
255 switch (m_scope)
256 {
Greg Clayton82f07462011-05-30 00:49:24 +0000257 case eValueTypeRegister:
258 case eValueTypeRegisterSet:
259 return frame != NULL;
260
261 case eValueTypeConstResult:
Greg Clayton82f07462011-05-30 00:49:24 +0000262 case eValueTypeVariableGlobal:
263 case eValueTypeVariableStatic:
Greg Clayton24b03102011-07-09 20:12:33 +0000264 return true;
265
Chris Lattner24943d22010-06-08 16:52:24 +0000266 case eValueTypeVariableArgument:
267 case eValueTypeVariableLocal:
Greg Clayton82f07462011-05-30 00:49:24 +0000268 if (frame)
Chris Lattner24943d22010-06-08 16:52:24 +0000269 {
270 // We don't have a location list, we just need to see if the block
271 // that this variable was defined in is currently
Greg Claytona357ecf2010-09-14 03:16:58 +0000272 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
273 if (deepest_frame_block)
Chris Lattner24943d22010-06-08 16:52:24 +0000274 {
275 SymbolContext variable_sc;
276 CalculateSymbolContext (&variable_sc);
Greg Clayton82f07462011-05-30 00:49:24 +0000277 // Check for static or global variable defined at the compile unit
278 // level that wasn't defined in a block
279 if (variable_sc.block == NULL)
280 return true;
281
Greg Claytona357ecf2010-09-14 03:16:58 +0000282 if (variable_sc.block == deepest_frame_block)
Greg Clayton178710c2010-09-14 02:20:48 +0000283 return true;
Greg Claytona357ecf2010-09-14 03:16:58 +0000284 return variable_sc.block->Contains (deepest_frame_block);
Chris Lattner24943d22010-06-08 16:52:24 +0000285 }
286 }
287 break;
288
289 default:
Chris Lattner24943d22010-06-08 16:52:24 +0000290 break;
291 }
292 return false;
293}
294
Greg Clayton5d81f492011-07-08 21:46:14 +0000295Error
296Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
297 ExecutionContextScope *scope,
298 GetVariableCallback callback,
299 void *baton,
300 VariableList &variable_list,
301 ValueObjectList &valobj_list)
302{
303 Error error;
304 if (variable_expr_path && callback)
305 {
306 switch (variable_expr_path[0])
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)->Dereference(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 case '&':
343 {
344 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
345 scope,
346 callback,
347 baton,
348 variable_list,
349 valobj_list);
350 if (error.Success())
351 {
352 for (uint32_t i=0; i<valobj_list.GetSize(); )
353 {
354 Error tmp_error;
355 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
356 if (tmp_error.Fail())
357 {
358 variable_list.RemoveVariableAtIndex (i);
359 valobj_list.RemoveValueObjectAtIndex (i);
360 }
361 else
362 {
363 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
364 ++i;
365 }
366 }
367 }
368 else
369 {
370 error.SetErrorString ("unknown error");
371 }
372 return error;
373 }
374 break;
375
376 default:
377 {
378 RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
379 if (regex.Execute(variable_expr_path, 1))
380 {
381 std::string variable_name;
382 if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name))
383 {
384 variable_list.Clear();
385 if (callback (baton, variable_name.c_str(), variable_list))
386 {
387 uint32_t i=0;
388 while (i < variable_list.GetSize())
389 {
390 VariableSP var_sp (variable_list.GetVariableAtIndex (i));
391 ValueObjectSP valobj_sp;
392 if (var_sp)
393 {
394 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
395 if (variable_valobj_sp)
396 {
397 variable_expr_path += variable_name.size();
398 if (*variable_expr_path)
399 {
400 const char* first_unparsed = NULL;
401 ValueObject::ExpressionPathScanEndReason reason_to_stop;
402 ValueObject::ExpressionPathEndResultType final_value_type;
403 ValueObject::GetValueForExpressionPathOptions options;
404 ValueObject::ExpressionPathAftermath final_task_on_target;
405
406 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path,
407 &first_unparsed,
408 &reason_to_stop,
409 &final_value_type,
410 options,
411 &final_task_on_target);
412 if (!valobj_sp)
413 {
414 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
415 variable_expr_path,
416 var_sp->GetName().GetCString());
417 }
418 }
419 else
420 {
421 // Just the name of a variable with no extras
422 valobj_sp = variable_valobj_sp;
423 }
424 }
425 }
426
427 if (!var_sp || !valobj_sp)
428 {
429 variable_list.RemoveVariableAtIndex (i);
430 }
431 else
432 {
433 valobj_list.Append(valobj_sp);
434 ++i;
435 }
436 }
437
438 if (variable_list.GetSize() > 0)
439 {
440 error.Clear();
441 return error;
442 }
443 }
444 }
445 }
446 error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path);
447 }
448 break;
449 }
450 }
451 error.SetErrorString ("unknown error");
452 return error;
453}
454
Greg Clayton9b82f862011-07-11 05:12:02 +0000455bool
456Variable::DumpLocationForAddress (Stream *s, const Address &address)
457{
458 // Be sure to resolve the address to section offset prior to
459 // calling this function.
460 if (address.IsSectionOffset())
461 {
462 SymbolContext sc;
463 CalculateSymbolContext(&sc);
464 if (sc.module_sp.get() == address.GetModule())
465 {
466 const addr_t file_addr = address.GetFileAddress();
467 if (sc.function)
468 {
469 if (sc.function->GetAddressRange().ContainsFileAddress(address))
470 {
471 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
472 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
473 return false;
474 return m_location.DumpLocationForAddress (s,
475 eDescriptionLevelBrief,
476 loclist_base_file_addr,
477 file_addr);
478 }
479 }
480 return m_location.DumpLocationForAddress (s,
481 eDescriptionLevelBrief,
482 LLDB_INVALID_ADDRESS,
483 file_addr);
484
485 }
486 }
487 return false;
488
489}
490