1 //===-- 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"
13 #include "lldb/Core/RegularExpression.h"
14 #include "lldb/Symbol/Block.h"
15 #include "lldb/Symbol/Function.h"
16 #include "lldb/Symbol/SymbolContext.h"
17 #include "lldb/Symbol/Type.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/StackFrame.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Target/Target.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 //----------------------------------------------------------------------
28 // Variable constructor
29 //----------------------------------------------------------------------
30 Variable::Variable
31 (
32     lldb::user_id_t uid,
33     const char *name,
34     const char *mangled,   // The mangled variable name for variables in namespaces
35     Type *type,
36     ValueType scope,
37     SymbolContextScope *context,
38     Declaration* decl_ptr,
39     const DWARFExpression& location,
40     bool external,
41     bool artificial
42 ) :
43     UserID(uid),
44     m_name(name),
45     m_mangled (mangled, true),
46     m_type(type),
47     m_scope(scope),
48     m_owner_scope(context),
49     m_declaration(decl_ptr),
50     m_location(location),
51     m_external(external),
52     m_artificial(artificial)
53 {
54 }
55 
56 //----------------------------------------------------------------------
57 // Destructor
58 //----------------------------------------------------------------------
59 Variable::~Variable()
60 {
61 }
62 
63 
64 const ConstString&
65 Variable::GetName() const
66 {
67     if (m_mangled)
68         return m_mangled.GetName();
69     return m_name;
70 }
71 
72 bool
73 Variable::NameMatches (const RegularExpression& regex) const
74 {
75     if (regex.Execute (m_name.AsCString()))
76         return true;
77     return m_mangled.NameMatches (regex);
78 }
79 
80 void
81 Variable::Dump(Stream *s, bool show_context) const
82 {
83     s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
84     s->Indent();
85     *s << "Variable" << (const UserID&)*this;
86 
87     if (m_name)
88         *s << ", name = \"" << m_name << "\"";
89 
90     if (m_type != NULL)
91     {
92         *s << ", type = {" << m_type->GetID() << "} " << (void*)m_type << " (";
93         m_type->DumpTypeName(s);
94         s->PutChar(')');
95     }
96 
97     if (m_scope != eValueTypeInvalid)
98     {
99         s->PutCString(", scope = ");
100         switch (m_scope)
101         {
102         case eValueTypeVariableGlobal:       s->PutCString(m_external ? "global" : "static"); break;
103         case eValueTypeVariableArgument:    s->PutCString("parameter"); break;
104         case eValueTypeVariableLocal:        s->PutCString("local"); break;
105         default:            *s << "??? (" << m_scope << ')';
106         }
107     }
108 
109     if (show_context && m_owner_scope != NULL)
110     {
111         s->PutCString(", context = ( ");
112         m_owner_scope->DumpSymbolContext(s);
113         s->PutCString(" )");
114     }
115 
116     bool show_fullpaths = false;
117     m_declaration.Dump(s, show_fullpaths);
118 
119     if (m_location.IsValid())
120     {
121         s->PutCString(", location = ");
122         lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
123         if (m_location.IsLocationList())
124         {
125             SymbolContext variable_sc;
126             m_owner_scope->CalculateSymbolContext(&variable_sc);
127             if (variable_sc.function)
128                 loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
129         }
130         m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr);
131     }
132 
133     if (m_external)
134         s->PutCString(", external");
135 
136     if (m_artificial)
137         s->PutCString(", artificial");
138 
139     s->EOL();
140 }
141 
142 
143 size_t
144 Variable::MemorySize() const
145 {
146     return sizeof(Variable);
147 }
148 
149 
150 void
151 Variable::CalculateSymbolContext (SymbolContext *sc)
152 {
153     if (m_owner_scope)
154         m_owner_scope->CalculateSymbolContext(sc);
155     else
156         sc->Clear();
157 }
158 
159 
160 bool
161 Variable::IsInScope (StackFrame *frame)
162 {
163     switch (m_scope)
164     {
165     case eValueTypeVariableGlobal:
166     case eValueTypeVariableStatic:
167         // Globals and statics are always in scope.
168         return true;
169 
170     case eValueTypeVariableArgument:
171     case eValueTypeVariableLocal:
172         // Check if the location has a location list that describes the value
173         // of the variable with address ranges and different locations for each
174         // address range?
175         if (m_location.IsLocationList())
176         {
177             SymbolContext sc;
178             CalculateSymbolContext(&sc);
179 
180             // Currently we only support functions that have things with
181             // locations lists. If this expands, we will need to add support
182             assert (sc.function);
183             Target *target = &frame->GetThread().GetProcess().GetTarget();
184             addr_t loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
185             if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
186                 return false;
187             // It is a location list. We just need to tell if the location
188             // list contains the current address when converted to a load
189             // address
190             return m_location.LocationListContainsAddress (loclist_base_load_addr, frame->GetFrameCodeAddress().GetLoadAddress (target));
191         }
192         else
193         {
194             // We don't have a location list, we just need to see if the block
195             // that this variable was defined in is currently
196             Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
197             if (deepest_frame_block)
198             {
199                 SymbolContext variable_sc;
200                 CalculateSymbolContext (&variable_sc);
201                 if (variable_sc.block == deepest_frame_block)
202                     return true;
203 
204                 return variable_sc.block->Contains (deepest_frame_block);
205             }
206         }
207         break;
208 
209     default:
210         assert (!"Unhandled case");
211         break;
212     }
213     return false;
214 }
215 
216