blob: 161d4826bad274b04936e848832a8381408ffe44 [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 Clayton83c5cd92010-11-14 22:13:40 +000049 m_mangled (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 {
149 Module *module = m_owner_scope->CalculateSymbolContextModule();
150 abi = ABI::FindPlugin (module->GetArchitecture()).get();
151 }
152 m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr, abi);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153 }
154
155 if (m_external)
156 s->PutCString(", external");
157
158 if (m_artificial)
159 s->PutCString(", artificial");
160
161 s->EOL();
162}
163
Greg Clayton45ba8542011-07-10 19:21:23 +0000164bool
165Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module)
166{
167 bool dumped_declaration_info = false;
168 if (m_owner_scope)
169 {
170 SymbolContext sc;
171 m_owner_scope->CalculateSymbolContext(&sc);
172 sc.block = NULL;
173 sc.line_entry.Clear();
174 bool show_inlined_frames = false;
175
176 dumped_declaration_info = sc.DumpStopContext (s,
177 NULL,
178 Address(),
179 show_fullpaths,
180 show_module,
181 show_inlined_frames);
182
183 if (sc.function)
184 s->PutChar(':');
185 }
186 if (m_declaration.DumpStopContext (s, false))
187 dumped_declaration_info = true;
188 return dumped_declaration_info;
189}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000190
191size_t
192Variable::MemorySize() const
193{
194 return sizeof(Variable);
195}
196
197
198void
199Variable::CalculateSymbolContext (SymbolContext *sc)
200{
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000201 if (m_owner_scope)
202 m_owner_scope->CalculateSymbolContext(sc);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203 else
204 sc->Clear();
205}
206
Greg Clayton007d5be2011-05-30 00:49:24 +0000207bool
208Variable::LocationIsValidForFrame (StackFrame *frame)
209{
210 // Is the variable is described by a single location?
211 if (!m_location.IsLocationList())
212 {
213 // Yes it is, the location is valid.
214 return true;
215 }
216
217 if (frame)
218 {
Greg Clayton007d5be2011-05-30 00:49:24 +0000219 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
220 if (function)
221 {
Greg Claytond9e416c2012-02-18 05:35:26 +0000222 TargetSP target_sp (frame->CalculateTarget());
223
224 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target_sp.get());
Greg Clayton007d5be2011-05-30 00:49:24 +0000225 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
226 return false;
227 // It is a location list. We just need to tell if the location
228 // list contains the current address when converted to a load
229 // address
230 return m_location.LocationListContainsAddress (loclist_base_load_addr,
Greg Claytond9e416c2012-02-18 05:35:26 +0000231 frame->GetFrameCodeAddress().GetLoadAddress (target_sp.get()));
Greg Clayton007d5be2011-05-30 00:49:24 +0000232 }
233 }
234 return false;
235}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236
237bool
Greg Claytonc749eb82011-07-11 05:12:02 +0000238Variable::LocationIsValidForAddress (const Address &address)
239{
240 // Be sure to resolve the address to section offset prior to
241 // calling this function.
242 if (address.IsSectionOffset())
243 {
244 SymbolContext sc;
245 CalculateSymbolContext(&sc);
Greg Claytone1cd1be2012-01-29 20:56:30 +0000246 if (sc.module_sp.get() == address.GetModulePtr())
Greg Claytonc749eb82011-07-11 05:12:02 +0000247 {
248 // Is the variable is described by a single location?
249 if (!m_location.IsLocationList())
250 {
251 // Yes it is, the location is valid.
252 return true;
253 }
254
255 if (sc.function)
256 {
257 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
258 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
259 return false;
260 // It is a location list. We just need to tell if the location
261 // list contains the current address when converted to a load
262 // address
263 return m_location.LocationListContainsAddress (loclist_base_file_addr,
264 address.GetFileAddress());
265 }
266 }
267 }
268 return false;
269}
270
271bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000272Variable::IsInScope (StackFrame *frame)
273{
274 switch (m_scope)
275 {
Greg Clayton007d5be2011-05-30 00:49:24 +0000276 case eValueTypeRegister:
277 case eValueTypeRegisterSet:
278 return frame != NULL;
279
280 case eValueTypeConstResult:
Greg Clayton007d5be2011-05-30 00:49:24 +0000281 case eValueTypeVariableGlobal:
282 case eValueTypeVariableStatic:
Greg Claytondaf515f2011-07-09 20:12:33 +0000283 return true;
284
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000285 case eValueTypeVariableArgument:
286 case eValueTypeVariableLocal:
Greg Clayton007d5be2011-05-30 00:49:24 +0000287 if (frame)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288 {
289 // We don't have a location list, we just need to see if the block
290 // that this variable was defined in is currently
Greg Clayton6f00abd2010-09-14 03:16:58 +0000291 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
292 if (deepest_frame_block)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293 {
294 SymbolContext variable_sc;
295 CalculateSymbolContext (&variable_sc);
Greg Clayton007d5be2011-05-30 00:49:24 +0000296 // Check for static or global variable defined at the compile unit
297 // level that wasn't defined in a block
298 if (variable_sc.block == NULL)
299 return true;
300
Greg Clayton6f00abd2010-09-14 03:16:58 +0000301 if (variable_sc.block == deepest_frame_block)
Greg Clayton016a95e2010-09-14 02:20:48 +0000302 return true;
Greg Clayton6f00abd2010-09-14 03:16:58 +0000303 return variable_sc.block->Contains (deepest_frame_block);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000304 }
305 }
306 break;
307
308 default:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000309 break;
310 }
311 return false;
312}
313
Greg Clayton884fb692011-07-08 21:46:14 +0000314Error
315Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
316 ExecutionContextScope *scope,
317 GetVariableCallback callback,
318 void *baton,
319 VariableList &variable_list,
320 ValueObjectList &valobj_list)
321{
322 Error error;
323 if (variable_expr_path && callback)
324 {
325 switch (variable_expr_path[0])
326 {
327 case '*':
328 {
329 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
330 scope,
331 callback,
332 baton,
333 variable_list,
334 valobj_list);
335 if (error.Success())
336 {
337 for (uint32_t i=0; i<valobj_list.GetSize(); )
338 {
339 Error tmp_error;
340 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
341 if (tmp_error.Fail())
342 {
343 variable_list.RemoveVariableAtIndex (i);
344 valobj_list.RemoveValueObjectAtIndex (i);
345 }
346 else
347 {
348 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
349 ++i;
350 }
351 }
352 }
353 else
354 {
355 error.SetErrorString ("unknown error");
356 }
357 return error;
358 }
359 break;
360
361 case '&':
362 {
363 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
364 scope,
365 callback,
366 baton,
367 variable_list,
368 valobj_list);
369 if (error.Success())
370 {
371 for (uint32_t i=0; i<valobj_list.GetSize(); )
372 {
373 Error tmp_error;
374 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
375 if (tmp_error.Fail())
376 {
377 variable_list.RemoveVariableAtIndex (i);
378 valobj_list.RemoveValueObjectAtIndex (i);
379 }
380 else
381 {
382 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
383 ++i;
384 }
385 }
386 }
387 else
388 {
389 error.SetErrorString ("unknown error");
390 }
391 return error;
392 }
393 break;
394
395 default:
396 {
397 RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
398 if (regex.Execute(variable_expr_path, 1))
399 {
400 std::string variable_name;
401 if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name))
402 {
403 variable_list.Clear();
404 if (callback (baton, variable_name.c_str(), variable_list))
405 {
406 uint32_t i=0;
407 while (i < variable_list.GetSize())
408 {
409 VariableSP var_sp (variable_list.GetVariableAtIndex (i));
410 ValueObjectSP valobj_sp;
411 if (var_sp)
412 {
413 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
414 if (variable_valobj_sp)
415 {
416 variable_expr_path += variable_name.size();
417 if (*variable_expr_path)
418 {
419 const char* first_unparsed = NULL;
420 ValueObject::ExpressionPathScanEndReason reason_to_stop;
421 ValueObject::ExpressionPathEndResultType final_value_type;
422 ValueObject::GetValueForExpressionPathOptions options;
423 ValueObject::ExpressionPathAftermath final_task_on_target;
424
425 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path,
426 &first_unparsed,
427 &reason_to_stop,
428 &final_value_type,
429 options,
430 &final_task_on_target);
431 if (!valobj_sp)
432 {
433 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
434 variable_expr_path,
435 var_sp->GetName().GetCString());
436 }
437 }
438 else
439 {
440 // Just the name of a variable with no extras
441 valobj_sp = variable_valobj_sp;
442 }
443 }
444 }
445
446 if (!var_sp || !valobj_sp)
447 {
448 variable_list.RemoveVariableAtIndex (i);
449 }
450 else
451 {
452 valobj_list.Append(valobj_sp);
453 ++i;
454 }
455 }
456
457 if (variable_list.GetSize() > 0)
458 {
459 error.Clear();
460 return error;
461 }
462 }
463 }
464 }
465 error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path);
466 }
467 break;
468 }
469 }
470 error.SetErrorString ("unknown error");
471 return error;
472}
473
Greg Claytonc749eb82011-07-11 05:12:02 +0000474bool
475Variable::DumpLocationForAddress (Stream *s, const Address &address)
476{
477 // Be sure to resolve the address to section offset prior to
478 // calling this function.
479 if (address.IsSectionOffset())
480 {
481 SymbolContext sc;
482 CalculateSymbolContext(&sc);
Greg Claytone1cd1be2012-01-29 20:56:30 +0000483 if (sc.module_sp.get() == address.GetModulePtr())
Greg Claytonc749eb82011-07-11 05:12:02 +0000484 {
Greg Claytonafacd142011-09-02 01:15:17 +0000485 ABI *abi = NULL;
486 if (m_owner_scope)
487 {
488 Module *module = m_owner_scope->CalculateSymbolContextModule();
489 abi = ABI::FindPlugin (module->GetArchitecture()).get();
490 }
491
Greg Claytonc749eb82011-07-11 05:12:02 +0000492 const addr_t file_addr = address.GetFileAddress();
493 if (sc.function)
494 {
495 if (sc.function->GetAddressRange().ContainsFileAddress(address))
496 {
497 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
498 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
499 return false;
500 return m_location.DumpLocationForAddress (s,
501 eDescriptionLevelBrief,
502 loclist_base_file_addr,
Greg Claytonafacd142011-09-02 01:15:17 +0000503 file_addr,
504 abi);
Greg Claytonc749eb82011-07-11 05:12:02 +0000505 }
506 }
507 return m_location.DumpLocationForAddress (s,
508 eDescriptionLevelBrief,
509 LLDB_INVALID_ADDRESS,
Greg Claytonafacd142011-09-02 01:15:17 +0000510 file_addr,
511 abi);
Greg Claytonc749eb82011-07-11 05:12:02 +0000512 }
513 }
514 return false;
515
516}
517