blob: e7524850aecd863f5c930b9aa1fb001ad5a556fc [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
39 Type *type,
40 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),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050 m_type(type),
51 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
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084void
85Variable::Dump(Stream *s, bool show_context) const
86{
87 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
88 s->Indent();
89 *s << "Variable" << (const UserID&)*this;
90
91 if (m_name)
92 *s << ", name = \"" << m_name << "\"";
93
94 if (m_type != NULL)
95 {
Greg Clayton24739922010-10-13 03:15:28 +000096 *s << ", type = {" << m_type->GetID() << "} " << (void*)m_type << " (";
Chris Lattner30fdc8d2010-06-08 16:52:24 +000097 m_type->DumpTypeName(s);
98 s->PutChar(')');
99 }
100
101 if (m_scope != eValueTypeInvalid)
102 {
103 s->PutCString(", scope = ");
104 switch (m_scope)
105 {
106 case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break;
107 case eValueTypeVariableArgument: s->PutCString("parameter"); break;
108 case eValueTypeVariableLocal: s->PutCString("local"); break;
109 default: *s << "??? (" << m_scope << ')';
110 }
111 }
112
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000113 if (show_context && m_owner_scope != NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114 {
115 s->PutCString(", context = ( ");
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000116 m_owner_scope->DumpSymbolContext(s);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 s->PutCString(" )");
118 }
119
Greg Clayton6dbd3982010-09-15 05:51:24 +0000120 bool show_fullpaths = false;
121 m_declaration.Dump(s, show_fullpaths);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000122
123 if (m_location.IsValid())
124 {
125 s->PutCString(", location = ");
Greg Clayton016a95e2010-09-14 02:20:48 +0000126 lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
127 if (m_location.IsLocationList())
128 {
129 SymbolContext variable_sc;
130 m_owner_scope->CalculateSymbolContext(&variable_sc);
131 if (variable_sc.function)
132 loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
133 }
Greg Claytonafacd142011-09-02 01:15:17 +0000134 ABI *abi = NULL;
135 if (m_owner_scope)
136 {
137 Module *module = m_owner_scope->CalculateSymbolContextModule();
138 abi = ABI::FindPlugin (module->GetArchitecture()).get();
139 }
140 m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr, abi);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141 }
142
143 if (m_external)
144 s->PutCString(", external");
145
146 if (m_artificial)
147 s->PutCString(", artificial");
148
149 s->EOL();
150}
151
Greg Clayton45ba8542011-07-10 19:21:23 +0000152bool
153Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module)
154{
155 bool dumped_declaration_info = false;
156 if (m_owner_scope)
157 {
158 SymbolContext sc;
159 m_owner_scope->CalculateSymbolContext(&sc);
160 sc.block = NULL;
161 sc.line_entry.Clear();
162 bool show_inlined_frames = false;
163
164 dumped_declaration_info = sc.DumpStopContext (s,
165 NULL,
166 Address(),
167 show_fullpaths,
168 show_module,
169 show_inlined_frames);
170
171 if (sc.function)
172 s->PutChar(':');
173 }
174 if (m_declaration.DumpStopContext (s, false))
175 dumped_declaration_info = true;
176 return dumped_declaration_info;
177}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178
179size_t
180Variable::MemorySize() const
181{
182 return sizeof(Variable);
183}
184
185
186void
187Variable::CalculateSymbolContext (SymbolContext *sc)
188{
Greg Clayton59e8fc1c2010-08-30 18:11:35 +0000189 if (m_owner_scope)
190 m_owner_scope->CalculateSymbolContext(sc);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 else
192 sc->Clear();
193}
194
Greg Clayton007d5be2011-05-30 00:49:24 +0000195bool
196Variable::LocationIsValidForFrame (StackFrame *frame)
197{
198 // Is the variable is described by a single location?
199 if (!m_location.IsLocationList())
200 {
201 // Yes it is, the location is valid.
202 return true;
203 }
204
205 if (frame)
206 {
207 Target *target = &frame->GetThread().GetProcess().GetTarget();
208
209 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
210 if (function)
211 {
212 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
213 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
214 return false;
215 // It is a location list. We just need to tell if the location
216 // list contains the current address when converted to a load
217 // address
218 return m_location.LocationListContainsAddress (loclist_base_load_addr,
219 frame->GetFrameCodeAddress().GetLoadAddress (target));
220 }
221 }
222 return false;
223}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000224
225bool
Greg Claytonc749eb82011-07-11 05:12:02 +0000226Variable::LocationIsValidForAddress (const Address &address)
227{
228 // Be sure to resolve the address to section offset prior to
229 // calling this function.
230 if (address.IsSectionOffset())
231 {
232 SymbolContext sc;
233 CalculateSymbolContext(&sc);
234 if (sc.module_sp.get() == address.GetModule())
235 {
236 // Is the variable is described by a single location?
237 if (!m_location.IsLocationList())
238 {
239 // Yes it is, the location is valid.
240 return true;
241 }
242
243 if (sc.function)
244 {
245 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
246 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
247 return false;
248 // It is a location list. We just need to tell if the location
249 // list contains the current address when converted to a load
250 // address
251 return m_location.LocationListContainsAddress (loclist_base_file_addr,
252 address.GetFileAddress());
253 }
254 }
255 }
256 return false;
257}
258
259bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000260Variable::IsInScope (StackFrame *frame)
261{
262 switch (m_scope)
263 {
Greg Clayton007d5be2011-05-30 00:49:24 +0000264 case eValueTypeRegister:
265 case eValueTypeRegisterSet:
266 return frame != NULL;
267
268 case eValueTypeConstResult:
Greg Clayton007d5be2011-05-30 00:49:24 +0000269 case eValueTypeVariableGlobal:
270 case eValueTypeVariableStatic:
Greg Claytondaf515f2011-07-09 20:12:33 +0000271 return true;
272
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000273 case eValueTypeVariableArgument:
274 case eValueTypeVariableLocal:
Greg Clayton007d5be2011-05-30 00:49:24 +0000275 if (frame)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276 {
277 // We don't have a location list, we just need to see if the block
278 // that this variable was defined in is currently
Greg Clayton6f00abd2010-09-14 03:16:58 +0000279 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
280 if (deepest_frame_block)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000281 {
282 SymbolContext variable_sc;
283 CalculateSymbolContext (&variable_sc);
Greg Clayton007d5be2011-05-30 00:49:24 +0000284 // Check for static or global variable defined at the compile unit
285 // level that wasn't defined in a block
286 if (variable_sc.block == NULL)
287 return true;
288
Greg Clayton6f00abd2010-09-14 03:16:58 +0000289 if (variable_sc.block == deepest_frame_block)
Greg Clayton016a95e2010-09-14 02:20:48 +0000290 return true;
Greg Clayton6f00abd2010-09-14 03:16:58 +0000291 return variable_sc.block->Contains (deepest_frame_block);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000292 }
293 }
294 break;
295
296 default:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000297 break;
298 }
299 return false;
300}
301
Greg Clayton884fb692011-07-08 21:46:14 +0000302Error
303Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path,
304 ExecutionContextScope *scope,
305 GetVariableCallback callback,
306 void *baton,
307 VariableList &variable_list,
308 ValueObjectList &valobj_list)
309{
310 Error error;
311 if (variable_expr_path && callback)
312 {
313 switch (variable_expr_path[0])
314 {
315 case '*':
316 {
317 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
318 scope,
319 callback,
320 baton,
321 variable_list,
322 valobj_list);
323 if (error.Success())
324 {
325 for (uint32_t i=0; i<valobj_list.GetSize(); )
326 {
327 Error tmp_error;
328 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
329 if (tmp_error.Fail())
330 {
331 variable_list.RemoveVariableAtIndex (i);
332 valobj_list.RemoveValueObjectAtIndex (i);
333 }
334 else
335 {
336 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
337 ++i;
338 }
339 }
340 }
341 else
342 {
343 error.SetErrorString ("unknown error");
344 }
345 return error;
346 }
347 break;
348
349 case '&':
350 {
351 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1,
352 scope,
353 callback,
354 baton,
355 variable_list,
356 valobj_list);
357 if (error.Success())
358 {
359 for (uint32_t i=0; i<valobj_list.GetSize(); )
360 {
361 Error tmp_error;
362 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
363 if (tmp_error.Fail())
364 {
365 variable_list.RemoveVariableAtIndex (i);
366 valobj_list.RemoveValueObjectAtIndex (i);
367 }
368 else
369 {
370 valobj_list.SetValueObjectAtIndex (i, valobj_sp);
371 ++i;
372 }
373 }
374 }
375 else
376 {
377 error.SetErrorString ("unknown error");
378 }
379 return error;
380 }
381 break;
382
383 default:
384 {
385 RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)");
386 if (regex.Execute(variable_expr_path, 1))
387 {
388 std::string variable_name;
389 if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name))
390 {
391 variable_list.Clear();
392 if (callback (baton, variable_name.c_str(), variable_list))
393 {
394 uint32_t i=0;
395 while (i < variable_list.GetSize())
396 {
397 VariableSP var_sp (variable_list.GetVariableAtIndex (i));
398 ValueObjectSP valobj_sp;
399 if (var_sp)
400 {
401 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
402 if (variable_valobj_sp)
403 {
404 variable_expr_path += variable_name.size();
405 if (*variable_expr_path)
406 {
407 const char* first_unparsed = NULL;
408 ValueObject::ExpressionPathScanEndReason reason_to_stop;
409 ValueObject::ExpressionPathEndResultType final_value_type;
410 ValueObject::GetValueForExpressionPathOptions options;
411 ValueObject::ExpressionPathAftermath final_task_on_target;
412
413 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path,
414 &first_unparsed,
415 &reason_to_stop,
416 &final_value_type,
417 options,
418 &final_task_on_target);
419 if (!valobj_sp)
420 {
421 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
422 variable_expr_path,
423 var_sp->GetName().GetCString());
424 }
425 }
426 else
427 {
428 // Just the name of a variable with no extras
429 valobj_sp = variable_valobj_sp;
430 }
431 }
432 }
433
434 if (!var_sp || !valobj_sp)
435 {
436 variable_list.RemoveVariableAtIndex (i);
437 }
438 else
439 {
440 valobj_list.Append(valobj_sp);
441 ++i;
442 }
443 }
444
445 if (variable_list.GetSize() > 0)
446 {
447 error.Clear();
448 return error;
449 }
450 }
451 }
452 }
453 error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path);
454 }
455 break;
456 }
457 }
458 error.SetErrorString ("unknown error");
459 return error;
460}
461
Greg Claytonc749eb82011-07-11 05:12:02 +0000462bool
463Variable::DumpLocationForAddress (Stream *s, const Address &address)
464{
465 // Be sure to resolve the address to section offset prior to
466 // calling this function.
467 if (address.IsSectionOffset())
468 {
469 SymbolContext sc;
470 CalculateSymbolContext(&sc);
471 if (sc.module_sp.get() == address.GetModule())
472 {
Greg Claytonafacd142011-09-02 01:15:17 +0000473 ABI *abi = NULL;
474 if (m_owner_scope)
475 {
476 Module *module = m_owner_scope->CalculateSymbolContextModule();
477 abi = ABI::FindPlugin (module->GetArchitecture()).get();
478 }
479
Greg Claytonc749eb82011-07-11 05:12:02 +0000480 const addr_t file_addr = address.GetFileAddress();
481 if (sc.function)
482 {
483 if (sc.function->GetAddressRange().ContainsFileAddress(address))
484 {
485 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
486 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
487 return false;
488 return m_location.DumpLocationForAddress (s,
489 eDescriptionLevelBrief,
490 loclist_base_file_addr,
Greg Claytonafacd142011-09-02 01:15:17 +0000491 file_addr,
492 abi);
Greg Claytonc749eb82011-07-11 05:12:02 +0000493 }
494 }
495 return m_location.DumpLocationForAddress (s,
496 eDescriptionLevelBrief,
497 LLDB_INVALID_ADDRESS,
Greg Claytonafacd142011-09-02 01:15:17 +0000498 file_addr,
499 abi);
Greg Claytonc749eb82011-07-11 05:12:02 +0000500 }
501 }
502 return false;
503
504}
505