blob: df008737e6d7a520d839ba536f3912e8d49470c5 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Clayton83c5cd92010-11-14 22:13:40 +000013#include "lldb/Core/RegularExpression.h"
Greg Clayton884fb692011-07-08 21:46:14 +000014#include "lldb/Core/ValueObject.h"
15#include "lldb/Core/ValueObjectVariable.h"
Chris Lattner30fdc8d2010-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 Clayton884fb692011-07-08 21:46:14 +000020#include "lldb/Symbol/VariableList.h"
Greg Claytonafacd142011-09-02 01:15:17 +000021#include "lldb/Target/ABI.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000022#include "lldb/Target/Process.h"
Greg Clayton9da7bd02010-08-24 21:05:24 +000023#include "lldb/Target/RegisterContext.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024#include "lldb/Target/StackFrame.h"
25#include "lldb/Target/Thread.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000026#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027
28using namespace lldb;
29using namespace lldb_private;
30
31//----------------------------------------------------------------------
32// Variable constructor
33//----------------------------------------------------------------------
Greg Clayton83c5cd92010-11-14 22:13:40 +000034Variable::Variable
35(
36 lldb::user_id_t uid,
37 const char *name,
38 const char *mangled, // The mangled variable name for variables in namespaces
Greg Claytond1767f02011-12-08 02:13:16 +000039 const lldb::SymbolFileTypeSP &symfile_type_sp,
Greg Clayton83c5cd92010-11-14 22:13:40 +000040 ValueType scope,
41 SymbolContextScope *context,
42 Declaration* decl_ptr,
43 const DWARFExpression& location,
44 bool external,
45 bool artificial
46) :
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047 UserID(uid),
48 m_name(name),
Greg Clayton037520e2012-07-18 23:18:10 +000049 m_mangled (ConstString(mangled), true),
Greg Claytond1767f02011-12-08 02:13:16 +000050 m_symfile_type_sp(symfile_type_sp),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051 m_scope(scope),
Greg Clayton59e8fc1c2010-08-30 18:11:35 +000052 m_owner_scope(context),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053 m_declaration(decl_ptr),
54 m_location(location),
55 m_external(external),
56 m_artificial(artificial)
57{
58}
59
60//----------------------------------------------------------------------
61// Destructor
62//----------------------------------------------------------------------
63Variable::~Variable()
64{
65}
66
67
Greg Clayton83c5cd92010-11-14 22:13:40 +000068const ConstString&
69Variable::GetName() const
70{
71 if (m_mangled)
72 return m_mangled.GetName();
73 return m_name;
74}
75
76bool
77Variable::NameMatches (const RegularExpression& regex) const
78{
79 if (regex.Execute (m_name.AsCString()))
80 return true;
81 return m_mangled.NameMatches (regex);
82}
83
Greg Claytond1767f02011-12-08 02:13:16 +000084Type *
85Variable::GetType()
86{
87 if (m_symfile_type_sp)
88 return m_symfile_type_sp->GetType();
89 return NULL;
90}
91
Chris Lattner30fdc8d2010-06-08 16:52:24 +000092void
93Variable::Dump(Stream *s, bool show_context) const
94{
Jason Molendafd54b362011-09-20 21:44:10 +000095 s->Printf("%p: ", this);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096 s->Indent();
97 *s << "Variable" << (const UserID&)*this;
98
99 if (m_name)
100 *s << ", name = \"" << m_name << "\"";
101
Greg Claytond1767f02011-12-08 02:13:16 +0000102 if (m_symfile_type_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000103 {
Greg Claytond1767f02011-12-08 02:13:16 +0000104 Type *type = m_symfile_type_sp->GetType();
105 if (type)
106 {
107 *s << ", type = {" << type->GetID() << "} " << (void*)type << " (";
108 type->DumpTypeName(s);
109 s->PutChar(')');
110 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111 }
112
113 if (m_scope != eValueTypeInvalid)
114 {
115 s->PutCString(", scope = ");
116 switch (m_scope)
117 {
118 case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break;
119 case eValueTypeVariableArgument: s->PutCString("parameter"); break;
120 case eValueTypeVariableLocal: s->PutCString("local"); break;
121 default: *s << "??? (" << m_scope << ')';
122 }
123 }
124
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000125 if (show_context && m_owner_scope != NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000126 {
127 s->PutCString(", context = ( ");
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000128 m_owner_scope->DumpSymbolContext(s);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129 s->PutCString(" )");
130 }
131
Greg Clayton6dbd3982010-09-15 05:51:24 +0000132 bool show_fullpaths = false;
133 m_declaration.Dump(s, show_fullpaths);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000134
135 if (m_location.IsValid())
136 {
137 s->PutCString(", location = ");
Greg Clayton016a95e2010-09-14 02:20:48 +0000138 lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
139 if (m_location.IsLocationList())
140 {
141 SymbolContext variable_sc;
142 m_owner_scope->CalculateSymbolContext(&variable_sc);
143 if (variable_sc.function)
144 loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
145 }
Greg Claytonafacd142011-09-02 01:15:17 +0000146 ABI *abi = NULL;
147 if (m_owner_scope)
148 {
Greg Claytone72dfb32012-02-24 01:59:29 +0000149 ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule());
150 if (module_sp)
151 abi = ABI::FindPlugin (module_sp->GetArchitecture()).get();
Greg Claytonafacd142011-09-02 01:15:17 +0000152 }
153 m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr, abi);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154 }
155
156 if (m_external)
157 s->PutCString(", external");
158
159 if (m_artificial)
160 s->PutCString(", artificial");
161
162 s->EOL();
163}
164
Greg Clayton45ba8542011-07-10 19:21:23 +0000165bool
166Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module)
167{
168 bool dumped_declaration_info = false;
169 if (m_owner_scope)
170 {
171 SymbolContext sc;
172 m_owner_scope->CalculateSymbolContext(&sc);
173 sc.block = NULL;
174 sc.line_entry.Clear();
175 bool show_inlined_frames = false;
176
177 dumped_declaration_info = sc.DumpStopContext (s,
178 NULL,
179 Address(),
180 show_fullpaths,
181 show_module,
182 show_inlined_frames);
183
184 if (sc.function)
185 s->PutChar(':');
186 }
187 if (m_declaration.DumpStopContext (s, false))
188 dumped_declaration_info = true;
189 return dumped_declaration_info;
190}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191
192size_t
193Variable::MemorySize() const
194{
195 return sizeof(Variable);
196}
197
198
199void
200Variable::CalculateSymbolContext (SymbolContext *sc)
201{
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000202 if (m_owner_scope)
203 m_owner_scope->CalculateSymbolContext(sc);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000204 else
205 sc->Clear();
206}
207
Greg Clayton007d5be2011-05-30 00:49:24 +0000208bool
209Variable::LocationIsValidForFrame (StackFrame *frame)
210{
211 // Is the variable is described by a single location?
212 if (!m_location.IsLocationList())
213 {
214 // Yes it is, the location is valid.
215 return true;
216 }
217
218 if (frame)
219 {
Greg Clayton007d5be2011-05-30 00:49:24 +0000220 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
221 if (function)
222 {
Greg Claytond9e416c2012-02-18 05:35:26 +0000223 TargetSP target_sp (frame->CalculateTarget());
224
225 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target_sp.get());
Greg Clayton007d5be2011-05-30 00:49:24 +0000226 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
227 return false;
228 // It is a location list. We just need to tell if the location
229 // list contains the current address when converted to a load
230 // address
231 return m_location.LocationListContainsAddress (loclist_base_load_addr,
Greg Claytond9e416c2012-02-18 05:35:26 +0000232 frame->GetFrameCodeAddress().GetLoadAddress (target_sp.get()));
Greg Clayton007d5be2011-05-30 00:49:24 +0000233 }
234 }
235 return false;
236}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237
238bool
Greg Claytonc749eb82011-07-11 05:12:02 +0000239Variable::LocationIsValidForAddress (const Address &address)
240{
241 // Be sure to resolve the address to section offset prior to
242 // calling this function.
243 if (address.IsSectionOffset())
244 {
245 SymbolContext sc;
246 CalculateSymbolContext(&sc);
Greg Claytone72dfb32012-02-24 01:59:29 +0000247 if (sc.module_sp == address.GetModule())
Greg Claytonc749eb82011-07-11 05:12:02 +0000248 {
249 // Is the variable is described by a single location?
250 if (!m_location.IsLocationList())
251 {
252 // Yes it is, the location is valid.
253 return true;
254 }
255
256 if (sc.function)
257 {
258 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
259 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
260 return false;
261 // It is a location list. We just need to tell if the location
262 // list contains the current address when converted to a load
263 // address
264 return m_location.LocationListContainsAddress (loclist_base_file_addr,
265 address.GetFileAddress());
266 }
267 }
268 }
269 return false;
270}
271
272bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000273Variable::IsInScope (StackFrame *frame)
274{
275 switch (m_scope)
276 {
Greg Clayton007d5be2011-05-30 00:49:24 +0000277 case eValueTypeRegister:
278 case eValueTypeRegisterSet:
279 return frame != NULL;
280
281 case eValueTypeConstResult:
Greg Clayton007d5be2011-05-30 00:49:24 +0000282 case eValueTypeVariableGlobal:
283 case eValueTypeVariableStatic:
Greg Claytondaf515f2011-07-09 20:12:33 +0000284 return true;
285
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000286 case eValueTypeVariableArgument:
287 case eValueTypeVariableLocal:
Greg Clayton007d5be2011-05-30 00:49:24 +0000288 if (frame)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000289 {
290 // We don't have a location list, we just need to see if the block
291 // that this variable was defined in is currently
Greg Clayton6f00abd2010-09-14 03:16:58 +0000292 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
293 if (deepest_frame_block)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000294 {
295 SymbolContext variable_sc;
296 CalculateSymbolContext (&variable_sc);
Greg Clayton007d5be2011-05-30 00:49:24 +0000297 // Check for static or global variable defined at the compile unit
298 // level that wasn't defined in a block
299 if (variable_sc.block == NULL)
300 return true;
301
Greg Clayton6f00abd2010-09-14 03:16:58 +0000302 if (variable_sc.block == deepest_frame_block)
Greg Clayton016a95e2010-09-14 02:20:48 +0000303 return true;
Greg Clayton6f00abd2010-09-14 03:16:58 +0000304 return variable_sc.block->Contains (deepest_frame_block);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305 }
306 }
307 break;
308
309 default:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000310 break;
311 }
312 return false;
313}
314
Greg Clayton884fb692011-07-08 21:46:14 +0000315Error
316Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
317 ExecutionContextScope *scope,
318 GetVariableCallback callback,
319 void *baton,
320 VariableList &variable_list,
321 ValueObjectList &valobj_list)
322{
323 Error error;
324 if (variable_expr_path && callback)
325 {
326 switch (variable_expr_path[0])
327 {
328 case '*':
329 {
330 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
331 scope,
332 callback,
333 baton,
334 variable_list,
335 valobj_list);
336 if (error.Success())
337 {
338 for (uint32_t i=0; i<valobj_list.GetSize(); )
339 {
340 Error tmp_error;
341 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
342 if (tmp_error.Fail())
343 {
344 variable_list.RemoveVariableAtIndex (i);
345 valobj_list.RemoveValueObjectAtIndex (i);
346 }
347 else
348 {
349 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
350 ++i;
351 }
352 }
353 }
354 else
355 {
356 error.SetErrorString ("unknown error");
357 }
358 return error;
359 }
360 break;
361
362 case '&':
363 {
364 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
365 scope,
366 callback,
367 baton,
368 variable_list,
369 valobj_list);
370 if (error.Success())
371 {
372 for (uint32_t i=0; i<valobj_list.GetSize(); )
373 {
374 Error tmp_error;
375 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
376 if (tmp_error.Fail())
377 {
378 variable_list.RemoveVariableAtIndex (i);
379 valobj_list.RemoveValueObjectAtIndex (i);
380 }
381 else
382 {
383 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
384 ++i;
385 }
386 }
387 }
388 else
389 {
390 error.SetErrorString ("unknown error");
391 }
392 return error;
393 }
394 break;
395
396 default:
397 {
398 RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
399 if (regex.Execute(variable_expr_path, 1))
400 {
401 std::string variable_name;
402 if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name))
403 {
404 variable_list.Clear();
405 if (callback (baton, variable_name.c_str(), variable_list))
406 {
407 uint32_t i=0;
408 while (i < variable_list.GetSize())
409 {
410 VariableSP var_sp (variable_list.GetVariableAtIndex (i));
411 ValueObjectSP valobj_sp;
412 if (var_sp)
413 {
414 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
415 if (variable_valobj_sp)
416 {
417 variable_expr_path += variable_name.size();
418 if (*variable_expr_path)
419 {
420 const char* first_unparsed = NULL;
421 ValueObject::ExpressionPathScanEndReason reason_to_stop;
422 ValueObject::ExpressionPathEndResultType final_value_type;
423 ValueObject::GetValueForExpressionPathOptions options;
424 ValueObject::ExpressionPathAftermath final_task_on_target;
425
426 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path,
427 &first_unparsed,
428 &reason_to_stop,
429 &final_value_type,
430 options,
431 &final_task_on_target);
432 if (!valobj_sp)
433 {
434 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
435 variable_expr_path,
436 var_sp->GetName().GetCString());
437 }
438 }
439 else
440 {
441 // Just the name of a variable with no extras
442 valobj_sp = variable_valobj_sp;
443 }
444 }
445 }
446
447 if (!var_sp || !valobj_sp)
448 {
449 variable_list.RemoveVariableAtIndex (i);
450 }
451 else
452 {
453 valobj_list.Append(valobj_sp);
454 ++i;
455 }
456 }
457
458 if (variable_list.GetSize() > 0)
459 {
460 error.Clear();
461 return error;
462 }
463 }
464 }
465 }
466 error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path);
467 }
468 break;
469 }
470 }
471 error.SetErrorString ("unknown error");
472 return error;
473}
474
Greg Claytonc749eb82011-07-11 05:12:02 +0000475bool
476Variable::DumpLocationForAddress (Stream *s, const Address &address)
477{
478 // Be sure to resolve the address to section offset prior to
479 // calling this function.
480 if (address.IsSectionOffset())
481 {
482 SymbolContext sc;
483 CalculateSymbolContext(&sc);
Greg Claytone72dfb32012-02-24 01:59:29 +0000484 if (sc.module_sp == address.GetModule())
Greg Claytonc749eb82011-07-11 05:12:02 +0000485 {
Greg Claytonafacd142011-09-02 01:15:17 +0000486 ABI *abi = NULL;
487 if (m_owner_scope)
488 {
Greg Claytone72dfb32012-02-24 01:59:29 +0000489 ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule());
490 if (module_sp)
491 abi = ABI::FindPlugin (module_sp->GetArchitecture()).get();
Greg Claytonafacd142011-09-02 01:15:17 +0000492 }
493
Greg Claytonc749eb82011-07-11 05:12:02 +0000494 const addr_t file_addr = address.GetFileAddress();
495 if (sc.function)
496 {
497 if (sc.function->GetAddressRange().ContainsFileAddress(address))
498 {
499 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
500 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
501 return false;
502 return m_location.DumpLocationForAddress (s,
503 eDescriptionLevelBrief,
504 loclist_base_file_addr,
Greg Claytonafacd142011-09-02 01:15:17 +0000505 file_addr,
506 abi);
Greg Claytonc749eb82011-07-11 05:12:02 +0000507 }
508 }
509 return m_location.DumpLocationForAddress (s,
510 eDescriptionLevelBrief,
511 LLDB_INVALID_ADDRESS,
Greg Claytonafacd142011-09-02 01:15:17 +0000512 file_addr,
513 abi);
Greg Claytonc749eb82011-07-11 05:12:02 +0000514 }
515 }
516 return false;
517
518}
519