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 bool
160 Variable::LocationIsValidForFrame (StackFrame *frame)
161 {
162     // Is the variable is described by a single location?
163     if (!m_location.IsLocationList())
164     {
165         // Yes it is, the location is valid.
166         return true;
167     }
168 
169     if (frame)
170     {
171         Target *target = &frame->GetThread().GetProcess().GetTarget();
172 
173         Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
174         if (function)
175         {
176             addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
177             if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
178                 return false;
179             // It is a location list. We just need to tell if the location
180             // list contains the current address when converted to a load
181             // address
182             return m_location.LocationListContainsAddress (loclist_base_load_addr,
183                                                            frame->GetFrameCodeAddress().GetLoadAddress (target));
184         }
185     }
186     return false;
187 }
188 
189 bool
190 Variable::IsInScope (StackFrame *frame)
191 {
192     switch (m_scope)
193     {
194     case eValueTypeRegister:
195     case eValueTypeRegisterSet:
196         return frame != NULL;
197 
198     case eValueTypeConstResult:
199         return true;
200 
201     case eValueTypeVariableGlobal:
202     case eValueTypeVariableStatic:
203     case eValueTypeVariableArgument:
204     case eValueTypeVariableLocal:
205         if (frame)
206         {
207             // We don't have a location list, we just need to see if the block
208             // that this variable was defined in is currently
209             Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
210             if (deepest_frame_block)
211             {
212                 SymbolContext variable_sc;
213                 CalculateSymbolContext (&variable_sc);
214                 // Check for static or global variable defined at the compile unit
215                 // level that wasn't defined in a block
216                 if (variable_sc.block == NULL)
217                     return true;
218 
219                 if (variable_sc.block == deepest_frame_block)
220                     return true;
221                 return variable_sc.block->Contains (deepest_frame_block);
222             }
223         }
224         break;
225 
226     default:
227         break;
228     }
229     return false;
230 }
231 
232