1 //===-- ValueObjectVariable.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 
11 #include "lldb/Core/ValueObjectVariable.h"
12 
13 // C Includes
14 // C++ Includes
15 // Other libraries and framework includes
16 // Project includes
17 #include "lldb/Core/Module.h"
18 #include "lldb/Core/ValueObjectList.h"
19 #include "lldb/Core/Value.h"
20 
21 #include "lldb/Symbol/Function.h"
22 #include "lldb/Symbol/ObjectFile.h"
23 #include "lldb/Symbol/SymbolContext.h"
24 #include "lldb/Symbol/SymbolContextScope.h"
25 #include "lldb/Symbol/Type.h"
26 #include "lldb/Symbol/Variable.h"
27 
28 #include "lldb/Target/ExecutionContext.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/Target.h"
32 #include "lldb/Target/Thread.h"
33 
34 
35 using namespace lldb_private;
36 
37 lldb::ValueObjectSP
38 ValueObjectVariable::Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
39 {
40     return (new ValueObjectVariable (exe_scope, var_sp))->GetSP();
41 }
42 
43 ValueObjectVariable::ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) :
44     ValueObject(exe_scope),
45     m_variable_sp(var_sp)
46 {
47     // Do not attempt to construct one of these objects with no variable!
48     assert (m_variable_sp.get() != NULL);
49     m_name = var_sp->GetName();
50 }
51 
52 ValueObjectVariable::~ValueObjectVariable()
53 {
54 }
55 
56 lldb::clang_type_t
57 ValueObjectVariable::GetClangTypeImpl ()
58 {
59     Type *var_type = m_variable_sp->GetType();
60     if (var_type)
61         return var_type->GetClangForwardType();
62     return NULL;
63 }
64 
65 ConstString
66 ValueObjectVariable::GetTypeName()
67 {
68     Type * var_type = m_variable_sp->GetType();
69     if (var_type)
70         return var_type->GetName();
71     return ConstString();
72 }
73 
74 ConstString
75 ValueObjectVariable::GetQualifiedTypeName()
76 {
77     Type * var_type = m_variable_sp->GetType();
78     if (var_type)
79         return var_type->GetQualifiedName();
80     return ConstString();
81 }
82 
83 uint32_t
84 ValueObjectVariable::CalculateNumChildren()
85 {
86     ClangASTType type(GetClangAST(),
87                       GetClangType());
88 
89     if (!type.IsValid())
90         return 0;
91 
92     const bool omit_empty_base_classes = true;
93     return ClangASTContext::GetNumChildren(type.GetASTContext(), type.GetOpaqueQualType(), omit_empty_base_classes);
94 }
95 
96 clang::ASTContext *
97 ValueObjectVariable::GetClangASTImpl ()
98 {
99     Type *var_type = m_variable_sp->GetType();
100     if (var_type)
101         return var_type->GetClangAST();
102     return 0;
103 }
104 
105 size_t
106 ValueObjectVariable::GetByteSize()
107 {
108     ClangASTType type(GetClangAST(),
109                       GetClangType());
110 
111     if (!type.IsValid())
112         return 0;
113 
114     return (ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType()) + 7) / 8;
115 }
116 
117 lldb::ValueType
118 ValueObjectVariable::GetValueType() const
119 {
120     if (m_variable_sp)
121         return m_variable_sp->GetScope();
122     return lldb::eValueTypeInvalid;
123 }
124 
125 bool
126 ValueObjectVariable::UpdateValue ()
127 {
128     SetValueIsValid (false);
129     m_error.Clear();
130 
131     Variable *variable = m_variable_sp.get();
132     DWARFExpression &expr = variable->LocationExpression();
133 
134     if (variable->GetLocationIsConstantValueData())
135     {
136         // expr doesn't contain DWARF bytes, it contains the constant variable
137         // value bytes themselves...
138         if (expr.GetExpressionData(m_data))
139             m_value.SetContext(Value::eContextTypeVariable, variable);
140         else
141             m_error.SetErrorString ("empty constant data");
142     }
143     else
144     {
145         lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
146         ExecutionContext exe_ctx (GetExecutionContextRef());
147 
148         Target *target = exe_ctx.GetTargetPtr();
149         if (target)
150         {
151             m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
152             m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
153         }
154 
155         if (expr.IsLocationList())
156         {
157             SymbolContext sc;
158             variable->CalculateSymbolContext (&sc);
159             if (sc.function)
160                 loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
161         }
162         Value old_value(m_value);
163         if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
164         {
165             m_value.SetContext(Value::eContextTypeVariable, variable);
166 
167             Value::ValueType value_type = m_value.GetValueType();
168 
169             switch (value_type)
170             {
171                 case Value::eValueTypeFileAddress:
172                     SetAddressTypeOfChildren(eAddressTypeFile);
173                     break;
174                 case Value::eValueTypeHostAddress:
175                     SetAddressTypeOfChildren(eAddressTypeHost);
176                     break;
177                 case Value::eValueTypeLoadAddress:
178                 case Value::eValueTypeScalar:
179                     SetAddressTypeOfChildren(eAddressTypeLoad);
180                     break;
181             }
182 
183             switch (value_type)
184             {
185             default:
186                 assert(!"Unhandled expression result value kind...");
187                 break;
188 
189             case Value::eValueTypeScalar:
190                 // The variable value is in the Scalar value inside the m_value.
191                 // We can point our m_data right to it.
192                 m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule().get());
193                 break;
194 
195             case Value::eValueTypeFileAddress:
196             case Value::eValueTypeLoadAddress:
197             case Value::eValueTypeHostAddress:
198                 // The DWARF expression result was an address in the inferior
199                 // process. If this variable is an aggregate type, we just need
200                 // the address as the main value as all child variable objects
201                 // will rely upon this location and add an offset and then read
202                 // their own values as needed. If this variable is a simple
203                 // type, we read all data for it into m_data.
204                 // Make sure this type has a value before we try and read it
205 
206                 // If we have a file address, convert it to a load address if we can.
207                 Process *process = exe_ctx.GetProcessPtr();
208                 if (value_type == Value::eValueTypeFileAddress && process && process->IsAlive())
209                 {
210                     lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
211                     if (file_addr != LLDB_INVALID_ADDRESS)
212                     {
213                         SymbolContext var_sc;
214                         variable->CalculateSymbolContext(&var_sc);
215                         if (var_sc.module_sp)
216                         {
217                             ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
218                             if (objfile)
219                             {
220                                 Address so_addr(file_addr, objfile->GetSectionList());
221                                 lldb::addr_t load_addr = so_addr.GetLoadAddress (target);
222                                 if (load_addr != LLDB_INVALID_ADDRESS)
223                                 {
224                                     m_value.SetValueType(Value::eValueTypeLoadAddress);
225                                     m_value.GetScalar() = load_addr;
226                                 }
227                             }
228                         }
229                     }
230                 }
231 
232                 if (ClangASTContext::IsAggregateType (GetClangType()))
233                 {
234                     // this value object represents an aggregate type whose
235                     // children have values, but this object does not. So we
236                     // say we are changed if our location has changed.
237                     SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
238                 }
239                 else
240                 {
241                     // Copy the Value and set the context to use our Variable
242                     // so it can extract read its value into m_data appropriately
243                     Value value(m_value);
244                     value.SetContext(Value::eContextTypeVariable, variable);
245                     m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0, GetModule().get());
246                 }
247                 break;
248             }
249 
250             SetValueIsValid (m_error.Success());
251         }
252     }
253     return m_error.Success();
254 }
255 
256 
257 
258 bool
259 ValueObjectVariable::IsInScope ()
260 {
261     const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef();
262     if (exe_ctx_ref.HasFrameRef())
263     {
264         ExecutionContext exe_ctx (exe_ctx_ref);
265         StackFrame *frame = exe_ctx.GetFramePtr();
266         if (frame)
267         {
268             return m_variable_sp->IsInScope (frame);
269         }
270         else
271         {
272             // This ValueObject had a frame at one time, but now we
273             // can't locate it, so return false since we probably aren't
274             // in scope.
275             return false;
276         }
277     }
278     // We have a variable that wasn't tied to a frame, which
279     // means it is a global and is always in scope.
280     return true;
281 
282 }
283 
284 lldb::ModuleSP
285 ValueObjectVariable::GetModule()
286 {
287     if (m_variable_sp)
288     {
289         SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope();
290         if (sc_scope)
291         {
292             return sc_scope->CalculateSymbolContextModule();
293         }
294     }
295     return lldb::ModuleSP();
296 }
297 
298 SymbolContextScope *
299 ValueObjectVariable::GetSymbolContextScope()
300 {
301     if (m_variable_sp)
302         return m_variable_sp->GetSymbolContextScope();
303     return NULL;
304 }
305 
306 bool
307 ValueObjectVariable::GetDeclaration (Declaration &decl)
308 {
309     if (m_variable_sp)
310     {
311         decl = m_variable_sp->GetDeclaration();
312         return true;
313     }
314     return false;
315 }
316